AMBA AXI · Module 16
AXI Scoreboards
Build an AXI scoreboard that checks data integrity and ordering by comparing the monitor's reconstructed transactions against a reference model — a memory model for write/read data, per-ID expected-response queues for ordering, and the predict-then-compare loop that turns protocol-legal traffic into a verdict on functional correctness.
Assertions prove the traffic is legal; the scoreboard proves the design does the right thing. Fed by the monitor's reconstructed transactions (16.3), a scoreboard maintains a reference model of expected behavior — most often a memory model — and for every transaction it predicts the correct result and compares it against what the DUT actually did. This is where data integrity (does a read return what was last written?) and ordering (do same-ID responses come back in order?) are actually checked — the compliance-vs-correctness split the mindset chapter (16.1) insisted on. This chapter builds the scoreboard: the predict-then-compare loop, the memory reference model, per-ID expected-response queues for ordering, and the end-of-test checks that catch the transactions that never completed.
1. Predict, Then Compare
A scoreboard's core is a two-step loop driven by the monitor's analysis export: predict the expected outcome of each transaction from a reference model, then compare the DUT's actual outcome against the prediction, flagging any mismatch. For a memory-mapped slave the reference is a model of memory: a write updates the model; a read is predicted by reading the model and compared against the returned data.
2. The Memory Reference Model and Data-Integrity Check
For a memory or register slave, the reference model is an associative array indexed by address. A write transaction updates the model byte-by-byte under WSTRB (so the model mirrors the slave's strobe behavior); a read transaction is checked by comparing each returned beat against the model's current contents at that beat's address.
class axi_scoreboard extends uvm_component;
byte mem [axi_addr_t]; // reference memory model
// Write: update the model exactly as the slave should (WSTRB-masked)
function void on_write(axi_txn t);
axi_addr_t a = t.addr;
foreach (t.data[beat]) begin
for (int b = 0; b < BYTES; b++)
if (t.strb[beat][b]) mem[a + beat*BYTES + b] = t.data[beat][b*8 +: 8];
end
endfunction
// Read: predict from the model, compare against the DUT's returned data
function void on_read(axi_txn t);
axi_addr_t a = t.addr;
foreach (t.data[beat]) begin
for (int b = 0; b < BYTES; b++) begin
byte exp = mem.exists(a + beat*BYTES + b) ? mem[a + beat*BYTES + b] : 8'hXX;
byte got = t.data[beat][b*8 +: 8];
if (mem.exists(a + beat*BYTES + b) && exp !== got)
`uvm_error("SB", $sformatf("Read mismatch @%0h: exp %0h got %0h",
a+beat*BYTES+b, exp, got))
end
end
endfunction
endclassThe byte-level, WSTRB-aware update is what makes the data-integrity check trustworthy: a read after a partial-word write must return the merged result, and the model only gets that right if it applies strobes exactly as the slave does.
3. Ordering Checks with Per-ID Queues
Data integrity is only half the job; the scoreboard also checks ordering. AXI's rule is that responses for the same ID must return in the order their requests were issued, while different IDs may complete in any order. The scoreboard models this with per-ID queues: when a request is observed it's pushed onto that ID's expected queue; when a response arrives it must match the head of the corresponding ID's queue (in-order), but no ordering is enforced across different IDs.
// Per-ID expected-response queues
axi_txn exp_q [int][$]; // exp_q[id] is a queue of outstanding txns
function void on_request(axi_txn t); // push when request observed
exp_q[t.id].push_back(t);
endfunction
function void on_response(axi_txn r); // must match head of its ID's queue
if (exp_q[r.id].size() == 0)
`uvm_error("SB", $sformatf("Response for id %0d with no outstanding request", r.id))
else begin
axi_txn expected = exp_q[r.id].pop_front(); // in-order within ID
if (r.addr !== expected.addr)
`uvm_error("SB", $sformatf("Out-of-order/mismatched response for id %0d", r.id))
end
endfunction4. End-of-Test Checks: The Transactions That Never Came
A scoreboard must also check what didn't happen. At end of test, any non-empty per-ID queue means a request was issued but never got its response — a dropped or hung transaction the per-transaction checks can't catch (they only fire when a response arrives). The check_phase sweeps every queue and errors on leftovers.
function void check_phase(uvm_phase phase);
foreach (exp_q[id])
if (exp_q[id].size() != 0)
`uvm_error("SB", $sformatf("%0d transactions for id %0d never completed",
exp_q[id].size(), id))
endfunction5. Common Misconceptions
6. Debugging Insight
7. Verification Insight
8. Interview Questions
9. Summary
An AXI scoreboard decides functional correctness, complementing the assertions that decide compliance. Fed by the monitor's reconstructed transactions, it runs a predict-then-compare loop against an independent reference model: for a memory/register slave, a write updates the model byte-by-byte under WSTRB, and a read is predicted from the model and compared against the DUT's returned data — making write-then-read to the same address the canonical data-integrity check (and requiring the model to mirror the slave's byte-level semantics exactly). Ordering is checked with per-ID queues that enforce AXI's rule — same-ID responses in request order, different-ID responses in any order — where a response must match the head of its ID's queue. End-of-test checks sweep the queues so dropped or hung transactions (which per-response comparison can't see) are caught as leftover entries.
The scoreboard's soundness rests on an independent model (spec-derived, never peeking at the DUT — often a RAL), per-ID ordering semantics (not global), and completeness checking at end of test. It sits in a layered stack: assertions for signal-local legality, the (separately verified) monitor for transaction reconstruction, the scoreboard for correctness/ordering, and coverage to confirm the scenarios were exercised — together answering the four distinct verification questions. A mismatch is symmetric (model and DUT disagree), so debugging always rules out the model first. Next, we measure whether the traffic actually exercised the bursts, IDs, responses, and corners that make these checks meaningful — functional coverage.
10. What Comes Next
You can now judge correctness; next we measure whether the right scenarios were tested:
- 16.5 — AXI Functional Coverage (coming next) — defining coverage for burst types/lengths, IDs, responses, and protocol corners, so a clean scoreboard run is backed by evidence the interesting cases were exercised.
Previous: 16.3 — AXI Monitors. Related: 8.3 — Same-ID Ordering and 8.4 — Different-ID Ordering for the ordering model the scoreboard enforces, and 10.5 — AXI4-Lite Verification Checklist for the register-model (RAL) reference.