R5.1.1 Two reads and a write

EasyImplementIcarus Verilog + Yosys · serverReview the topic

Design a small register file with one write port and two combinational read ports that show the new word when it is read in the cycle it is written.

Hardware context: A 16 x 8 register file with one write port and two combinational read ports for a small processor. Design the two-read, one-write register file with write-first reads.

A small processor reads two operands and writes one result in every cycle. Its register file is 16 words of 8 bits, small enough to build from flops, with one write port and two read ports (lesson R5.1). The pipeline reads a register in the same cycle an older instruction writes it, so the brief asks for write-first reads: the read shows the word being written, not the old one.

Brief: parameters DEPTH (2 to 16, a power of two) and WIDTH (1 to 16); ports clk and rst_n (asynchronous, active-low), we, waddr, wdata, raddr_a, raddr_b in, rdata_a and rdata_b out. A write lands at the rising edge when we is 1. Both reads are combinational: rdata follows its address in the same cycle. When we is 1 and a read address equals waddr, that port shows wdata. Reset clears every word to 0. Corner cases: both ports on the address being written, a matching address while we is 0, a word written twice. The tests run copies with DEPTH 16 and 8. Synthesis check: the design must build on the site's synthesis flow with no latch. The cell and level counts come from an open-source flow and are a proxy for area and depth, not a foundry result.

Signals in the timeline

SignalWidthRole
sel1input of each check
writes104input of each check
reads105input of each check
Full specification
The module you write (keep the name, the parameters and the ports)
module regfile2r #(parameter int DEPTH = 16, parameter int WIDTH = 8) (
  input  logic                     clk,
  input  logic                     rst_n,      // asynchronous, active-low
  input  logic                     we,
  input  logic [$clog2(DEPTH)-1:0] waddr,
  input  logic [WIDTH-1:0]         wdata,
  input  logic [$clog2(DEPTH)-1:0] raddr_a,
  output logic [WIDTH-1:0]         rdata_a,
  input  logic [$clog2(DEPTH)-1:0] raddr_b,
  output logic [WIDTH-1:0]         rdata_b
);
  // your design
endmodule
In the cyclerdata_a (rdata_b the same with raddr_b)
we = 1 and waddr = raddr_awdata: the word being written
otherwisethe word at raddr_a: the last value written there, or 0 since reset
rst_n = 0 (at any time)every word is 0 at once

The tests reset the file, apply up to eight writes, then run five cycles in which a write may happen while both ports read. Both ports are sampled 1 ns before each of those five edges: c0_rdata_a and c0_rdata_b to c4_rdata_a and c4_rdata_b.

Examples

Example 1

Four words, two ports
Input
DEPTH 16. Writes: 3<-3c, 9<-99, 12<-c5, 15<-f0. Then: no write, read 3 and 9; no write, read 12 and 15; no write, read 15 and 3; no write, read 0 and 12; no write, read 9 and 9
Output
c0_rdata_a = 0x3c, c0_rdata_b = 0x99, c1_rdata_a = 0xc5, c1_rdata_b = 0xf0, c2_rdata_a = 0xf0, c2_rdata_b = 0x3c, c3_rdata_a = 0x0, c3_rdata_b = 0xc5, c4_rdata_a = 0x99, c4_rdata_b = 0x99

Words 3, 9, 12 and 15 hold what was written; word 0 was never written and reads 00 after reset. Both ports may read the same word in one cycle.

Example 2

Read the word being written
Input
DEPTH 16. Writes: 5<-55, 6<-66. Then: no write, read 5 and 6; write 5<-a5, read 5 and 6; no write, read 5 and 6; write 6<-b6, read 2 and 6; write 2<-22, read 6 and 2
Output
c0_rdata_a = 0x55, c0_rdata_b = 0x66, c1_rdata_a = 0xa5, c1_rdata_b = 0x66, c2_rdata_a = 0xa5, c2_rdata_b = 0x66, c3_rdata_a = 0x0, c3_rdata_b = 0xb6, c4_rdata_a = 0xb6, c4_rdata_b = 0x22

In cycle 1 word 5 is written with a5 while port A reads it: port A shows a5 at once, and a5 stays in later cycles. In cycles 3 and 4 port B reads the word being written (6, then 2) and forwards it, while port A reads stored words.

Example 3

A matching address with we low
Input
DEPTH 16. Writes: 4<-44, 8<-88. Then: no write, read 8 and 4; we 0 (4, ee), read 4 and 8; we 0 (8, 11), read 8 and 4; write 4<-4f, read 4 and 8; we 0 (4, 00), read 4 and 8
Output
c0_rdata_a = 0x88, c0_rdata_b = 0x44, c1_rdata_a = 0x44, c1_rdata_b = 0x88, c2_rdata_a = 0x88, c2_rdata_b = 0x44, c3_rdata_a = 0x4f, c3_rdata_b = 0x88, c4_rdata_a = 0x4f, c4_rdata_b = 0x88

In cycles 1 and 2 waddr and wdata change but we is 0, so nothing is written and nothing is forwarded: the ports show the stored 44 and 88. In cycle 3 port A forwards 4f as it is written; in cycle 4, with we 0 again, it shows the stored 4f, not the 00 on wdata.

Constraints and contract

  • Inputs change 1 ns after an edge and are known 0/1 values; addresses are below DEPTH.
  • Keep the module name, the parameters and the ports.

Hints

Hint 1

The storage is an unpacked array of DEPTH words. Which block writes it, and what does that block do while rst_n is 0?

Hint 2

Each read port is one continuous assignment from its address. What must it show when the same word is being written in this cycle?

Hint 3

The new word is on wdata before the edge, while the array still holds the old one. A compare of waddr with the read address, taken only when we is 1, picks between them.

What the grader checks: Eight directed and eight seeded scripts run on copies with DEPTH 16 and 8 (WIDTH 8): up to eight writes, then five cycles that mix writes with reads on both ports, sampled before every edge and compared with an independent model of the brief. Other DEPTH and WIDTH values follow the same code but are not simulated. The synthesis check adds the latch count.

The submitted design must synthesize with 0 latches and no combinational loop. Counts come from the pinned open-source synthesis flow. They are proxies for logic size and depth, not physical area or timing.

16 checks on Icarus Verilog + Yosys · server. Run the examples first, then check the full regression. The suite is local and inspectable. A passing result establishes the tested cases, not a proof for all possible inputs.

See all 1 steps and the final capstone
Your code SystemVerilogSaved locally
Ln 1, Col 1Tab indents · Ctrl/⌘ + Enter runs samples
Not run yet

Four words, two ports

Input
DEPTH 16. Writes: 3<-3c, 9<-99, 12<-c5, 15<-f0. Then: no write, read 3 and 9; no write, read 12 and 15; no write, read 15 and 3; no write, read 0 and 12; no write, read 9 and 9
Expected output
c0_rdata_a = 0x3c, c0_rdata_b = 0x99, c1_rdata_a = 0xc5, c1_rdata_b = 0xf0, c2_rdata_a = 0xf0, c2_rdata_b = 0x3c, c3_rdata_a = 0x0, c3_rdata_b = 0xc5, c4_rdata_a = 0x99, c4_rdata_b = 0x99

Words 3, 9, 12 and 15 hold what was written; word 0 was never written and reads 00 after reset. Both ports may read the same word in one cycle.

Run samples executes all 3 example checks. Check all tests runs 16 checks.

Icarus Verilog + Yosys · server