In short: A scoreboard compares each transaction the DUT produces against a reference transaction, matching them either in strict program order or by a key when traffic can be reordered, and a good one reports exactly which field mismatched and the full transaction context so a failure is debuggable in seconds, not hours.
Every self-checking UVM testbench eventually comes down to one question: did the design do the right thing? The component that answers it is the scoreboard, and the heart of the scoreboard is the transaction comparison policy. Getting this policy right is the difference between a regression that catches a real RTL bug on the first failing seed and one that drowns you in false mismatches or, worse, silently passes a broken design. This article walks through the mechanics an interviewer will expect you to know: in-order versus out-of-order matching, key-based lookup, and mismatch reporting that actually helps.
What a scoreboard actually compares
A scoreboard receives two streams of transactions through analysis exports. One stream is the expected data: either produced by a reference model (a C/C++ golden model, a SystemVerilog predictor, or a reused RTL block) or forwarded straight from the input monitor. The other is the actual data observed on the DUT output by a monitor. The scoreboard's job is to pair each actual with the expected it corresponds to and compare them field by field.
The comparison itself is usually delegated to the transaction's compare() method. In UVM, if you register fields with the field-automation macros (or override do_compare()), uvm_object::compare() walks every registered field and returns a single pass/fail plus a miscompare count in the uvm_comparer. The scoreboard decides which two transactions get handed to that method, and that decision is the whole game.
In-order comparison: the simple, strict case
If the DUT guarantees that outputs appear in the same order as the stimulus that produced them, use in-order comparison. Both streams push into FIFO queues; on each new actual transaction you pop the head of the expected queue and compare. This is the default for a single-channel FIFO, a pipelined ALU, a UART, or any point-to-point link where reordering is architecturally impossible.
In-order is cheap and precise: O(1) per transaction, and a mismatch pins the exact position in the sequence. The failure mode to watch for is a dropped or extra transaction, which shifts every subsequent pair by one and produces a cascade of mismatches. That is why a drained-queue check at end-of-test (check_phase) is mandatory — a non-empty expected queue means the DUT swallowed transactions even if every compared pair passed.
Key fact: In-order comparison needs a leftover-count check. A test that compares 9,998 pairs cleanly but leaves 2 expected transactions stranded in the queue has found a real bug — a silent drop — that the per-pair compare() never saw.
Out-of-order comparison: key-based matching
Modern designs reorder freely. An AXI interconnect returns read data for different IDs in any order; an out-of-order CPU load/store unit, a network switch with multiple egress ports, or a cache with hit-under-miss all break strict ordering. Here you cannot pop a FIFO head — the matching actual may be the third, not the first, expected transaction still outstanding. The answer is an associative array keyed by a matching field.
You choose a key that is unique among all in-flight transactions: an AXI transaction ID (AWID/ARID), a packet sequence number, a tag, or a composite key such as {id, address} when a single ID can have multiple outstanding beats. Expected transactions are inserted into exp_map[key]; when an actual arrives, you look up its key, compare against the stored expected, and delete the entry. A missing key means an unexpected or duplicated output; a surviving entry at end-of-test means a response that never came back.
Choosing a good key
- Uniqueness while in flight. The key must identify at most one outstanding transaction. If an AXI master can issue two reads with the same ARID, the ID alone is not enough — AXI ordering rules say same-ID responses return in order, so key on ID and match the oldest same-ID entry (a queue per ID).
- Observable on both sides. The key must exist in both the expected and actual transaction. A payload CRC is a terrible key if the DUT is allowed to recompute it.
- Stable. The key must not be a field the DUT may legally transform. Match on the identifier, then
compare()the payload.
Mismatch reporting that saves hours
A scoreboard that prints UVM_ERROR: compare failed is nearly useless at 3 a.m. during a regression triage. Report the full picture: both transactions printed with sprint(), the specific field that differed, the matching key, a transaction count/sequence index, and simulation time. Let the uvm_comparer collect every miscompare (set show_max high) rather than aborting on the first, so a reader sees that bytes 4–7 of a 64-byte beat all flipped — a hint it is a lane or endianness bug, not random corruption.
| Scenario | Matching strategy | Typical key | Leftover check |
|---|---|---|---|
| UART / FIFO / pipe | In-order (FIFO pop) | none — position is the key | expected queue empty |
| AXI read channel | Out-of-order, queue per ID | ARID | all ID queues empty |
| NoC / switch | Out-of-order, assoc array | packet seq / dest+seq | map empty |
| Cache (hit-under-miss) | Out-of-order | {addr, req_tag} | map empty |
Key fact: Tools do not supply the policy for you. Synopsys VCS, Cadence Xcelium, and Siemens Questa all run the same UVM library — the in-order vs. key-based decision, the key choice, and the drain check are architecture you write, informed by the DUT's ordering contract.
Two more production habits worth internalizing: add an out-of-order timeout so a transaction that never returns raises an error at a bounded time instead of only at end-of-test, and gate the comparison behind coverage so you know the matching paths were actually exercised. For a deeper treatment of how the scoreboard plugs into the broader environment, see our companion piece on building a scoreboard in UVM, and for how the predicted stream is generated, read reference model vs. predictor.
If you are preparing for interviews or ramping onto a live verification project, structured mentorship accelerates this enormously — the VLSI verification tracks run by ChipXpert's training programs walk through exactly these scoreboard patterns on real AXI and NoC testbenches.
Go deeper: CourseTron's UVM Verification course builds a complete out-of-order AXI scoreboard from scratch — keys, timeouts, and failure triage included. Join a cohort and ship a self-checking testbench you can put on your resume.
Frequently asked questions
When should I use in-order instead of key-based comparison?
Use in-order whenever the DUT's specification guarantees outputs appear in the same sequence as the stimulus — single FIFOs, UARTs, simple pipelines. The moment the design can legally reorder (multiple AXI IDs, multiple egress ports, hit-under-miss), switch to key-based matching with an associative array.
What makes a good scoreboard key?
A field that uniquely identifies one in-flight transaction, is observable on both the expected and actual sides, and is never legally transformed by the DUT. AXI IDs, packet sequence numbers, and tags are common; use a composite key like {id, address} when a single ID can have several outstanding beats.
How do I detect a dropped transaction?
Per-pair compare() alone cannot see a drop. Add an end-of-test check in check_phase that the expected queue or key map is empty. Any leftover entry is a transaction the DUT never produced — a real functional bug.
Should the scoreboard abort on the first mismatched field?
No. Configure the uvm_comparer to report many miscompares so you see the full pattern — contiguous flipped bytes suggest a lane or endianness bug, scattered ones suggest random corruption. Always print both full transactions and the matching key alongside the error.
References & Further Reading
- Accellera — UVM (Universal Verification Methodology) standard and reference library
- IEEE 1800.2-2020 — Standard for UVM Language Reference Manual
- Arm — AMBA AXI Protocol Specification (ID-based ordering rules)
- Siemens Verification Academy — UVM scoreboard and analysis-port cookbook
- Wikipedia — Universal Verification Methodology