The requester only holds its request until the handshake. After the accept it may present the next request or leave garbage on the bus.
The controller copies req_we, req_addr and req_wdata into we_r, addr_r and wdata_r at the accept edge. It drives the RAM only from those copies.
IDLE: if (req_valid) begin
we_r <= req_we; addr_r <= req_addr; wdata_r <= req_wdata; // copy at accept
state <= ACCESS;
end
...
assign mem_addr = addr_r; // never req_addr
assign mem_wdata = wdata_r; // never req_wdataEach change below breaks the controller in one place. The table shows what a value-only scoreboard saw (AW=6, DW=8, LAT=2).
Change | What the scoreboard saw |
|---|---|
| Fails: a read returned 0x00 where 0x9e was expected. The RAM was addressed with the next request's address. |
| Fails: a read returned 0x63 where 0x9e was expected. A write stored the next request's data. |
| Fails: a read returned 0x31 where 0x00 was expected. A read accepted as a read was executed as a write, or the reverse. |
Read goes straight to RESP, skipping WAIT (data taken one cycle early) | Fails: data from the previous access was returned. |
WAIT exit uses | A value-only check passes after a longer wait: data stays stable. The exact-edge check must fail. For LAT >= 3, ==2 can instead shorten the wait; this is not a universal slow mutation. |
A correct but slower design can be invisible to a value-only scoreboard. The bench therefore also requires response consumption exactly LAT + 1 edges after acceptance, independently of data matching.
Item | Cost |
|---|---|
we_r + addr_r + wdata_r | 1 + AW + DW flip-flops (15 for this 6-bit address, 8-bit data controller) |
Benefit | Requester can pipeline its next request; outputs to the RAM come straight from registers (clean timing) |
Different interface alternative | Require fields to remain stable through read-response consumption or through write commit (explicit write_done, or a documented return of ready after ACCESS). This is incompatible with the current accept-edge release contract and creates a longer requester-to-RAM timing path. Waiting for rsp_valid on a write would hang. |
At the edge where req_valid && req_ready is true (IDLE with a valid request). That is the last moment the requester is obliged to hold them, so copying earlier is impossible and copying later is unsafe.
The mutation results in the table are value-only observations for AW=6, DW=8, LAT=2 from an earlier version of the bench. They have not been rerun against the current bench.
The current bench, which requires response consumption exactly LAT + 1 edges after acceptance, passes with Icarus Verilog 13.0 (2026-10-16).