AMBA CHI · Module 17 · CHI Verification
CHI Scoreboards
The scoreboard proves the data values are correct — the complement to Chapter 17.2's state invariant. It records the data a read should return (from a reference model) and compares each response against its expected entry. For CHI it is distributed: a transaction touches requester, home, snooped caches, and memory, correlating events from many nodes. The crux is matching: a response is matched to its expected entry by the transaction key (TxnID + SrcID) CHI uses — not by address. Because several same-address transactions can be outstanding, address is ambiguous: a response matched against another entry compares a wrong value against the wrong expected, and if they agree it passes — hiding a real bug. Representative model, not the specification.
Advanced16 min readAMBA CHIScoreboardTxnIDCorrelationData Check
Module 17 · Chapter 17.3 · CHI Verification
Project thread — 17.2 checked state invariants. 17.3 checks data values via the scoreboard; 17.4 builds the reference.
1. Learning Outcomes
By the end of this chapter you should be able to:
- Explain that a scoreboard matches actual responses against expected outcomes.
- State that a CHI scoreboard is distributed — correlating events across nodes.
- Describe matching a response to its expected entry by the transaction key (TxnID + SrcID).
- Explain why matching by address alone is ambiguous for same-address transactions.
- Diagnose the hidden data bug from address-based mis-correlation.
- Implement a representative scoreboard matcher in SystemVerilog, Verilog-2001, and VHDL.
2. Why Should I Learn This?
The coherency checker (Chapter 17.2) proves the caches' states are consistent, but a design can hold legal states and still return the wrong bytes. The scoreboard is what checks the data values — it records the outcome each transaction is expected to produce and compares the actual response against it. It is the component that catches "the read returned the wrong data" — the most direct form of a functional bug.
The subtle part is correlation: how does the scoreboard know which expected entry a returning response belongs to? It must use the same key CHI itself uses — the transaction key (TxnID + SrcID, Chapter 13.4) — because that is what uniquely identifies a transaction. Matching by address instead is a trap: several transactions to the same address can be outstanding at once, so an address is ambiguous, and a response for one transaction can be matched against another's expected entry. When that happens, a genuinely wrong value is compared against the wrong expected value — and if they coincidentally agree, the bug passes. This chapter is the scoreboard and the correlation discipline that keeps it from hiding the very bugs it exists to catch.
3. Key Terms
4. Previous Chapter Connection
This chapter adds data-value checking to the state checking of Chapter 17.2 — together they cover both halves of correctness: the caches are in legal states and they return the right bytes. The reference for the expected data comes from a model built in Chapter 17.4; this chapter is the matching and comparison that uses it.
The correlation key is the one CHI itself uses. Chapter 13.4 established that a response carries a TxnID (and SrcID) so the requester can match it to an outstanding transaction — and Chapter 16.5 stored exactly that key in the tracker. The scoreboard must mirror this: it correlates by the same key, because that key is what makes the match unique. Matching by address instead is the verification analog of the RTL bug in Chapter 16.6 (a reused TxnID aliasing a response) — a correlation done on the wrong key. The lesson recurs: correlate by the identifier designed for it, in the RTL and in the checker alike.
5. Core Concept — match by the transaction key
A scoreboard matches each actual response to its expected entry by the transaction key (TxnID + SrcID) — never by address, which is ambiguous for same-address transactions.
- Expected vs actual. For each issued transaction, the scoreboard records the expected outcome (the data a read should return). Each actual response is matched to its expected entry and compared.
- Distributed correlation. A CHI transaction produces events at multiple nodes (requester, home, snooped caches, memory); the scoreboard correlates them into one transaction's picture.
- Match by the transaction key. A response is matched to its expected entry by the TxnID + SrcID — the same key CHI uses to route the response back (Chapter 13.4). This key is unique per outstanding transaction.
- Address is ambiguous. Several transactions to the same address can be outstanding at once, so address does not uniquely identify a transaction — matching by it can pair a response with the wrong expected entry.
The synthesis:
A scoreboard records each transaction's expected outcome and compares the actual response against it. It must correlate by the transaction key (TxnID + SrcID) — the unique identifier CHI itself uses — not by address, because multiple same-address transactions can be outstanding and address is ambiguous. Address-based matching mis-correlates a response to the wrong expected entry, so a wrong value can be compared against the wrong expected value and pass — hiding a real data bug.
6. Engineering Mental Model — matching lab results to patients
Think of a lab returning test results that must be matched to the right patient's chart (the expected entry).
- Each result comes back with a unique patient ID (the transaction key). The clerk matches the result to the chart with that ID and compares it against what was expected.
- Suppose the clerk instead matches by test type — "this is a blood-sugar result, file it under the blood-sugar chart." But several patients had blood-sugar tests ordered (same "address").
- A result for patient A gets filed against patient B's chart (same test type). Now B's expected range is checked against A's value. If A's abnormal value happens to fall in B's expected range, it is marked normal — A's real problem is missed.
- Worse, B's actual result later checks against A's chart and may flag a false abnormality — noise that buries the real ones.
The unique patient ID is the transaction key; the test type is the address. Matching by test type when several patients share it mis-files results — hiding real problems and inventing false ones. Match by the ID.
7. Engineering Diagram — the distributed scoreboard
The match by key stage keys on TxnID + SrcID, so each response finds its own expected entry, and the data comparison is meaningful. The DebugLab replaces the key with the address, so same-address responses can match the wrong entry.
8. Transaction Key vs Address
The two matching keys compared.
| Property | Transaction key (TxnID + SrcID) | Address (anti-pattern) |
|---|---|---|
| Unique per outstanding txn? | yes | no — many same-address txns |
| What CHI uses to correlate | yes (Chapter 13.4) | no |
| Match result | always the right entry | can be the wrong entry |
| Failure mode | — | hidden bug (false pass) / noise |
The rule to carry: correlate by the identifier that is unique per transaction — the same one the protocol uses. CHI assigns a TxnID precisely so a response can be matched unambiguously to its transaction, even when several target the same address. The scoreboard is doing the same job the requester's tracker does (Chapter 16.5), so it must use the same key. Address is a property of the transaction, not its identity — and using a non-unique property as a key is the root of the mis-correlation.
9. Why Address-Based Matching Hides Bugs
The false pass, made explicit.
- Same-address transactions coexist. Two reads to address X (from different sources, or pipelined) can be outstanding at once, with different expected values (e.g. before and after a write).
- Address matches ambiguously. When a response for X returns, an address-keyed scoreboard finds multiple expected entries for X and picks one — possibly the wrong one.
- Wrong value vs wrong expected. A response carrying a wrong value (a real bug) is compared against another transaction's expected value. If those happen to agree, the compare passes.
- The bug is hidden. The real data bug produces no mismatch because it was checked against the wrong reference — a false pass. (Symmetrically, a correct value checked against the wrong expected can false-fail, adding noise that masks real failures.)
The point to carry:
A scoreboard's value rests entirely on comparing the right actual against the right expected, and correlation is what pairs them — so a correlation bug silently poisons every comparison the scoreboard makes on affected transactions. This is more insidious than a wrong comparison, because the comparison logic is fine; it is the operands that are swapped. And the poisoning is data-dependent: whether a mis-correlation produces a false pass, a false fail, or (by luck) a correct verdict depends on whether the swapped expected values happen to match — so the same bug can pass a thousand times and fail once, or hide a real bug entirely when the values coincide. The defense is to make correlation unambiguous by construction, using the key that is guaranteed unique per outstanding transaction — the very key the protocol assigns for this purpose. This is a general principle for any checker that pairs events across time or space: key on identity, not on attributes, because attributes can collide and a collision in the key corrupts the check without any visible error. The scoreboard mirrors the DUT's own correlation (13.4, 16.5) precisely so that the checker and the design agree on which transaction each response belongs to.
10. Matching a Response — by key vs by address
Two reads to address X: transaction A (expects old value 0x11) and B (expects new value 0x22, after a write). A's response returns a wrong value 0x22 (a bug).
- Issue A and B. The scoreboard records expected: A → 0x11, B → 0x22, both for address X, keyed by their transaction keys.
- A's response returns — wrong value 0x22. A's read should have returned 0x11 but a bug returns 0x22. The response carries A's transaction key.
- Match by key — caught. A key-based scoreboard matches the response to A's expected entry (0x11), compares 0x22 vs 0x11 → mismatch → fail. The bug is caught.
- Match by address — hidden. An address-keyed scoreboard finds two entries for X and matches A's response to B's entry (0x22). It compares 0x22 vs 0x22 → match → pass. The bug is hidden.
- The wrong value passed. A returned the wrong data, but because it was checked against B's expected value (which coincidentally equalled the wrong value), the scoreboard reported all clear. False pass.
The key-based match compared A's response against A's expectation and caught the bug; the address-based match compared it against B's and hid it. The DebugLab is step 4.
11. Checker / Monitor View — the scoreboard matcher
Match an actual response to the expected entry with the same transaction key, then compare data. Representative.
// Representative scoreboard matcher (educational).
// Match an actual response to its expected entry by the TRANSACTION KEY (TxnID + SrcID),
// the same correlation CHI uses -- NOT by address, which is ambiguous when multiple
// same-address transactions are outstanding. Then compare the returned data.
module chi_sb_match #(parameter NEXP = 16, parameter TW = 8, parameter DW = 64) (
input logic resp_valid,
input logic [TW-1:0] resp_key, // response's transaction key (TxnID+Src)
input logic [DW-1:0] resp_data, // returned data
input logic [NEXP-1:0] exp_valid, // which expected entries are pending
input logic [TW-1:0] exp_key [NEXP], // each entry's transaction key
input logic [DW-1:0] exp_data [NEXP], // each entry's expected data
output logic matched,
output logic [NEXP-1:0] match_oh,
output logic data_mismatch, // a real data bug: value != expected
output logic unmatched // no expected entry -> orphan
);
logic [NEXP-1:0] hits;
always_comb begin
hits = '0;
for (int i = 0; i < NEXP; i++)
if (exp_valid[i] && (exp_key[i] == resp_key)) // match on the TRANSACTION KEY
hits[i] = 1'b1;
end
assign match_oh = hits;
assign matched = resp_valid && (|hits);
assign unmatched = resp_valid && !(|hits);
// Compare the returned data against THIS transaction's expected value.
logic [DW-1:0] exp_sel;
always_comb begin
exp_sel = '0;
for (int i = 0; i < NEXP; i++) if (hits[i]) exp_sel = exp_data[i];
end
assign data_mismatch = matched && (resp_data != exp_sel);
endmoduleThe same behavior in Verilog-2001 (flattened arrays):
// Representative scoreboard matcher (Verilog-2001).
module chi_sb_match #(parameter NEXP = 16, parameter TW = 8, parameter DW = 64) (
input resp_valid,
input [TW-1:0] resp_key,
input [DW-1:0] resp_data,
input [NEXP-1:0] exp_valid,
input [NEXP*TW-1:0] exp_key_flat,
input [NEXP*DW-1:0] exp_data_flat,
output matched, data_mismatch, unmatched,
output reg [NEXP-1:0] match_oh
);
integer i; reg [DW-1:0] exp_sel;
always @* begin
match_oh = {NEXP{1'b0}};
for (i = 0; i < NEXP; i = i + 1)
if (exp_valid[i] && (exp_key_flat[i*TW +: TW] == resp_key))
match_oh[i] = 1'b1;
end
assign matched = resp_valid & (|match_oh);
assign unmatched = resp_valid & ~(|match_oh);
always @* begin
exp_sel = {DW{1'b0}};
for (i = 0; i < NEXP; i = i + 1) if (match_oh[i]) exp_sel = exp_data_flat[i*DW +: DW];
end
assign data_mismatch = matched & (resp_data != exp_sel);
endmoduleAnd in VHDL:
-- Representative scoreboard matcher (VHDL).
library ieee;
use ieee.std_logic_1164.all;
entity chi_sb_match is
generic ( NEXP : integer := 16; TW : integer := 8; DW : integer := 64 );
port (
resp_valid : in std_logic;
resp_key : in std_logic_vector(TW-1 downto 0);
resp_data : in std_logic_vector(DW-1 downto 0);
exp_valid : in std_logic_vector(NEXP-1 downto 0);
exp_key_flat : in std_logic_vector(NEXP*TW-1 downto 0);
exp_data_flat : in std_logic_vector(NEXP*DW-1 downto 0);
matched : out std_logic;
data_mismatch : out std_logic;
unmatched : out std_logic
);
end entity;
architecture rtl of chi_sb_match is
begin
process (resp_valid, resp_key, resp_data, exp_valid, exp_key_flat, exp_data_flat)
variable hit : std_logic;
variable exp_sel : std_logic_vector(DW-1 downto 0);
begin
hit := '0'; exp_sel := (others => '0');
for i in 0 to NEXP-1 loop
if exp_valid(i) = '1' and
exp_key_flat((i+1)*TW-1 downto i*TW) = resp_key then -- match on the KEY
hit := '1';
exp_sel := exp_data_flat((i+1)*DW-1 downto i*DW);
end if;
end loop;
matched <= resp_valid and hit;
unmatched <= resp_valid and (not hit);
data_mismatch <= '1' when (resp_valid = '1' and hit = '1' and resp_data /= exp_sel)
else '0';
end process;
end architecture;All three match on resp_key == exp_key[i] — the transaction key — and compare the data against that entry's expected value. The DebugLab matches on addr instead, so same-address entries can be confused.
12. Assertion View — a response matches its own expected entry
The properties enforce correct correlation: a match is on the key, and unmatched responses are flagged.
// Bind to chi_sb_match.
// 1. A match is one-hot on an expected entry with the SAME transaction key.
property p_match_is_by_key;
@(posedge clk) disable iff (!rst_n)
matched |-> ($onehot(match_oh) && (exp_key[$onehot0(match_oh)?0:0] == resp_key));
endproperty
// (structural: match_oh[i] set only where exp_key[i]==resp_key)
// 2. A response with no matching key is flagged unmatched (an orphan), not silently used.
property p_unmatched_flagged;
@(posedge clk) disable iff (!rst_n)
(resp_valid && !(|match_oh)) |-> unmatched;
endproperty
// 3. Two outstanding entries never share a transaction key (keys are unique).
property p_keys_unique;
@(posedge clk) disable iff (!rst_n)
(exp_valid[i] && exp_valid[j] && i != j) |-> (exp_key[i] != exp_key[j]);
endpropertyThe system point, beyond the checks:
p_keys_uniqueis the assumption that makes key-based matching sound, and it is worth stating explicitly because it is inherited from the protocol, not assumed by the scoreboard. CHI guarantees that outstanding transactions from a given source have distinct TxnIDs (Chapter 16.6's issue gate enforces it), so the (TxnID, SrcID) pair is unique across all outstanding transactions system-wide — which is exactly what a matching key needs. The scoreboard borrows this uniqueness: because the protocol keeps keys unique, the scoreboard's key-based lookup is unambiguous. This is a recurring and powerful pattern — a checker aligns its correlation with the design's own correlation, so the checker is correct for the same reason the design is. It also means the scoreboard can serve as a check on the uniqueness assumption itself: if two outstanding entries ever collide on a key (Chapter 16.6's reused-TxnID bug), the scoreboard'sp_keys_uniquefires — so the scoreboard catches both data bugs (wrong value) and the correlation bugs that would corrupt its own matching. Aligning the checker's key with the protocol's key thus makes the checker both correct and self-protecting; choosing a different key (address) breaks both properties at once.
- What it proves: matches are by key; unmatched responses are flagged; keys are unique.
- What it does not prove: the expected data is right — that is the reference model (Chapter 17.4).
- Bug signature: a scoreboard whose match key is the address, not TxnID + SrcID.
13. Testbench — a same-address response must match its own entry
Two same-address transactions with different expected data; a wrong response for one must be caught.
module tb_chi_sb_match;
localparam NEXP = 4, TW = 8, DW = 16;
logic resp_valid;
logic [TW-1:0] resp_key;
logic [DW-1:0] resp_data;
logic [NEXP-1:0] exp_valid;
logic [TW-1:0] exp_key [NEXP];
logic [DW-1:0] exp_data [NEXP];
logic matched, data_mismatch, unmatched;
logic [NEXP-1:0] match_oh;
int errors = 0;
chi_sb_match #(.NEXP(NEXP), .TW(TW), .DW(DW)) dut (.*);
initial begin
// Two outstanding transactions to the SAME address, different keys and expected data.
// A: key=0xAA expects 0x0011. B: key=0xBB expects 0x0022.
exp_valid = 4'b0011;
exp_key[0] = 8'hAA; exp_data[0] = 16'h0011; // transaction A
exp_key[1] = 8'hBB; exp_data[1] = 16'h0022; // transaction B
exp_key[2] = 0; exp_data[2] = 0; exp_key[3] = 0; exp_data[3] = 0;
// A's response returns the WRONG value 0x0022 (a real data bug), carrying A's key.
resp_valid = 1; resp_key = 8'hAA; resp_data = 16'h0022; #1;
if (!matched) begin errors++; $display("FAIL A's response not matched"); end
else if (match_oh !== 4'b0001) begin errors++; $display("FAIL matched wrong entry: %b", match_oh); end
else if (!data_mismatch) begin errors++; $display("FAIL wrong value NOT caught (address match would hide it!)"); end
else $display("PASS A matched its OWN entry (key) -> data_mismatch caught the bug");
// A correct response for B: key=0xBB, value 0x0022 -> matches B, no mismatch.
resp_key = 8'hBB; resp_data = 16'h0022; #1;
if (!matched || data_mismatch) begin errors++; $display("FAIL B's correct response flagged"); end
else $display("PASS B matched its own entry, value correct");
// A response with an unknown key -> unmatched (orphan), flagged not swallowed.
resp_key = 8'hCC; resp_data = 16'h0033; #1;
if (!unmatched) begin errors++; $display("FAIL unknown-key response not flagged"); end
else $display("PASS unknown key flagged unmatched");
if (errors == 0) $display("ALL TESTS PASSED");
else $display("%0d FAILURE(S)", errors);
$finish;
end
endmoduleExpected output:
PASS A matched its OWN entry (key) -> data_mismatch caught the bug
PASS B matched its own entry, value correct
PASS unknown key flagged unmatched
ALL TESTS PASSED14. DebugLab — a scoreboard that matches by address
A scoreboard that matches by address
SCOREBOARD MATCHES BY ADDRESS -> SAME-ADDRESS RESPONSES MIS-CORRELATED -> WRONG VALUE PASSES (HIDDEN BUG)Data bugs escape a green scoreboard, and separately the scoreboard sometimes reports failures that do not reproduce (noise). Both correlate with multiple same-address transactions in flight (pipelined reads, producer/consumer sharing); single-outstanding-per-address tests are clean. The escapes and the noise appear together — the fingerprint of mis-correlation.
A wrong value was checked against the wrong expected entry:
outstanding: A (key AA, addr X, expects 0x11), B (key BB, addr X, expects 0x22)
A's response returns WRONG value 0x22 (bug), carrying key AA
scoreboard matches by ADDRESS X -> finds A and B -> picks B's entry (expects 0x22)
-> compares 0x22 vs 0x22 -> MATCH -> PASS (A's bug HIDDEN)
symmetric: B's correct 0x22 could match A's entry (0x11) -> false FAIL (noise)
correct: match by key AA -> A's entry (expects 0x11) -> 0x22 vs 0x11 -> MISMATCH -> caughtAddress did not identify the transaction; the key did.
The scoreboard matched responses to expected entries by address instead of the transaction key. From that point any same-address concurrency mis-correlated responses.
A scoreboard must correlate by the identifier that is unique per outstanding transaction — the transaction key (TxnID + SrcID) CHI uses — because address is an attribute, not an identity, and collides when same-address transactions coexist. Matching by address pairs a response with the wrong same-address expected entry, so the data comparison uses the wrong expected value: a wrong response can pass (hidden bug) and a right one can fail (noise), data-dependent on whether the swapped values happen to agree. The comparison logic is fine; the operands are swapped. The scoreboard must mirror the DUT's own correlation (Chapter 13.4, 16.5), keying on the unique transaction key — which the protocol keeps unique (Chapter 16.6), making the match unambiguous. Key on identity, not attributes.
Correlate responses to expected entries by the transaction key (TxnID + SrcID) — the same key CHI uses — as the matcher does, so each response is always compared against its own expected value. Never key on the address, which does not uniquely identify a transaction. Align the scoreboard's correlation with the protocol's.
15. Common Mistakes
- Matching by address. Assumption: address identifies a transaction. Bug: hidden data bug (the DebugLab). Prevention: match by TxnID + SrcID.
- Dropping SrcID from the key. Assumption: TxnID alone is unique. Bug: cross-source collision. Prevention: key on TxnID + SrcID.
- Ignoring unmatched responses. Assumption: every response matches. Bug: orphans swallowed. Prevention: flag unmatched.
- Not checking key uniqueness. Assumption: keys are always unique. Bug: a reused-ID bug corrupts matching. Prevention: assert unique keys.
- A single central scoreboard for a distributed protocol. Assumption: one view suffices. Bug: missed multi-node events. Prevention: correlate across nodes.
- Trusting a green scoreboard alone. Assumption: no mismatch means correct. Bug: mis-correlation hides bugs. Prevention: verify correlation itself.
16. Engineering Checklist
- Record each transaction's expected outcome keyed by TxnID + SrcID.
- Match each actual response to its expected entry by the transaction key.
- Compare returned data against that entry's expected value.
- Flag responses with no matching key as unmatched (orphans).
- Correlate events across the requester, home, snooped caches, and memory.
- Assert transaction keys are unique among outstanding entries.
17. Key Takeaways
- A scoreboard matches actual responses against expected outcomes.
- A CHI scoreboard is distributed — correlating events across nodes.
- Match by the transaction key (TxnID + SrcID) — the identifier CHI uses.
- Address is ambiguous — many same-address transactions can be outstanding.
- Address-based matching hides data bugs (false pass) and adds noise (false fail).
- Key on identity, not attributes; the model here is representative.
18. Quick Revision
CHI scoreboards. A scoreboard records, per transaction, the expected outcome (chiefly the data a read should return, from a reference model) and matches each actual response against its expected entry, flagging mismatches — the data-value check that complements the state invariant of Chapter 17.2. For CHI it is distributed: a transaction touches the requester, home, snooped caches, and memory, so the scoreboard correlates events from multiple nodes. The crux is the matching key: a response must be matched to its expected entry by the transaction key (TxnID + SrcID) — the same correlation CHI uses (Chapter 13.4) and stores in the tracker (Chapter 16.5) — not by address. Because several transactions to the same address can be outstanding at once, address is ambiguous: an address-keyed scoreboard can match a response to another same-address transaction's expected entry, comparing a wrong value against the wrong expected value. If they coincidentally agree, a real data bug passes (false pass); if they disagree, a correct value false-fails (noise). The comparison logic is fine — the operands are swapped. Correlate by the unique identifier the protocol assigns (which Chapter 16.6 keeps unique), so the checker and the design agree on which transaction each response belongs to. Key on identity, not attributes. Representative model; 17.4 covers the reference model that supplies the expected values.
Coming Next
Chapter 17.4 — Reference Models. The scoreboard compares actual data against an expected value; that value comes from a reference model. Chapter 17.4 covers reference models — the independent golden model that computes each transaction's expected result, and why it must be a genuinely separate implementation, because a reference model that shares the design's logic or state produces matching wrong answers and the comparison passes both.