ooo_memctl is a 16-word memory behind two request ports and one response port. Each request port carries a 2-bit ID, so there are eight ordering domains, one per {port, id}. Reads are held in an 8-entry table. Each read waits a pseudo-random 0 to 7 cycles before it may leave, and never leaves before an older read on its own ID; a ninth read can wait in the response register. The Part 8 FIFO capstone had one stream and a total order. This one has eight streams and a partial order, which is what changes the checking.
Interface | Signals | Driven by |
|---|---|---|
Request port 0 and 1 | valid, write, id[1:0], addr[3:0] (word), wdata[31:0], wstrb[3:0] | Testbench |
ready | Controller | |
Response port | valid, port, id[1:0], data[31:0] | Controller |
ready | Testbench | |
Global | clk, rst_n (asynchronous, active low) | Testbench |
Rule | Statement |
|---|---|
R1 | Read responses on the same {port, id} return in request order. |
R2 | Responses on different {port, id} may return in any order. |
R3 | A write applies its byte strobes when it is accepted. Writes are posted: they produce no response. A read returns the memory contents at the moment it was accepted. |
R4 | valid/ready on every port. A stalled response holds its payload. A request is accepted only when the read table has a free entry. |
R5 | Reset drops every outstanding read: no response is ever sent for it. Memory contents survive reset. |
R6 | When both ports request in the same cycle, acceptance alternates (round-robin). At most one request is accepted per cycle. |
R3 sets the ordering point. Because read data is fixed at acceptance, the reference model is updated on write acceptance and snapshotted on read acceptance, exactly as in the memory-model lesson. R5 tells the scoreboard what to do on reset: forget outstanding reads, keep the memory model. Writing these down before any code is what lets the checkers be exact.
Rank features by how likely a bug is and how bad an escape would be. Likelihood comes from complexity and from how hard the state is to reach; impact comes from what software sees.
Feature | Likelihood | Impact | Rank | Why |
|---|---|---|---|---|
Per-ID ordering with a shared table | High | High | 1 | Ordering state is spread over the table and per-ID counters |
Reset with reads in flight | High | High | 2 | Rarely reached by random traffic; state that survives reset is a classic bug |
Table full and response stalls | Medium | High | 3 | Last entry, allocation and release in one cycle |
Byte strobes per port | Medium | High | 4 | Silent data corruption |
Arbitration fairness | Medium | Medium | 5 | Starvation looks like low performance, not a failure |
Response ID and duplicate control | Low | High | 6 | A wrong ID corrupts another transaction's data |
Each row names its stimulus, the checker that judges it, the coverage that proves it was exercised, and what "done" means. A row without a checker is a hope; a row without coverage cannot be closed.
Row | Feature | Stimulus | Checker | Coverage | Done when |
|---|---|---|---|---|---|
P1 | R1, R2 ordering | Same-ID bursts, random latency | ID scoreboard | CV2 same-ID depth, CV3 cross-ID overtake | 0 mismatches; CV2 and CV3 at goal |
P2 | R3 strobes | Partial writes on both ports, reads of hot words | Memory model through the scoreboard | CV4 lane x port, CV5 read-after-write | All 8 lane bins and CV5 at goal |
P3 | R4 back-pressure | Response ready 25-70% | a_rsp_stable, drain | CV1 depth bins, CV1b entry 7, CV6 stalls | Table found full at least 3 times |
P4 | R5 reset | Reset in the middle of a stalled phase | Scoreboard flush, watchdog, drain | CV8 reset busy, CV9 ID reuse after reset | Both hit; nothing leaks after reset |
P5 | R6 fairness | Both ports back to back | a_fair (two assertions) | CV7 wins per port | No assertion failure; both ports win |
P6 | Checker quality | Six planted bugs | Each must fail the bench | n/a | Every bug caught; table recorded |
It fixes when expected read data is computed. If read data were fixed at response time, a write accepted between a read and its response would change the expected value, and the model would need to snapshot at a different point. Getting the ordering point wrong produces false failures or hides real ones.
Random traffic almost never asserts reset, so the state is unreachable unless a test does it on purpose, and state that wrongly survives reset corrupts behaviour long after. Table-full is reached naturally under heavy back-pressure.