Skip to content

UCIe · Module 27

Verification Review Checklist

The DV signoff gate — why coverage of contracts beats coverage of code, how to audit a predictor for independence rather than trust it, the monitor and scoreboard defects that make a testbench agree with the design's bugs, and why twenty thousand passing tests at full code coverage can still be a FAIL.

27.1 closed the decisions; 27.2 checked the code implements them. This gate asks the harder question: could this environment have told us if it did not?

1. The One-Sentence Model

Verification completeness is coverage of contracts, not coverage of code — and an environment is only checking something when the expected value comes from somewhere other than the thing being checked.

The failure this gate exists to catch is a green regression. Twenty thousand tests, full code coverage, zero failures — and a scoreboard that would have passed regardless of what the design did (§23). Nothing in a pass/fail summary distinguishes that from real closure, which is why the gate audits structure rather than results.

And the second idea is the evidence standard (§4). "Retry is tested" is a review statement. "Retry × sustained backpressure × outstanding depth is covered, the scoreboard correlates semantic identity independently across attempts, and mutation testing proved the checker fails when duplicate delivery is injected" is evidence. This gate accepts only the second, and §24's checklist is written to force it.

2. What This Gate Owns

GateAsksNot this chapter
27.1 — Architecturewhat are we building, and who owns each decision?
27.2 — RTLdid we implement it safely?code-level review, lint, X-propagation
27.3 — Verification (this chapter)can we prove it?
27.4 — Performancecan it meet the workload?measured throughput, counters, margin
27.5 — Integrationcan independent pieces operate together?package seams, interop
27.6 — Debugcan we diagnose it in silicon?observability, first-failure capture
27.7 — Interviewcan an engineer reason through all of it?

Three boundaries, stated because this gate is the one most often merged with its neighbours.

This gate does not re-review RTL. "Is this else if losing an update?" is 27.2 §8. "Would our scoreboard have detected the drift?" is this gate's — and they have different answers surprisingly often.

This gate does not build the environment; 25.8 did that. 25.8 owns the design of a multi-agent UCIe environment — agents, predictors, analysis topology. This chapter owns the audit: given an environment, can it prove the architecture correct? Where 25.8 explains a structure, this gate asks for the evidence that the structure works.

And this gate does not measure performance. A throughput shortfall is 27.4's. But whether the environment can observe a throughput shortfall — whether the counters exist and are sampled — is partly this gate's, and §19 hands that boundary over explicitly.

3. PASS / CONDITIONAL PASS / FAIL

Module 27's gates need decision semantics, and this is where they are defined for the rest of the module.

DecisionRequires
PASSrequirement closed · owner clear · evidence reproducible · risk understood · no unresolved architectural ambiguity
CONDITIONAL PASSknown issue · bounded risk · named owner · documented mitigation · closure date or precondition · does not invalidate a downstream gate's assumptions
FAILunresolved correctness ambiguity · unverified cross-layer contract · target not demonstrated · integration assumption unresolved · insufficient observability for a known risk · the review rests on intention rather than evidence

Four readings, and the third is the one that keeps a gate honest.

"Evidence reproducible" is the PASS criterion that does the most work. A result someone saw once, on a branch, with a local edit, is not evidence. A named regression, a named test, a coverage report, a mutation result — those are reproducible by someone else, which is what makes a PASS survive the reviewer leaving the company.

A CONDITIONAL PASS has five required fields and is void without any of them. In particular it needs a closure date or precondition and a statement that it does not invalidate a downstream gate's assumptions. A conditional pass on predictor independence, for instance, invalidates every subsequent claim of functional closure — so it is not conditional, it is a FAIL wearing a schedule.

And the last FAIL row is the one reviewers resist using. "The review rests on intention rather than evidence" is a legitimate, sufficient reason to fail a gate (27.1 §4). A gate that only fails on discovered defects will always pass, because an environment that cannot find defects reports none.

One anti-pattern worth naming explicitly. CONDITIONAL PASS must not become a polite FAIL. The test is mechanical: can a downstream gate proceed on the assumption that this item will close? If 27.4 would have to redo its work when the item closes, the item is blocking and the honest decision is FAIL.

4. Statement Versus Evidence

Every item in §24 is written to force the right-hand column.

Review statement (worthless)Evidence (accepted)
"retry is tested"retry × sustained backpressure × outstanding-depth crosses covered; scoreboard correlates semantic identity across attempts independently; mutation with injected duplicate delivery FAILED the checker
"the scoreboard checks it"the analysis topology, showing the predictor's input port is not fed by the output monitor (§7)
"we have 100 % coverage"the requirement→coverpoint map, with the crosses that were hit and the ones deliberately excluded, each with a reason
"recovery works"recovery injected with N outstanding obligations; exactly one completion per semantic operation asserted; both retention policies tested
"assertions pass"each assertion's antecedent covered; each proven capable of failing by mutation (27.2 §17)
"the test suite is large"nothing. Test count is not a metric of anything (§23)
"DV signed off"the requirements matrix with a status per row and a named owner per gap (§6)

Three readings.

The pattern in the right-hand column is always the same three parts: what stimulus was applied, what independently checked it, and what proves the check can fail. An item missing the third part is untested verification — and §22's mutation testing is how you get it.

Row 6 is deliberately blunt. Test count measures effort, not closure. A suite of 20,000 tests against a mirrored predictor (§8) has the same diagnostic power as zero tests, and it costs more to run.

And row 3 matters because coverage is the metric most often misused as evidence. 100 % code coverage says every line executed. It says nothing about whether any line was checked, and nothing at all about combinations (27.2 §3 pass 2's territory, in DV form).

5. Sourcing and Scope

6. Area A — The Verification Plan as a Requirements Matrix

A verification plan is not a list of tests. It is a mapping from architectural requirements to the evidence that closes each one.

ColumnWhat it must containA gap here means
requirementone architectural decision from 27.1the plan is not traceable
stimulusthe test or sequence that creates the conditionuntestable requirement
checkerthe independent mechanism that decides pass/failstimulus without a checker is NOT verification
coveragethe coverpoint or cross proving it was reachedchecker without coverage is not closure
fault injectionwhat negative condition was injectedonly happy paths verified
expected failure evidencewhat a failure would look likeyou cannot recognise the bug
ownera namenobody closes it
statusPASS / CONDITIONAL / FAIL (§3)the plan cannot be reviewed

Four readings.

The two load-bearing sentences of this whole area: a requirement with stimulus but no checker is not verified — it is exercised. And a requirement with a checker but no coverage is not closed — you have a mechanism that would have caught it, and no evidence the condition ever occurred.

Column 6 is the one nobody writes and every debug session needs. "What would a failure look like?" forces the plan to state the observable — an error class, a scoreboard message, a counter divergence. Without it, a failing regression produces a symptom nobody can map back to a requirement, and triage begins from zero (27.6 inherits this).

Traceability runs backwards to 27.1. Every architecture decision should appear as a row. A decision with no row is unverified by construction, and that is a finding at this gate even though the defect was created at the first one.

And the review technique is to sample rather than read. Take five requirements — including the two 27.1 §19 identifies as reaching silicon most often — and walk all eight columns. If two of five have a gap, the plan has a systematic problem and the finding is about the plan, not the rows.

7. Area B — Predictor Independence

The single highest-value audit in this chapter, and it takes ten minutes.

#Must be trueEvidence that countsWeak evidenceFAIL if
B1the predictor's input is not the DUT's outputthe actual connect_phase source, read line by line"it's a reference model"any path from output monitor into the model
B2the model does not call DUT functions or import its packagethe model's import list and dependencies"it's a separate file"shared implementation functions
B3constants are derived from the spec, not copied from RTLthe derivation, or a \define` from a shared spec header"the values match"constants copied from the design
B4a deliberate DUT mutation causes a failurethe mutation run and its failure signature (§22)"it would fail"never demonstrated
B5coverage is sampled from the monitor, not the modelthe covergroup's sampling sourcemodel-sampled coverage

Three readings.

B1 is checked by reading connect_phase, not by asking. Everyone believes their predictor is independent. The topology either has a path from the output monitor into the model or it does not, and that is a fact you can see in a few lines of code (25.8 §11).

B3 is the subtle one and it produces a testbench that agrees with the design's misreadings. If a width, an encoding or a timeout constant is imported from the RTL package, the checker cannot disagree with the design about it — so a misread specification value is confirmed rather than caught. The right source is the specification (recorded per 27.1 §7 B6), or at minimum a shared header owned by neither side.

And B4 converts belief into evidence. "The scoreboard would catch a duplicate" is a review statement (§4). A mutation run that injects duplicate delivery and shows the scoreboard failing with the expected message is evidence — and it is the only thing that distinguishes a working checker from a decorative one.

8. Wrong UVM — the Mirrored Predictor

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// WRONG. ILLUSTRATIVE. The analysis topology that produces a permanently green
// regression. Written by someone connecting ports in the order they appear in
// the environment — and every individual connection looks reasonable.
class ucie_env extends uvm_env;
  ucie_agent      m_in_agent;      // drives and monitors the input side
  ucie_agent      m_out_agent;     // PASSIVE monitor on the output side
  ucie_predictor  m_pred;
  ucie_scoreboard m_sb;
 
  function void connect_phase(uvm_phase phase);
    // BUG: the predictor is fed from the OUTPUT monitor. The "expected"
    // stream is now a function of what the DUT actually produced.
    m_out_agent.mon.ap.connect(m_pred.analysis_export);
 
    // The same output monitor also supplies "actual".
    m_pred.expect_ap.connect(m_sb.expected_export);
    m_out_agent.mon.ap.connect(m_sb.actual_export);
  endfunction
endclass

Architecture. Three connections. Two of them originate at the same port — which is the entire defect, and it is invisible unless you trace the sources rather than read the lines.

State. The scoreboard holds expected and actual queues that are, structurally, two views of one stream.

Event. Every output transaction writes both sides.

Contract. A scoreboard's contract is that expected is derived independently. Here it is derived from actual, so the comparison is f(x) == x for a predictor that is close to identity in the fields that matter.

Failure — the timeline. The DUT drops one transaction and duplicates another.

EventDUT outputPredictor inputExpectedActualScoreboard
txn A acceptedA emittedAAAmatch
txn B acceptedB DROPPEDnothingnothingnothingno comparison at all
txn C acceptedC emittedCCCmatch
txn D acceptedD emitted TWICED, DD, DD, Dboth match
end of testqueues equalqueues equalPASS

Two real, severe bugs — a dropped transaction and a duplicate delivery — and the regression is green.

Root cause. The expected value was derived from the thing being checked. A dropped transaction produces no expectation, so nothing detects the absence. A duplicated transaction produces a duplicated expectation, so the duplicate matches.

And the reason it survives review is that the environment looks textbook-complete: agents, a passive monitor, a predictor, a scoreboard, coverage. Every component exists. One wire is wrong.

DV/debug. The signature is the absence of a signature — no failures, ever, including in early bring-up when the design was genuinely broken. A scoreboard that has never failed during development is evidence of a problem, not of quality (27.2 §17). B4's mutation run makes it undeniable in one afternoon.

9. Corrected — Auditable Independence

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// CORRECT. ILLUSTRATIVE. The predictor is driven from the INPUT side and from
// configuration only. The topology is written so that independence is visible
// in five lines rather than argued about in a meeting.
class ucie_env extends uvm_env;
  ucie_agent      m_in_agent;
  ucie_agent      m_out_agent;
  ucie_predictor  m_pred;
  ucie_scoreboard m_sb;
 
  function void connect_phase(uvm_phase phase);
    // EXPECTED path: input stimulus -> predictor -> scoreboard.
    // The predictor never observes the output side. This single line is what
    // the review is checking, and it should be commented as such.
    m_in_agent.mon.ap.connect(m_pred.analysis_export);
    m_pred.expect_ap.connect(m_sb.expected_export);
 
    // ACTUAL path: output observation -> scoreboard. Terminates AT the
    // scoreboard; it must never fan out to the predictor.
    m_out_agent.mon.ap.connect(m_sb.actual_export);
 
    // Coverage samples OBSERVED behaviour, never predicted behaviour (B5) —
    // otherwise coverage reports what the model imagined, not what happened.
    m_in_agent.mon.ap.connect(m_cov.analysis_export);
  endfunction
endclass

Architecture. Two disjoint paths that meet only inside the scoreboard. The property being reviewed — no edge from the output monitor into the model — is now a structural fact.

State. Unchanged; the fix is topological, not behavioural.

Event. The predictor advances on input acceptance, so it produces an expectation whether or not the DUT emits anything — which is precisely what makes a dropped transaction detectable (§14's orphan and incomplete checks).

Contract. The predictor must model the architecture from the specification and configuration, never from observed output. Its inputs are stimulus plus config; that is the whole allowed set.

Failure. Replay §8's timeline against this topology: B produces an expectation with no actual → SB_INCOMPLETE at end of test. D produces one expectation and two actuals → SB_ORPHAN on the second. Both bugs are now two distinct, named failures.

DV/debug. The review artefact is this connect_phase with the comments. A reviewer should be able to confirm independence without reading the predictor at all — and if confirming it requires reading the predictor, that is itself a finding.

10. Area C — Monitor Acceptance Semantics

#Must be trueEvidence that countsWeak evidenceFAIL if
C1the monitor samples acceptance, not offeringthe sampling expression: valid && ready"it uses a clocking block"samples valid alone
C2signals are sampled through a clocking blockthe clocking block declaration and skewdirect interface readsrace-prone sampling
C3the transaction is cloned before write()the clone/copy callsubscribers share a handle
C4observed transport facts are excluded from comparisonUVM_NOCOMPARE on attempt/link fieldsretries reported as mismatches
C5the monitor is passive and drives nothingthe agent's is_active settinga monitor with a driver

Three readings.

C1 is 27.2 §6's question asked of the testbench, and the consequence here is worse. In RTL a valid-only counter inflates a metric. In a monitor it publishes the same transaction once per stalled cycle — so the scoreboard sees duplicates that the design never produced. The testbench then reports a DUT bug that does not exist, and a team can spend a week proving the RTL innocent.

C3 is a one-call defect with a nasty signature. If the monitor reuses one transaction object and writes a handle, every subscriber sees the last transaction, and earlier ones appear mutated. The symptom is a scoreboard mismatch whose data changes when you add a second subscriber — which sends debug toward the scoreboard and away from the monitor.

And C4 keeps the layers separate. Transport facts — attempt count, which physical link — belong in the transaction for debug and must not participate in comparison (25.5 §11). Otherwise a legitimate retry is a mismatch, and the team learns to ignore mismatches.

11. Wrong Monitor — Sampling the Offer

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// WRONG. ILLUSTRATIVE. The monitor publishes whenever valid is high. Under
// backpressure the producer HOLDS valid with the same payload, so one
// transaction is published once per stalled cycle.
task ucie_monitor::run_phase(uvm_phase phase);
  ucie_txn t;
  forever begin
    @(cb);
    if (cb.valid) begin                 // BUG 1: no ready term
      t = ucie_txn::type_id::create("t");
      t.sem_id = cb.sem_id;
      t.data   = cb.data;
      ap.write(t);                      // BUG 2: publishes every stalled cycle
    end
  end
endtask

Architecture. One sample, one publish. Correct if ready is always high — which is exactly the condition under which nobody exercises backpressure.

State. None retained, so the monitor cannot tell a held offer from a new one.

Event. Every clock edge with valid high.

Contract. Subscribers assume one write() per transaction. The monitor's contract is broken for the entire duration of any stall.

Failure — the timeline. One transaction, ready low for four cycles.

CyclevalidreadyTransferMonitor publishesScoreboard sees
1010notxn(A)1 × A
1110notxn(A)2 × A
1210notxn(A)3 × A
1310notxn(A)4 × A
1411YEStxn(A)5 × A
4 spurious duplicates

Root cause. A testbench bug that accuses the RTL. The design transferred A exactly once; the monitor reported it five times, and the scoreboard raises four duplicate-delivery errors against innocent logic.

And the damage compounds. The failure appears only under backpressure, so it correlates with load — which looks exactly like a real congestion-related design bug. Teams have chased this into the RTL for days.

Corrected.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// CORRECT. Publish on the ACCEPTED event, and clone so subscribers cannot
// observe a mutated object (C3).
task ucie_monitor::run_phase(uvm_phase phase);
  ucie_txn t, t_pub;
  forever begin
    @(cb);
    if (cb.valid && cb.ready) begin           // the transfer, not the offer
      t = ucie_txn::type_id::create("t");
      t.sem_id     = cb.sem_id;
      t.generation = cb.generation;
      t.data       = cb.data;
      t.attempt    = cb.attempt;              // carried for debug, NOT compared
      $cast(t_pub, t.clone());                // independent object per publish
      ap.write(t_pub);
    end
  end
endtask

DV/debug. The review question is one line long: "show me the sampling expression." And the corroborating evidence is a coverage bin on transactions accepted while a stall was in progress — if that bin is empty, backpressure was never exercised and C1 has never actually been tested either way.

12. Area D — Scoreboard Architecture

#Must be trueEvidence that countsWeak evidenceFAIL if
D1matching is by semantic identity, not arrival orderthe outstanding map keyed by sem_id"it's in order"FIFO compare where ordering is not contractual
D2generation is checkedthe generation comparisonstale completion retires a live entry
D3orphan actuals are an errora named SB_ORPHAN errorsilently droppedunexpected output ignored
D4unmatched expecteds are an error at end of testSB_INCOMPLETE in check_phasedropped transactions invisible
D5the "nothing was checked" case is an errorSB_NOTHING_CHECKEDan empty run reports PASS
D6duplicate delivery is distinguishable from mismatchdistinct error classesone generic errortriage cannot start

Three readings.

D1 is where a scoreboard silently narrows its own scope. FIFO comparison is correct only if ordering is contractual (27.1 §7 B-area). Where it is not, an out-of-order but perfectly legal response is a false failure — and the usual repair is to relax the check, which removes the ability to detect real reordering.

D4 and D5 are the two checks that make a quiet environment fail loudly. Without D4, a dropped transaction is simply an expectation nobody looked at. Without D5, a test whose stimulus never started reports PASS with a spotless scoreboard — the most dangerous single result in verification, because it looks like the best one.

And D6 is a triage requirement more than a correctness one. SB_ORPHAN, SB_STALE_GEN, SB_REALLOC and SB_MISMATCH name four different design bugs (25.8 §14). A single "scoreboard error" tells you a problem exists and nothing about which subsystem to open.

13. Illustrative UVM — the Scoreboard

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ILLUSTRATIVE (§8). Architecture only; factory boilerplate elided. The
// structure being reviewed is: identity-keyed outstanding map, generation
// check, four distinct error classes, and a check_phase that can FAIL a
// silent run.
class ucie_scoreboard extends uvm_scoreboard;
  // Expected transactions, keyed by SEMANTIC identity — not by arrival order.
  ucie_txn                 m_expected [int];
  int                      m_live_gen [int];   // generation currently live per id
  int unsigned             m_checked;          // how many comparisons happened
 
  // EXPECTED side — fed only from the input path (§9).
  function void write_expected(ucie_txn t);
    if (m_expected.exists(t.sem_id)) begin
      // The id was reallocated while an expectation was still outstanding.
      // This is a DUT-visible protocol error, not a testbench artefact.
      `uvm_error("SB_REALLOC",
        $sformatf("sem_id %0d reallocated while live (gen %0d -> %0d)",
                  t.sem_id, m_live_gen[t.sem_id], t.generation))
    end
    m_expected[t.sem_id] = t;
    m_live_gen[t.sem_id] = t.generation;
  endfunction
 
  // ACTUAL side — fed only from the output monitor.
  function void write_actual(ucie_txn a);
    ucie_txn e;
    if (!m_expected.exists(a.sem_id)) begin
      // Output for something never requested, or for an already-retired id.
      `uvm_error("SB_ORPHAN",
        $sformatf("actual sem_id %0d has no live expectation", a.sem_id))
      return;
    end
    if (a.generation != m_live_gen[a.sem_id]) begin
      // A completion from a PREVIOUS use of this id. Retiring on sem_id alone
      // here would silently retire the live transaction (D2).
      `uvm_error("SB_STALE_GEN",
        $sformatf("sem_id %0d: actual gen %0d != live gen %0d",
                  a.sem_id, a.generation, m_live_gen[a.sem_id]))
      return;
    end
    e = m_expected[a.sem_id];
    // compare() honours UVM_NOCOMPARE on observed transport fields (C4), so a
    // retry does not read as a data mismatch.
    if (!a.compare(e)) begin
      `uvm_error("SB_MISMATCH",
        $sformatf("sem_id %0d payload mismatch", a.sem_id))
    end
    m_checked++;
    m_expected.delete(a.sem_id);     // retire only on a matched, live, in-gen actual
  endfunction
 
  function void check_phase(uvm_phase phase);
    // Every expectation that never arrived. Without this, a DROPPED
    // transaction is simply an entry nobody looked at (D4).
    foreach (m_expected[id])
      `uvm_error("SB_INCOMPLETE",
        $sformatf("sem_id %0d expected but never observed", id))
 
    // The most important four lines in the class: a run that checked NOTHING
    // must FAIL. Otherwise a testbench whose stimulus never started reports a
    // clean pass, which is the most dangerous result available (D5).
    if (m_checked == 0)
      `uvm_error("SB_NOTHING_CHECKED",
        "scoreboard performed zero comparisons — stimulus or connectivity broken")
  endfunction
endclass

Architecture. An associative map keyed by semantic identity, a live-generation map beside it, and four named errors plus two end-of-test errors. Every element exists to make one specific bug distinguishable from the others.

State. m_expected holds outstanding expectations; m_live_gen records which use of each identifier is current; m_checked exists solely so a silent run can fail.

Event. Expectations are created on input acceptance; retirement requires an actual that is present, in-generation and matching. Three conditions, because failing any one of them is a different bug.

Contract. The scoreboard assumes the monitor publishes once per accepted transaction (§11) and that transport fields are excluded from comparison (C4). Both assumptions are review items in their own right — a scoreboard is only as trustworthy as the monitors feeding it.

Failure. Remove the generation check and a late completion from a recycled identifier retires a live transaction — the environment then reports a spurious SB_INCOMPLETE for the real transaction, sending debug toward a drop that never happened.

DV/debug. m_checked should be reported at end of test even when the run passes. A regression whose comparison count silently falls by 90 % after a refactor is broken, and the pass/fail summary will never tell you.

14. Area E — Reset and Recovery Under Live Traffic

#Must be trueEvidence that countsWeak evidenceFAIL if
E1recovery is injected with obligations OUTSTANDINGthe test, plus the outstanding count at injection"we test recovery"only idle recovery tested
E2the retention policy is assertedthe property from 27.1 §16policy untested either way
E3exactly one completion per semantic operation across recoverythe assertion and its coverageduplicate delivery undetected
E4reset scopes are tested separatelya test per scope (26.5 §7)one "reset test"scope confusion undetected
E5first-fault capture survives the reset under testthe captured value after resetevidence destroyed (27.6)
E6back-to-back and overlapping recoveries are exercisedthe coverage binsecond event dropped

Three readings.

E1 is the item that would have caught 26.5 §21's flagship integration failure, and it is almost always missing. A directed recovery test naturally drains the pipeline first — it is easier to write, easier to debug and completely blind to the bug. The review question is quantitative: "what was the outstanding count at the moment of injection?" If the answer is zero, the test proves nothing about retention.

E1 plus E2 together are what make a retention policy verified rather than assumed. Both policies are implementable (27.1 §15); the environment must assert the one that was chosen, and it must have been chosen.

And E6 exists because the second fault is the realistic one. A link that is recovering is a link that is marginal — so a second error during recovery is not an exotic corner, it is the expected environment. If the design drops the second event, it believes it is recovering and is not.

15. Area F — Fault Injection at Contract Boundaries

#Must be trueEvidence that countsWeak evidenceFAIL if
F1faults are injected where a contract existsthe boundary list, mapped to §6's requirementsrandom bit flipsinjection unrelated to contracts
F2sustained backpressure, not a single stallthe stall-duration coverage binsone-cycle stalls§11's monitor bug never exposed
F3delayed and out-of-order completionthe delay-distribution configfixed latencyordering assumptions untested
F4stale response after retirementthe injected scenarioSB_ORPHAN never exercised
F5credit starvation to zerothe coverage bin at zero creditsboundary never reached
F6configuration change with traffic in flightthe testconfig changes at idle26.5 §17's window untested
F7injection is legal for the interfacethe injection's justificationfabricated wire errors

Three readings.

F7 is a discipline item and it belongs in a UCIe chapter specifically. Do not fabricate protocol-level error conditions whose legality you have not established (§5). Inject at boundaries you own — backpressure, delay, credit starvation, configuration timing, reset scope — all of which are legal, realistic, and where the interesting bugs are.

F2 is the pairing that makes F-area worth running. A single-cycle stall exercises the stall path; sustained backpressure exercises everything downstream of it — the monitor (§11), the credit accounting, the outstanding window, the arbiter's fairness ageing. One-cycle stalls are why §11's bug reaches silicon.

And F4 is how you prove D3 is not decorative. SB_ORPHAN must be observed to fire at least once, in a directed test that injects a stale response. An error class that has never triggered is an untested branch of the testbench — and testbench code is code (27.2 §1).

16. Area G — Concurrency Crosses

The most common systematic gap in a mature DV plan: every feature tested, no two tested together.

CrossWhy it mattersFAIL if
backpressure × retryretry under a full pipeline is where identity confusion appearsnot covered
retry × recoverya retry in flight when recovery startsnot covered
config change × live traffic26.5 §17's split-configuration windownot covered
high outstanding × backpressurethe window and the credits interactnot covered
error × bidirectional trafficboth directions loaded during a faultnot covered
reset × pending work§14 E1 — the retention questionnot covered → gate FAIL
recovery × recoveryE6's second eventnot covered
credit exhaustion × recoverycredits at zero when state is rebuiltnot covered

Three readings.

The review question is not "do you have random tests?" Constrained-random stimulus can reach these crosses and frequently does not, because the constraints that make a test converge also make rare combinations rare. The evidence that counts is the cross coverage bin, not the presence of randomisation.

Row 6 is a gate-failing item on its own. Reset × pending work is 26.5 §21's failure and 27.1 §15's two-readings problem. An environment that has never injected reset with work outstanding cannot claim to have verified the retention contract, whatever its test count.

And a practical technique: if a cross is genuinely unreachable under the current constraints, write a directed test rather than declaring it covered. Then the bin is hit by construction, and the test documents the scenario for whoever inherits it.

17. Area H — Coverage That Means Something

#Must be trueEvidence that countsWeak evidenceFAIL if
H1coverage is of contracts, not linesthe requirement→coverpoint map (§6)"100 % code coverage"code coverage offered as closure
H2outstanding depth is binnedbins at 0, 1, mid, max−1, maxa single "outstanding" pointwindow boundary never reached
H3state and transition coverage on key FSMsthe transition bins, including illegal-attempt binsstate coverage onlytransitions unexercised
H4negative conditions are coveredbins for injected faults (§15)only happy paths measured
H5crosses from §16 are bins, not aspirationsthe cross coverage reportcrosses absent
H6exclusions have written reasonsthe exclusion file with justificationsblanket exclusionsunexplained exclusions
H7coverage is sampled from observationthe covergroup's source (B5)model-sampledmeasures imagination

Three readings.

H1 is the headline and it is worth being blunt about. 100 % code coverage means every line executed. It does not mean any line was checked, and against §8's mirrored predictor it is achievable with a scoreboard that cannot fail. Code coverage is a necessary hygiene metric and is not evidence of verification.

H2's max bin is the one that catches 27.1 §17's concurrency defect from the DV side. If the outstanding depth never reaches its maximum in any test, the design has never been driven hard enough to expose either the window limit or the allocator's behaviour at full.

And H6 turns exclusions from a loophole into a review artefact. An exclusion with a written reason is a decision; an exclusion without one is a hidden gap. The reviewer's job is to read the reasons, not to check the percentage.

18. Area I — Assertion Review, From the DV Side

27.2 §16 reviews assertions as code. This gate reviews them as evidence.

#Must be trueEvidence that countsWeak evidenceFAIL if
I1every assertion's antecedent is covereda cover property result per assertion"it's in the regression"vacuous assertions counted as closure
I2each critical assertion has been proven able to failthe mutation result (§22)never demonstrated
I3disable iff does not mask the interesting statethe disable expression, readdisabled when it matters (27.2 §17)
I4bounded eventualities have architectural boundsthe bound's derivation##[1:$]cannot fail in finite simulation
I5assumptions used in formal are justifiedthe assumption list and their rationaleproof of a design that cannot exist
I6assertion count is not offered as closure"we have 200 assertions"count presented as evidence

Two readings.

I1 is the item that converts an assertion count into an assertion result. A property whose antecedent never occurred has passed vacuously and proved nothing. The evidence is a cover result, and it is cheap: one cover property per non-trivial assertion.

And I5 is the highest-risk item in formal work. An over-constraining assumption can make a property provable about a design that cannot exist — the proof is real and the relevance is zero. Every assumption needs a one-line justification, and the reviewer reads those rather than the proof log.

19. Area J — Formal, and Where It Fits

PropertyFormal suitabilityWhy
no ID reuse while livestrongsmall state, deep bug (26.5 §9)
no double allocationstrongbounded, local
credit bounds and conservationstrongarithmetic invariant (25.6 §10)
atomic configuration commitstronga few states (26.5 §17)
FSM transition legalitystrong27.2 §12's illegal encodings
no duplicate semantic completiongood, if identity state is boundedmay need abstraction
end-to-end throughputNOT a formal propertyit is a performance claim — 27.4
full protocol conformanceimpractical at scalecomplexity

Three readings.

Rows 1–5 share a shape worth recognising: bounded state, deep consequence, hard to hit by simulation. Those are exactly the properties where formal earns its cost — and all five are the properties whose violations produce silent corruption rather than visible failure.

Row 7 is a boundary that gets crossed in review meetings. Formal cannot prove a throughput target. It can prove there is no deadlock and no state in which forward progress becomes impossible — which is valuable and is not a performance result (27.4 owns that).

And the review item is scoping, not adoption. "We use formal" is a review statement. "These five properties are proven, with these assumptions, and here is why each assumption holds" is evidence (I5).

20. Area K — What "Test Finished" Means

Accepted definition of doneVerdict
the sequence endednot sufficient
item_done() returnednot sufficient — driver-level, not semantic
objections dropped after the last itemnot sufficient25.8 §16
semantic outstanding == 0sufficient
an explicitly defined drain condition, with a bounded timeoutsufficient

Three readings.

item_done() means the driver finished driving. It does not mean the protocol finished. A test that ends there kills the simulation with transactions in flight — and the scoreboard's SB_INCOMPLETE entries are then indistinguishable from real drops (25.8 §16).

The drain must be bounded. An unbounded wait for outstanding == 0 hangs the regression when the design genuinely drops something — converting a clean failure into a timeout with no diagnosis. fork/join_any with a named DRAIN_TIMEOUT error is the shape, and the timeout must be a distinct error class from the drop it is detecting.

And the review question is one sentence: "what exactly is your end-of-test condition, and what error fires if it is not reached?" If the answer is "the sequence ends", every SB_INCOMPLETE in the regression is uninterpretable.

21. Area L — Debug Evidence From the Environment

A partial hand-off to 27.6, owned here because it is a testbench property.

#Must be trueFAIL if
L1a failure names the requirement, not just the signaltriage starts from zero
L2the transaction's semantic ID, generation and attempt are in the messagecannot correlate across components
L3scoreboard errors are distinct classes (D6)one generic error
L4the comparison count is reported on pass as well as failurea silent regression drift goes unnoticed
L5failing seeds are reproducible"it failed once" is not evidence

And L5 is a PASS/FAIL item in its own right. A failure that cannot be reproduced cannot be closed, and a regression whose seeds are not recorded produces exactly that. This is cheap infrastructure and it is the difference between a finding and a rumour.

22. Area M — Mutation Testing

The strongest single item in this gate, because it is the only one that tests the testbench.

Injected defectThe environment must fail with
duplicate delivery of one transactionSB_ORPHAN
drop one transactionSB_INCOMPLETE at end of test
complete with a stale generationSB_STALE_GEN
reallocate an id while liveSB_REALLOC
corrupt one payload byteSB_MISMATCH
skip one credit returnthe credit-conservation assertion
commit a config change mid-transactionthe epoch assertion (26.5 §17)
clear semantic state on link resetthe retention assertion (E2)

Three readings, and this section is what turns §4's right-hand column from an aspiration into a procedure.

Each row must fail for the expected reason. A mutation that fails with a different error is nearly as bad as one that passes — it means the environment detects that something is wrong and misattributes it, which produces a debug session pointed at the wrong subsystem.

A mutation that does not fail at all is a hole in the environment, and it is a FAIL for that requirement regardless of how much coverage it has. This is the single test that would have caught §8's mirrored predictor in one afternoon — inject a dropped transaction, observe a clean pass, and the topology bug is undeniable.

And the review evidence is the mutation report, not the assertion that mutations were run. Eight rows, eight expected error classes, eight observed results. That table is what a PASS in this area looks like.

23. Flagship Review Failure — Twenty Thousand Green Tests

The scenario that defines this gate.

What the team presents. 20,000 tests in the nightly regression. 100 % statement, branch and toggle coverage. Zero failures for six weeks. A verification plan with every row marked complete. Every conventional signal says PASS.

What the review does. Reads connect_phase (§7 B1) — fifteen lines, ten minutes.

What it finds. The predictor's analysis_export is connected to the output monitor (§8).

Question askedAnswerConsequence
Where does expected come from?the output monitorthe scoreboard compares the DUT to itself
Has the scoreboard ever failed?not since week 2 of bring-upconsistent with a checker that cannot fail
Has a mutation been run?nono evidence the checker works
What would a dropped transaction produce?nothing — no expectation is createddrops are invisible
What would a duplicate produce?two matching pairsduplicates are invisible

Gate decision: FAIL.

And the reasoning is worth stating precisely, because it is counter-intuitive.

The test count has zero value here. Not low value — zero. 20,000 runs of a checker that cannot fail produce exactly as much evidence as 0 runs, and consume six weeks of compute. Effort is not evidence (§4 row 6).

The coverage number has zero value for the same reason. 100 % code coverage against a mirrored predictor means every line was executed; nothing was checked. Coverage measures stimulus reach, and this gate is about checking.

And this is not a CONDITIONAL PASS, by §3's mechanical test. Could a downstream gate proceed assuming this closes? No — 27.4's performance claims, 27.5's interop evidence and every functional signoff downstream rest on the assumption that functional bugs would have been caught. The item invalidates downstream gates, so it is blocking, so it is FAIL.

The remediation is also worth naming, because "fix the connection" is not sufficient. Reconnect (§9), then re-run the full regression and expect failures — six weeks of unchecked design changes are now under examination for the first time. A team that reconnects the predictor and still sees zero failures has a second problem.

24. The Verification Gate Checklist

Thirty-eight items. Each has a section with the reasoning; this is the sheet you take into the room.

Plan and traceability

#QuestionFAIL if
1Does every 27.1 decision appear as a requirement row?a decision has no row (§6)
2Does every requirement have a checker, not just stimulus?stimulus-only rows exist
3Does every requirement have coverage proving it was reached?checker without coverage
4Does every row state what a failure would look like?column absent
5Does every open row have a named owner and a status?unowned gaps
6Sample five rows end to end — do all eight columns hold?two of five have gaps

Predictor and topology

#QuestionFAIL if
7Where does expected originate — read connect_phaseany path from the output monitor into the model
8Does the model import DUT packages or call DUT functions?shared implementation
9Are checker constants derived from the spec, not copied from RTL?constants copied from the design
10Has a DUT mutation been shown to fail the checker?never demonstrated
11Is coverage sampled from observation, not from the model?model-sampled

Monitors

#QuestionFAIL if
12Does the monitor sample valid && ready?samples the offer (§11)
13Is sampling through a clocking block with defined skew?direct interface reads
14Is the transaction cloned before write()?subscribers share a handle
15Are observed transport fields excluded from comparison?retries read as mismatches
16Is there a coverage bin for acceptance after a stall?backpressure never exercised

Scoreboard

#QuestionFAIL if
17Is matching by semantic identity rather than arrival order?FIFO compare without an ordering contract
18Is generation checked before retirement?stale completion retires a live entry
19Is an orphan actual an error?silently dropped
20Is an unmatched expectation an error at end of test?drops invisible
21Does a run with zero comparisons FAIL?an empty run reports PASS
22Are orphan / stale / realloc / mismatch distinct classes?one generic error

Reset, recovery and faults

#QuestionFAIL if
23Was recovery injected with obligations outstanding?only idle recovery tested
24What was the outstanding count at injection?the answer is zero
25Is the retention policy asserted, in the direction chosen?untested either way
26Is exactly one completion per semantic operation asserted across recovery?duplicates undetected
27Are the reset scopes tested separately?one generic reset test
28Is sustained backpressure exercised, not single-cycle stalls?one-cycle stalls only
29Is credit starvation to zero reached?boundary never hit
30Is fault injection confined to legal, owned boundaries?fabricated protocol errors

Concurrency, coverage and assertions

#QuestionFAIL if
31Are §16's crosses coverage bins with results?crosses aspirational
32Is reset × pending work covered?not covered → gate FAIL
33Is outstanding depth binned including max?window boundary unreached
34Do exclusions carry written reasons?blanket exclusions
35Is every assertion's antecedent covered?vacuous assertions counted
36Are formal assumptions justified individually?proof of an impossible design

Closure

#QuestionFAIL if
37What is the end-of-test condition, and what error fires if unmet?"the sequence ends"
38Is there a mutation report with expected and observed error classes?mutations never run

And the review technique matters as much as the list. Items 7, 10, 21, 23 and 38 are the five that most often change a gate decision, and they take under an hour combined. Run those first; if any of them fails, the remainder is diagnostic detail rather than a decision.

25. How the Verification Review Itself Fails

Failure modeLooks likeWhy it is fatal
reviewing results instead of structurereading the regression report§23 — a green report from a broken checker
accepting counts"20,000 tests, 200 assertions"effort is not evidence (§4)
accepting code coverage as closurea 100 % chartmeasures stimulus reach, not checking
reviewing the plan document, not the codeevery row marked completethe document cannot show connect_phase
conditional-passing a blocking itemschedule preserved§3 — a FAIL wearing a date

Two readings.

Row 4 is the one that lets §23 happen. A verification plan is a claim; connect_phase is a fact. A review that never opens the source code is reviewing the claim — and every environment's documentation says the predictor is independent.

And row 5 is the failure that compounds. A conditional pass on predictor independence lets 27.4, 27.5 and every functional signoff proceed on an assumption that is false. When it eventually closes, all of that work is invalidated — which is exactly the test §3 gives for whether an item is blocking.

26. Red Flags

Heard in reviewUsually meansAsk
"we have 20,000 tests"structure was never audited"has the scoreboard ever failed?"
"100 % code coverage"code coverage offered as closure"which contract crosses are covered?"
"the scoreboard checks it"B1 unverified"show me connect_phase"
"it's a reference model"independence assumed"what feeds its analysis export?"
"the values match the RTL"B3 — constants copied"derived from what?"
"we test recovery"idle recovery only"what was outstanding at injection?"
"random hits it eventually"crosses not binned"show me the cross bin"
"assertions all pass"possibly vacuous"is each antecedent covered?"
"the sequence completes"no semantic drain"what error fires if it does not drain?"
"it would catch that"no mutation evidence"has it ever caught that?"
"we'll close it next month"possible blocking item"can 27.4 proceed assuming this closes?"

And the single most useful question in the room is the third one. "Show me connect_phase" takes ten minutes, requires no preparation, and decides §23's gate outright.

27. Common Misconceptions

"A large regression is strong evidence." §23: 20,000 runs of a checker that cannot fail carry zero evidence.

"100 % code coverage means we're done." §17 H1: it means every line executed. Nothing about whether anything was checked.

"Our predictor is independent — it's a separate class." §7 B1: independence is a property of the topology, not of file organisation. Read connect_phase.

"The scoreboard has never failed, so the design is clean." §8: that is equally consistent with a scoreboard that cannot fail. Mutation testing distinguishes them.

"The monitor uses a clocking block, so sampling is fine." §10 C1: a clocking block fixes races, not semantics. valid alone still publishes duplicates under stall.

"A duplicate-delivery error means the RTL is broken." §11: it frequently means the monitor is. Check the sampling expression before opening the design.

"We test recovery." §14 E1: with what outstanding? Idle recovery proves nothing about retention.

"Formal proves the design is correct." §19: formal proves the properties you wrote, under the assumptions you made. Unjustified assumptions can prove things about a design that cannot exist.

"The test finished, so everything completed." §20: item_done() is a driver event. Semantic completion is a different fact.

"Conditional pass keeps us on schedule." §3: if a downstream gate cannot proceed on the assumption, it is a FAIL — and conditional-passing it invalidates their work too.

28. Understanding Check

29. Summary

Seven things.

Completeness is coverage of contracts, not code (§1, §17). 100 % code coverage means every line executed — nothing about whether anything was checked.

Independence is a property of the topology (§7–§9). Read connect_phase. A path from the output monitor into the predictor makes the scoreboard compare the DUT to itself, and both drops and duplicates become invisible.

Monitors must sample acceptance (§10–§11). valid alone publishes one transaction per stalled cycle — a testbench bug that accuses the RTL, and only under load.

A scoreboard needs four named errors plus two end-of-test checks (§12–§13), including the one that makes a run with zero comparisons FAIL — because a silent environment otherwise reports the cleanest possible pass.

Recovery must be injected with work outstanding (§14, §16). "What was the outstanding count at injection?"if zero, the retention contract is unverified.

Mutation testing is the only item that tests the testbench (§22). Eight defects, eight expected error classes, eight observed results. That table is what a PASS looks like.

And the gate has three decisions, not two (§3). CONDITIONAL PASS requires a bounded risk, a named owner, a closure date and no invalidation of a downstream gate — otherwise it is a FAIL with a schedule attached.