rv32g-core

Pipelined, synthesizable, and fabricable RISC-V core in SystemVerilog+Yosys+OpenROAD
Log | Files | Refs | LICENSE

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:
M.gitignore | 3+++
MMakefile | 8+++++---
Artl/rv32g_hart_top.cst | 8++++++++
Artl/rv32g_hart_top.sv | 31+++++++++++++++++++++++++++++++
Mrtl/tb_rv32g.sv | 4++--
Mrtl/unified_memory.sv | 4+++-
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