CPU Register File 2R1W
Standard RISC architectures require reading two operands combinationally in the decode stage while writing back a result from the writeback stage. The register file is the central storage structure bridging instruction execution and persistent data state.
The solution module maintains an array of 32 registers, each 32 bits wide. It provides two independent read ports and one write port. Register 0 is hardwired to zero; any write to address 0 is ignored, and any read from address 0 always returns zero. The read ports continuously output the data stored at the requested addresses. The write port updates the requested address with the provided data when the write enable signal is asserted.
Timing and reset rules: • Clock edge: posedge clk • Reset type: Asynchronous • Reset polarity: Active-low (rst_n) • Output values on reset: All 32 registers are cleared to 32'b0 • Read behavior: Strictly combinational. rd_data1 and rd_data2 must reflect the contents of the registers at rd_addr1 and rd_addr2 continuously, without waiting for a clock edge. • Write behavior: Synchronous. When we is 1, the register at wr_addr is updated on the positive edge of clk. • Read-during-write priority: Because reads are combinational, reading the same address currently being written will yield the old value before the clock edge, and the new value immediately after the clock edge.
Worked Trace: • Cycle 1: rst_n=0 → All registers cleared. Reading address 5 returns 0. • Cycle 2: rst_n=1, we=1, wr_addr=5, wr_data=32'hA, rd_addr1=5 → Before the clock edge, rd_data1 outputs 0 (old value). • Cycle 3: rst_n=1, we=0, rd_addr1=5 → After the clock edge, rd_data1 outputs 32'hA (new value).
{ "signal": [
{ "name": "clk", "wave": "p..." },
{ "name": "rst_n", "wave": "01.." },
{ "name": "we", "wave": "010." },
{ "name": "wr_addr", "wave": "x=x.", "data": ["5"] },
{ "name": "wr_data", "wave": "x=x.", "data": ["A"] },
{ "name": "rd_addr1", "wave": "====", "data": ["5", "5", "5", "5"] },
{ "name": "rd_data1", "wave": "====", "data": ["0", "0", "A", "A"] }
], "head": { "text": "Combinational read shows old value during the write cycle, and new value in the next cycle." } }| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered clock | | rst_n | input | 1 | Asynchronous active-low reset; clears all registers to 0 | | we | input | 1 | Write enable; synchronous active-high | | rd_addr1 | input | 5 | Read address for port 1 | | rd_addr2 | input | 5 | Read address for port 2 | | wr_addr | input | 5 | Write address | | wr_data | input | 32 | Data to write | | rd_data1 | output | 32 | Data read from port 1 (combinational) | | rd_data2 | output | 32 | Data read from port 2 (combinational) |
Constraints
- The module must handle exactly 32 registers, each 32 bits wide.
- Register 0 must always read as 0, regardless of any writes to it.
- Reads must be combinational (asynchronous).
- Writes must be synchronous to the positive edge of
clk. - All registers must be cleared to 0 asynchronously when
rst_nis 0.
Topics
Solve this problem
Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.
This problem is part of Codiode Pro. The statement above is free to read.
The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.