Skip to content

rtl/register_file.sv — 32×32 Register File

The RV32 integer register file: 31 physical 32-bit registers (x1x31), with x0 hardwired to zero and never stored. Synchronous write, asynchronous read with same-cycle write-then-read bypass forwarding.

Where it fits

Instantiated once by riscv_core.sv as rf_unit, read in ID (rs1/rs2) and written in WB (rd/wd). Testbenches reach it directly for register assertions via the hierarchical path dut.cpu_chiplet_inst.cpu_core_inst.rf_unit.rf[i].

Ports

Direction Name Width Description
in clk 1 Clock
in reg_write 1 Write enable (from WB stage)
in rs1, rs2 5, 5 Read register indices
in rd 5 Write register index
in wd 32 Write data
out rd_data1, rd_data2 32, 32 Read data for rs1/rs2

Functionality

Storage is logic [31:0] rf [31:1] — index 0 is never allocated; both read ports return 32'b0 unconditionally when the requested index is 0.

Bypass forwarding: if the same cycle writes rd and reads that same index (reg_write && rd == rs1), the read port returns wd directly instead of the pre-write rf[rs1] value — i.e. write-then-read same-cycle semantics, avoiding a structural hazard that would otherwise need an extra forwarding path in riscv_core.sv.

Write: synchronous, posedge clk, gated on reg_write && rd != 0.

Example

cycle N:   reg_write=1, rd=x9, wd=42, rs1=x9  (WB writing x9, ID reading x9 same cycle)
           rd_data1 = 42                       (bypass — not the stale rf[9])
cycle N+1: rf[9] = 42                          (committed to storage)
           rd_data1 (if rs1=x9 again) = rf[9] = 42