commit 7bf7051954fa3b626c579b331b72f0078c6c8691
parent 79c6c61d54ef8b96ed8395845ac1d08e84f9c304
Author: Vineet Kumar <git@vineetk.net>
Date: Wed, 10 Jun 2026 20:44:38 -0400
make fpga temp. top module and add dmem_valid output to unified_memory
currently getting in nextpnr 17 MHz (before routing optimization?) and then ~25 MHz (after its
auto-optimization?)
Diffstat:
6 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,3 +1,6 @@
#*
obj_dir
tests/.test_list
+design.json
+design_pnr.json
+*.rpt
diff --git a/Makefile b/Makefile
@@ -4,6 +4,7 @@ OBJDIR := obj_dir
PKG_SRC := ${SRCDIR}/rv32g_pkg.sv
TB_SRC := ${SRCDIR}/tb_rv32g.sv
SV_SRCS := ${SRCDIR}/rv32g_hart.sv ${wildcard ${SRCDIR}/stage_*.sv} ${SRCDIR}/unified_memory.sv
+TOP_SRC := ${SRCDIR}/rv32g_hart_top.sv
# tests
TEST_DIR := tests/riscv-tests/isa
@@ -20,11 +21,12 @@ all: lint synth
lint: $(PKG_SRC) $(SV_SRCS)
verilator --lint-only --timing \
+1800-2023ext+.sv \
- --top tb_rv32g \
- $(PKG_SRC) $(TB_SRC) $(SV_SRCS)
+ --top rv32g_hart_top \
+ $(PKG_SRC) $(TB_SRC) $(SV_SRCS) $(TOP_SRC)
+# --top tb_rv32g \
synth:
- yosys -m slang -p 'read_slang $(PKG_SRC) $(SV_SRCS); synth_gowin -top rv32g_hart'
+ yosys -m slang -p 'read_slang $(PKG_SRC) $(SV_SRCS) $(TOP_SRC); synth_gowin -family gw5a -top rv32g_hart_top -json design.json'
sim_compile: lint $(PKG_SRC) $(TB_SRC) $(SV_SRCS)
verilator --binary --exe --build --timing \
diff --git a/rtl/rv32g_hart_top.cst b/rtl/rv32g_hart_top.cst
@@ -0,0 +1,8 @@
+IO_LOC "clk" V22;
+IO_PORT "clk" IO_TYPE=LVCMOS33 PULL_MODE=NONE BANK_VCCIO=3.3;
+IO_LOC "rstN" E3;
+IO_PORT "rstN" IO_TYPE=LVCMOS33;
+IO_LOC "exception[0]" AB10;
+IO_PORT "exception[0]" IO_TYPE=LVCMOS33;
+IO_LOC "exception[1]" AB11;
+IO_PORT "exception[1]" IO_TYPE=LVCMOS33;
diff --git a/rtl/rv32g_hart_top.sv b/rtl/rv32g_hart_top.sv
@@ -0,0 +1,31 @@
+module rv32g_hart_top
+ import rv32g_pkg::*;
+ ( input logic clk,
+ input logic rstN,
+ output exception_t exception
+ );
+
+ // Wires connecting memory and core
+ logic [31:0] imem_addr;
+ logic [31:0] imem_data;
+ logic imem_valid;
+ logic [31:0] dmem_addr;
+ logic dmem_we;
+ logic [3:0] dmem_be;
+ logic [31:0] dmem_rdata;
+ logic [31:0] dmem_wdata;
+ logic dmem_valid; // now driven by memory
+
+ // Instantiate unified memory (modified to output dmem_valid)
+ unified_memory u_mem (.clk, .imem_addr, .imem_data, .imem_valid,
+ .dmem_addr, .dmem_we, .dmem_be,
+ .dmem_wdata, .dmem_rdata, .dmem_valid);
+
+ // Instantiate the core
+ rv32g_hart dut (.clk, .rstN, .exception,
+ .imem_addr, .imem_data, .imem_valid,
+ .dmem_addr, .dmem_valid,
+ .dmem_rdata, .dmem_wdata,
+ .dmem_we, .dmem_be);
+
+endmodule : rv32g_hart_top
diff --git a/rtl/tb_rv32g.sv b/rtl/tb_rv32g.sv
@@ -54,14 +54,14 @@ module tb_rv32g
// negedge clk instead of posedge clk to avoid race-condition
// prints the current cycle going into the hart
- always @(negedge clk or posedge rstN) begin
+ always_ff @(negedge clk or posedge rstN) begin
if (!rstN) cycle_cnt <= 0;
else cycle_cnt <= cycle_cnt + 1;
$display("Cycle: %d", cycle_cnt);
end
unified_memory u_mem (.clk, .imem_addr, .imem_data, .imem_valid,
- .dmem_addr, .dmem_we, .dmem_be,
+ .dmem_addr, .dmem_we, .dmem_be, .dmem_valid,
.dmem_wdata, .dmem_rdata);
rv32g_hart dut(.clk, .rstN, .exception,
diff --git a/rtl/unified_memory.sv b/rtl/unified_memory.sv
@@ -12,7 +12,8 @@ module unified_memory
input logic dmem_we,
input logic [3:0] dmem_be,
input logic [31:0] dmem_wdata,
- output logic [31:0] dmem_rdata);
+ output logic [31:0] dmem_rdata,
+ output logic dmem_valid);
logic [31:0] mem [0:CACHE_DEPTH-1];
logic [31:0] imem_idx, dmem_idx;
@@ -30,6 +31,7 @@ module unified_memory
// single-cycle hart requires combinational same-cycle read.
// otherwise it causes tests like rv32ui-p-fence_i to fail.
dmem_rdata = (dmem_idx < CACHE_DEPTH) ? mem[dmem_idx] : '0;
+ dmem_valid = (dmem_idx < CACHE_DEPTH) ? 1'b1 : 1'b0;
end
always_ff @(posedge clk) begin