Skip to main content...
S2 · Verilog RTL Design
30 min

Day 64: Building block: the 2R1W register file

The register file feeds every instruction. Its 2R1W structure and the x0 special case are exactly the paper design, now in RTL.

Building block: the 2R1W register file

The register file stores x0x31 with two combinational read ports and one clocked write port (Stage 1, Day 40). In RTL it's a small memory array with two asynchronous reads and a synchronous write — plus the critical `x0` special case: reads of index 0 return 0, and writes to index 0 are ignored.

A 32×32 2R1W register file with x0 hard-wired to zero
module regfile (
    input         clk,
    input  [4:0]  ra1, ra2, wa,
    input  [31:0] wd,
    input         we,
    output [31:0] rd1, rd2
);
    reg [31:0] regs [1:31];        // index 0 not stored — it is always zero

    assign rd1 = (ra1 == 5'd0) ? 32'd0 : regs[ra1];
    assign rd2 = (ra2 == 5'd0) ? 32'd0 : regs[ra2];

    always @(posedge clk)
        if (we && wa != 5'd0)      // never write x0
            regs[wa] <= wd;
endmodule

Write-first for the pipeline

In the pipelined core, WB writes a register in the same cycle ID reads it. A common convention is a write-first / internal-forwarding register file (write in the first half-cycle, read the new value in the second) so a register written in WB is visible to a dependent instruction in ID — reducing forwarding cases. Note the choice now; it matters when you pipeline (Day 87).

Ship for Day 64

In the register file RTL, why guard the write with (wa != 5'd0)?

We use cookies

We use cookies to enhance your browsing experience, serve personalized content, and analyze our traffic. By clicking "Accept All", you consent to our use of cookies. Learn more

    Day 64: Building block: the 2R1W register file | RBTechIconX