Wishbone · Module 26
Scoreboards
Zero protocol violations and wrong data on four of nine reads. Only an independent prediction catches it — and a DUT bug and a testbench bug produce the identical symptom.
Chapter 26.2 established that the bus was legal. Chapter 26.3 established what happened. Neither has said whether it was right.
// ── THE QUESTION IT ANSWERS ─────────────────────────────────────────────
// Not "was the bus legal" - the protocol checker owns that. Not "what
// happened" - the monitor owns that. This module asks:
//
// WAS THE OBSERVED RESULT THE CORRECT RESULT?1. The Defect No Checker Can See
WRONG_READ_DATA corrupts the returned word and touches no bus signal:
rig SPEC fails mon txns sb data mm sb all
correct 0 9 0 0
WRONG_READ_DATA 0 9 4 4 -> ZERO PROTOCOL FAILURES. 4 DATA MISMATCHES.
The monitor observed the same 9 transactions in
both rigs, at the same clocks, with the same
addresses and the same termination classes.
Everything about HOW the transfer was conducted
is identical. Only WHAT came back differs.B3 says WHEN
[DAT_O()]is valid — RULE 3.65 — and never what it should CONTAIN. There is no protocol rule to break, so there is no protocol checker that can help. This is the general case of Module 25's DMA result, and it is why a scoreboard is a separate layer rather than a stronger assertion.
The first version of this defect proved the opposite
An earlier WRONG_READ_DATA corrupted the bus unconditionally, including while no termination was asserted — and the RULE 3.65 property duly caught it:
// The corruption is applied ONLY while the data is QUALIFIED. The
// first version corrupted it unconditionally, which meant the bus
// carried a non-zero value with no termination asserted - and that IS
// a RULE 3.65 violation, which a protocol checker duly caught. The
// defect then proved the opposite of its point.A negative control that fires the wrong detector is not evidence of anything except that the defect was mis-specified.
2. Independence Is The Whole Design
// ── THE INDEPENDENCE RULE ───────────────────────────────────────────────
// This module reads NOTHING from inside the DUT. Not its register array,
// not its decoded index, not its termination decision, not a helper
// signal it kindly exports. Its only inputs are:
//
// the STIMULUS the testbench issued, and
// an independently written model of what that stimulus should mean.
//
// A scoreboard whose expected value came from the DUT is asking the
// suspect to write its own alibi. Module 25 made that point about a DMA;
// here it is architecture.And independence goes further than not reading DUT signals — it extends to how the model is written:
// The address map, the access policies, and the byte-lane semantics are
// re-implemented here from the SPECIFICATION OF INTENT, not copied from
// wb_slave_top. If both were derived from the same source a shared
// misunderstanding would cancel out and the scoreboard would agree with
// a wrong design.But independent does not mean guessed
The first version of this reference model assumed the register slave was word-indexed. It is not:
// The first version of this model assumed ADR_I[5:2] - word-indexed,
// four bytes per register - and the scoreboard reported two mismatches
// on a CORRECT design. INDEPENDENT DOES NOT MEAN GUESSED: a reference
// model must be written from the interface contract, not from an
// assumption about what the contract probably says.Two mismatches on a correct design, caused entirely by the model. Which is the subject of §6.
3. When State Updates
// ── WHEN STATE UPDATES ──────────────────────────────────────────────────
// At the ARCHITECTURAL COMMIT, which is an accepted write - never when a
// request merely appears. BROKEN_REF_UPDATE moves it to issue time, which
// is a REFERENCE MODEL bug, not a DUT bug, and the module keeps it as a
// named defect precisely because verification code is software too. logic apply;
assign apply = BROKEN_REF_UPDATE ? issue_i : commit_i;This is the same commit-versus-presentation distinction that Chapter 23.3, Chapter 24.2 and Chapter 25.1 each found on the design side. Here it appears in the verification code, which is the point of §6.
4. A Retry Does Not Consume A Prediction
// ── ATTEMPTS, AND WHY RTY DOES NOT CONSUME A PREDICTION ─────────────────
// A RTY attempt moved nothing. B3's [RTY_I] description: "the interface
// is not ready... the bus cycle should be retried at a later time."
//
// So a RTY observation is COUNTED but does not pop the expected entry:
// the intended operation has not happened yet and is still owed. Merging
// a RTY with its later retry would hide an engine that retries forever;
// popping on a RTY would desynchronise the comparison permanently.
//
// THAT IS A LOCAL VERIFICATION POLICY, not a protocol rule, and it is
// the kind of decision a scoreboard has to make explicitly.Every scoreboard makes decisions like this and most of them are undocumented. Naming it as local policy is the difference between a design choice and an accident.
5. The Ordering Problem Nobody Mentions
The expectation and the observation in this environment are produced on the same clock — both derive from the completion event. A plain queue gets that wrong:
// In this environment the expectation and the observation are
// produced on the SAME clock: both are derived from the completion
// event. With a plain queue that made the first observation an
// orphan and left every later comparison one entry behind, so a
// perfectly correct rig reported nine mismatches.Nine mismatches on a correct design, from a queue that was off by one. The fix is a bypass, and the queue is retained for the case the bypass does not cover — a monitor that emits later than the completion, which is exactly what the duplicate and early-sample defects do.
6. The Row That Matters Most
Four rigs, one workload. Read the last two rows against each other:
rig compared data term addr orphan total
correct 9 0 0 0 0 0
WRONG_BYTE_MASK 9 1 0 0 0 1
REF_IGNORES_SEL 9 1 0 0 0 1
BROKEN_REF_UPDATE 9 0 0 0 0 0WRONG_BYTE_MASK is a DUT bug. REF_IGNORES_SEL is a testbench bug. They produce an identical symptom.
-> AND NOW READ THE LAST ROW CAREFULLY.
REF_IGNORES_SEL scores 1 mismatches and the
DUT IN THAT RIG IS THE CORRECT ONE. Its protocol
failures are 0 and its monitor is identical to
the clean rig's. A FAILING SCOREBOARD DOES NOT PROVE THE DUT IS
WRONG. Verification code is software and contains
bugs like any other. The first question on a
scoreboard failure is which of the two models is
mistaken - and the protocol checker's silence here
is evidence, because a DUT that really moved the
wrong data would still have kept the bus legal.And a defect that could not arm
NOTE THE ROW BELOW IT. BROKEN_REF_UPDATE - a model
that applies writes at ISSUE instead of COMMIT -
scores 0. IT CANNOT ARM HERE: RULE 3.35 permits
one outstanding phase, so nothing can observe the
model between a write being issued and committed.
A defect that cannot arm is not evidence of a
correct model; it is evidence of a stimulus that
never asked.RULE 3.35 is doing verification work here. One outstanding phase means issue and commit cannot be separated by another access, so the classic reference-model bug is unreachable in this architecture. A design with multiple outstanding transactions would expose it immediately — which is a reason to be careful about carrying this environment to a protocol that allows them.
7. Byte Lanes Are Modelled, Not Copied
// [SEL_O()] names the participating lanes - modelled
// independently rather than copied from the write path
for (b = 0; b < SW; b = b + 1) begin
if (sel_i[b] || REF_IGNORES_SEL) beginAnd the stimulus has to make the model sensitive, not merely exercise it:
// ── THE PARTIAL WRITE MUST BE SENSITIVE, NOT MERELY PRESENT ──────
// Seed the register with a value whose OTHER lanes are non-zero
// first. A partial write of zero-filled data into an already-zero
// register produces the same result whether [SEL_I()] is honoured or
// ignored, so the lane defects would hit the coverage bin and stay
// invisible. HITTING A BIN IS NOT THE SAME AS BEING SENSITIVE TO
// THE BUG THE BIN WAS CHOSEN FOR.That paragraph is the bridge to Chapter 26.5. The first version of the integrated test hit the partial-write bin and still missed both lane defects, because the data made masked and unmasked writes indistinguishable. Coverage said yes; sensitivity said no.
8. The Scoreboard Audits Its Own Inputs
// ── TB INTEGRITY: never compare a value that is not known ────────
if (exp_valid_i && ((^exp_adr_i === 1'bx) || (^exp_rdat_i === 1'bx)
|| (^exp_term_i === 1'bx)))
unk_q <= 1'b1; -> EVERY PASS DECISION WAS MADE ON KNOWN VALUES.
Module 24 lost a gate to an undriven counter: the
value went X, `if (x == 0)` was neither true nor
false, and the check was silently skipped.9. What The Reference Model Has To Get Right
A reference model is a second implementation, and it has its own list of things that are easy to get subtly wrong. Four of them appear in this one:
Reset state. The model starts all registers and all memory at zero, and the design does the same. If they disagreed at time zero, every read before the first write would mismatch — and the failure would look like a data bug rather than an initialisation bug.
for (i = 0; i < 16; i = i + 1) regs_m[i] <= 32'd0;
for (i = 0; i < 256; i = i + 1) mem_m[i] <= 32'd0;Read-after-write. The prediction for a read is computed from the model state as it stands at the completion clock, which is after every previously committed write has applied. In this environment that is automatic, because RULE 3.35 permits one outstanding phase and writes commit before the next request is issued.
Refused accesses must not change state. A write to a read-only offset or a reserved one is counted, not applied:
if (refuse) begin
nref_q <= nref_q + 16'd1;
end else beginA model that applied refused writes would diverge silently, and the divergence would only surface on a later read — far from the access that caused it.
The decode must match the interface, not an assumption about it. §2's offset bug is the example: the model was internally consistent, the design was correct, and they disagreed about what an address meant.
10. Which Layer Catches Which Defect
The four negative controls in this chapter land in three different places:
| defect | protocol | monitor census | scoreboard | it is a bug in |
|---|---|---|---|---|
WRONG_READ_DATA | 0 | clean | 4 data | the design |
WRONG_BYTE_MASK | 0 | clean | 1 data | the design |
DUPLICATE_MONITOR | 0 | 10 extra | orphans | the monitor |
REF_IGNORES_SEL | 0 | clean | 1 data | the reference model |
Every row has a zero in the protocol column. Two are design bugs, two are verification bugs, and the scoreboard alone cannot tell you which — that is what the monitor census and the checker's silence are for.
11. What This Chapter Did Not Build
- No out-of-order matching. RULE 3.35 permits one outstanding phase, so in-order comparison is sufficient for this protocol.
- No transaction-level modelling of the interconnect. The reference model predicts the endpoint's behaviour, not the fabric's routing.
- No golden-file comparison. The prediction is computed live, which is what lets it explain which field differed.
- No coverage of what was compared. Chapter 26.5 takes that up, and §7 above is why it matters.
Next: Chapter 26.5 — Coverage measures what the stimulus actually reached — and finds a regression that passes every check in this module while never issuing the one access that would have caught a shipped bug.
Continue learning
Related tutorials
- Related topic
Memory Transfers
A source read and a destination write are two bus operations with an arbitrary gap between them. Remove the holding register and six of six items corrupt, with zero protocol and zero invariant violations.
- Related topic
UCIe Scoreboards
Building a distributed UCIe scoreboard that follows obligations rather than expected packets — four independent models instead of one class, associative storage keyed by identity and generation, correlation across semantic operations, transport objects and physical attempts, epoch tracking, recovery-safe state, and a first-divergence report that names the layer instead of the symptom.
- Related topic
Protocol Verification — Three Contracts, and an Oracle That Owes You Nothing
A PCIe design is not verified by checking packets. Three different contracts must be proven, each observed somewhere different — and a checker that shares code with the design proves only that the design agrees with itself.
- Related topic
Scoreboards
A scoreboard that compares octet for octet fails on padding, on an appended check value and on a tag — and on a minimum-size frame only fifteen octets are invariant.
Standards & specifications
- Governing standard
- Wishbone SoC Interconnection Architecture (OpenCores)(opens OpenCores in a new tab)
Defines the Wishbone signal set, the bus cycles built from it and the interface rules a portable IP core must follow. It deliberately leaves interconnect topology, address map and arbitration policy to the integrator, so those are system decisions rather than requirements of the specification.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the Wishbone curriculum.
