A "green regression" is not sign-off — sign-off is a structured checklist proving the testbench actually asked every question, and this chapter is that checklist for APB. You have built the pieces across this module: a rules catalogue, assertions, a monitor, a scoreboard, a coverage model, and negative tests. The single idea to carry: a passing run only proves the environment checks everything in its plan — so the review checklist verifies the plan itself is complete, non-vacuous, and closed, category by category, before anyone signs the block off. Every item below is stated as what to check, why it matters, and the failure it catches — because a checklist whose items you cannot justify is a ritual, and a ritual escapes silicon.
1. Problem statement
The problem is rendering "is this APB block verified?" as a finite, categorised, auditable checklist — one whose every item has a concrete pass/fail test and names the specific escape it prevents — so that sign-off is a decision made against evidence, not a feeling made against a green log.
Verification sign-off is a comparison: observed testbench state versus a definition of done. For that comparison to be sound, the definition of done has to be made concrete and itemised, and it must span every axis on which an APB testbench can be incomplete:
- It must cover presence, not just result. "All assertions pass" is worthless if the stability assertion was never written. The checklist's first job is to confirm each required check exists — a protocol assertion per catalogue rule, a scoreboard, a coverage model — before it ever asks whether they passed.
- It must cover non-vacuity, not just presence. An assertion that exists and passes but never armed proves nothing. A coverpoint that exists but was never hit closes nothing. The checklist must demand evidence that every check actually fired — antecedents reached, bins hit.
- It must cover level, not just RTL. A glitch on
PREADYand a reset-polarity X are invisible in zero-delay RTL and only surface at gate-level. A checklist that stops at "RTL clean" signs off on bugs it structurally cannot see.
So the job is not "run more tests." It is to enumerate the completeness conditions an APB testbench must satisfy — grouped so the review is auditable per category — and attach to each the escape it exists to prevent. That enumerated, justified, categorised list is the deliverable.
2. Why previous knowledge is insufficient
This module built each verification component in isolation, and each is now a dependency this checklist audits — but none of them is the checklist itself.
- Chapter — assertions taught how to encode one catalogue rule as one SVA property, and even how to spot a vacuous pass. That is how to build a correct property. The checklist is a different job: confirming, at sign-off, that the assertion for every rule is present, correct, and demonstrably non-vacuous — the audit, not the authoring.
- Chapter — functional coverage taught how to model the transfer space in coverpoints and crosses. That is how to build the model. The checklist asks the sign-off question the model can't ask itself: are the boundary bins present, is the read×write cross closed, and did closure happen — or did the run stop at 92% with the corners uncovered?
- Chapter — negative testing and corner cases taught how to inject errors and reach boundary states. Those are stimulus techniques. The checklist verifies the outcome: that error injection actually fired
PSLVERRand the scoreboard predicted it, that reset-during-transfer left the DUT idle, that the corner was both reached and checked.
The gap is this: prior chapters taught the components. They did not assemble the sign-off gate — the categorised list that proves the assembled environment is complete, non-vacuous, closed, and gate-level clean. Building that gate is this chapter; carrying its verdict into the interview room is verification interview questions.
3. Mental model
The model: the testbench is signed off layer by layer, bottom to top, and each layer's green run must prove a specific thing before the layer above it means anything. A green assertion layer is meaningless if the stimulus below it never drove the scenario; a closed coverage number is meaningless if the assertions above it passed vacuously. So the review walks the stack and, at each layer, asks not "did it pass?" but "what did this green run prove, and what would still escape?"
The stack has six layers, and the checklist is the set of proof obligations at each:
- Stimulus + reference model (bottom). Proves data integrity — every legal transfer driven and independently predicted by a self-checking scoreboard, never eyeballed.
- Protocol assertions. Prove the catalogue rules hold on every edge — stable
PADDR,PENABLEonly in ACCESS, one-hotPSEL, bounded completion, ready-implies-valid,PSLVERRrules. - Assertion non-vacuity. Proves every assertion armed — no property passed while never testing its consequent.
- Functional coverage. Proves the space was exercised — address boundaries, response codes, wait bins, crosses.
- Negative + corner cases. Prove the illegal and boundary regions were driven and handled — error injection, reset-during-transfer, zero-idle back-to-back, max-wait.
- Gate-level (top). Proves the RTL-invisible bugs — glitch, reset-X — cannot survive real delays.
Three refinements sharpen the model:
- Presence, non-vacuity, and closure are three distinct gates, not one. A check can exist (presence) yet never arm (vacuity) yet arm-but-under-cover (closure). The review must pass all three at every layer; teams that conflate them sign off on green that proves nothing.
- A gap at any layer caps the whole sign-off. Sign-off is a minimum over layers, not a sum. A perfect coverage model over a vacuous assertion set is not "mostly signed off" — it is unsigned, because the assertion layer proves nothing.
- The escape always lives at the weakest layer, and it is usually the unglamorous one — a missing boundary bin, a vacuous liveness property, a skipped gate-level pass. The review's value is finding the weakest layer before silicon does.
4. Real SoC implementation — the checklist
This is the deliverable. Each item is stated as what to check and why / the gap it catches, grouped by category. Walk it top to bottom at sign-off; any row you cannot mark "done, with evidence" blocks closure. The nine categories map directly to the six sign-off layers of Figure 1, with non-vacuity and closure broken out because they are the silent-escape holes.
Category 1 — Protocol assertions present & correct (per the rules catalogue, rules from AMBA APB IHI 0024C §2.1):
| Category | Check | Why / gap caught |
|---|---|---|
| Protocol assertions | PADDR/PWRITE/PWDATA/PSTRB stable across SETUP+ACCESS until completion (` | =>+$stable`) |
| Protocol assertions | PENABLE low in SETUP, high only in ACCESS; `PENABLE | -> PSEL` |
| Protocol assertions | One-hot / one-hot-0 PSEL across the select vector ($onehot0(psel_vec)) | Catches a decode that selects two slaves at once — bus contention on PRDATA |
| Protocol assertions | Bounded completion: `(psel && penable) | -> ##[1:N] pready` |
| Protocol assertions | Ready-implies-data-valid: completing read ` | -> data_valid` |
| Protocol assertions | PSLVERR only at completion (`pslverr | -> psel && penable && pready`) and known, not X |
Category 2 — Assertion non-vacuity (layer 3):
| Category | Check | Why / gap caught |
|---|---|---|
| Non-vacuity | Every assert has a paired cover property on its antecedent, and every such cover is HIT | Catches a vacuous assertion that "passes" while never once arming — the dominant silent escape |
| Non-vacuity | Non-vacuous evaluation count > 0 for every property in the regression report | Catches a too-narrow antecedent (e.g. read-only gate on a write rule) that never fires |
Category 3 — Functional coverage (layer 4):
| Category | Check | Why / gap caught |
|---|---|---|
| Coverage | Address bins include the first and last legal register and the first illegal address past the top | Catches an off-by-one decode / missing-PSLVERR-on-overflow bug at the map boundary |
| Coverage | Response-code bins for OKAY and ERROR both hit | Catches an error path that was never exercised — PSLVERR handling unverified |
| Coverage | Wait-state bins 0..N (zero-wait, 1, mid, worst-case N) all hit | Catches wait handling verified only at one latency — the pipelining bug at N |
| Coverage | Read × write cross closed, and back-to-back (zero-idle) bin hit | Catches direction- or abutment-specific bugs a marginal coverpoint hides |
Category 4 — Scoreboard / reference model (layer 1):
| Category | Check | Why / gap caught |
|---|---|---|
| Scoreboard | A self-checking reference model predicts every transfer's data/response and compares (not waveform inspection) | Catches wrong-data / wrong-response escapes that assertions (which check protocol, not values) cannot |
| Scoreboard | Read-after-write to the same address returns the just-written value | Catches a register that returns stale pre-write data |
Category 5 — Negative / error injection (layer 5):
| Category | Check | Why / gap caught |
|---|---|---|
| Negative | Illegal-address access is driven and the DUT returns PSLVERR (scoreboard predicts ERROR) | Catches a decode that silently aliases or returns OKAY for an unmapped address |
| Negative | Write to a read-only / reserved register is injected and rejected per spec | Catches a register that accepts illegal writes |
Category 6 — Corner cases (layer 5):
| Category | Check | Why / gap caught |
|---|---|---|
| Corner | Reset-during-transfer ($fell(presetn) mid-ACCESS) leaves DUT idle, no half-commit | Catches a write that half-commits or an FSM stuck in a stale state on abort |
| Corner | Zero-idle back-to-back: PENABLE drops between abutting transfers | Catches a merged/missed transfer when a new SETUP follows completion immediately |
| Corner | Maximum wait / PREADY stuck low is driven; bounded-completion assertion fires | Catches a silent bus hang with no manager timeout |
Category 7 — X / reset checks (layer 2/5):
| Category | Check | Why / gap caught |
|---|---|---|
| X / reset | PENABLE, PSEL, PREADY, PSLVERR never X while selected (!$isunknown) | Catches an undriven signal / X-propagation into the sample window |
| X / reset | Out of reset, control outputs are a known, legal state on the correct polarity | Catches a reset-polarity bug or an undriven-out-of-reset hang |
Category 8 — Gate-level pass (layer 6):
| Category | Check | Why / gap caught |
|---|---|---|
| Gate-level | Assertions + scoreboard re-run on the SDF-annotated netlist | Catches the combinational PREADY glitch and reset-X that are invisible in zero-delay RTL |
Category 9 — Coverage closure & sign-off criteria (the gate):
| Category | Check | Why / gap caught |
|---|---|---|
| Sign-off | 100% of reviewed coverage goals closed (or every gap has a signed waiver with rationale) | Catches "92% is close enough" — the uncovered 8% is where corners live |
| Sign-off | Every catalogue rule ID traces to a present, passing, non-vacuous assertion | Catches an unowned rule — a rule with no assertion is an unchecked rule |
The single most useful item on this list is not any protocol assertion — it is the non-vacuity gate, because a vacuous assertion reads as green and is therefore worse than a missing one. Here is a representative sign-off check that fuses the bounded-completion liveness property with its anti-vacuity cover, exactly as the review demands:
// SIGN-OFF: bounded completion, written NON-VACUOUSLY, with its anti-vacuity cover.
// The antecedent is (psel && penable) ONLY -- it must NOT include pready, or the
// property arms after completion and can never prove completion happens.
property p_bounded_completion;
@(posedge pclk) disable iff (!presetn)
(psel && penable) |-> ##[1:N] pready; // N = slave's worst-case wait spec
endproperty
a_bounded_completion: assert property (p_bounded_completion); // liveness: catches the hang
// Anti-vacuity: the antecedent MUST be reachable, and the wait region MUST be exercised.
// A 0% hit on either cover means the assertion never tested a hang -> SUITE FAILURE.
c_access_armed: cover property (@(posedge pclk) disable iff (!presetn)
(psel && penable)); // property armed?
c_wait_exercised: cover property (@(posedge pclk) disable iff (!presetn)
(psel && penable && !pready)); // a real wait seen?
// Sign-off rule enforced at review, not runtime:
// a_bounded_completion PASS AND c_access_armed HIT AND c_wait_exercised HIT.
// Missing any one => the "pass" is vacuous or the hang was never stimulated => NOT signed off.Two facts make this the right shape. First, the property and its covers are reviewed as a unit — a green a_bounded_completion with a 0%-hit c_wait_exercised is not a pass, because the assertion never saw a wait state and therefore never tested the hang it exists to catch. Second, the antecedent excludes pready deliberately: gate the liveness property on (psel && penable) and it proves "completion will happen"; gate it on (psel && penable && pready) and it only arms after completion — vacuously true, and the exact wrong-reason pass Figure 2 dissects.
5. Engineering tradeoffs
The checklist is the deliverable; the judgement is how strict each gate is and where the effort goes.
| Decision | Option A | Option B | When to choose which |
|---|---|---|---|
| Coverage closure bar | 100% of reviewed goals | "high enough" (e.g. 95%) | 100% of a reviewed goal set — the gap is always where corners hide; waive explicitly, never implicitly |
| Vacuity policy | Every assert paired with a HIT cover | Trust the pass count | Paired cover — a green vacuous assertion is worse than none; this is the highest-value gate |
| Gate-level scope | Assertions + scoreboard re-run on netlist | RTL only | Gate-level for glitch/reset-X classes — RTL cannot see them, period |
| Scoreboard authority | Independent reference model | Reuse DUT's own logic as the model | Independent model — a scoreboard that borrows the DUT's arithmetic can't catch the DUT's bug |
| Sign-off evidence | Rule-ID → check traceability map | Pass/fail count | Traceability — a count hides the unowned rule; the map exposes it |
The throughline: every gate trades review effort now against an escape later, and the cheapest escapes to prevent are non-vacuity and boundary coverage — a one-line cover and one boundary bin each. The expensive gate, gate-level, is non-negotiable for exactly two bug classes (glitch, reset-X) and skippable for none of the others. And the subtle one, scoreboard independence, is where teams quietly cheat: a reference model that reuses the DUT's own decode or arithmetic will agree with the DUT's bug and sign off on it.
6. Common RTL mistakes
7. Debugging scenario
The signature sign-off failure is not a red regression — it is a green one that shipped a bug, because a checklist item was marked "done" without evidence. Take the most common instance: a bounded-completion assertion that passed vacuously.
- Observed symptom: a peripheral passes its full regression — "all assertions PASS, coverage closed" — and ships. In the lab, under a specific software poll of a slow status register, the bus intermittently hangs:
PSELandPENABLEstay high, no completion, the CPU wedged. The exact failure the bounded-completion assertion was written to catch. - Waveform / report clue: the regression log shows
a_bounded_completion: PASS. But pulling the assertion's coverage reveals the tell: its antecedent cover has 0 non-vacuous evaluations. The property compiled, "passed," and never once armed across the entire regression. - Root cause: the property was written
(psel && penable && pready) |-> ##[1:N] pready. The antecedent includespready— so it only arms on cycles where completion has already happened, at which point##[1:N] preadyis trivially satisfiable. The property can never test the hang, because it only evaluates after the thing it was meant to prove. It is vacuously green. - Correct SVA: gate the liveness property on
(psel && penable)alone so it arms in ACCESS before completion, and pair it with a cover that a wait state was actually seen:Azvya Education Pvt. Ltd.VLSI MentorSnippetproperty p_bounded_completion; @(posedge pclk) disable iff (!presetn) (psel && penable) |-> ##[1:N] pready; // arms before completion, proves it happens endproperty a_bounded_completion: assert property (p_bounded_completion); c_wait_exercised: cover property (@(posedge pclk) disable iff (!presetn) (psel && penable && !pready)); // must HIT - Verification / process fix: add the non-vacuity gate to sign-off — every
asserthas a paired antecedentcover, and a 0%-hit cover blocks closure. The bug here was never the RTL alone; it was a checklist item ("bounded completion asserted") marked done without the evidence ("and its antecedent was reached") that makes it real. - Debug habit: when a "fully verified" block hangs or corrupts on exactly the failure an assertion supposedly covers, do not assume the assertion is wrong — check whether it ever fired. Read the non-vacuous evaluation count first. A PASS with zero non-vacuous evaluations is the fingerprint of a vacuous property, and the fix is to reach the antecedent and prove it with a cover.
8. Verification perspective
The checklist's own credibility is a verification deliverable — it is verified the way a plan is, by traceability and evidence, not by re-running the DUT. Three properties make it trustworthy, and the sign-off SVA below shows the non-vacuity gate in force.
- Traceability, both directions. Every catalogue rule ID points to a present, passing, non-vacuous assertion; every assertion names the rule it owns. A rule with no owner is an unchecked rule; an assertion with no rule is either redundant or a hidden rule that belongs in the catalogue. Sign-off reviews this map, not the pass count.
- Evidence over assertion of completeness. "Coverage closed" must be backed by a report showing each reviewed goal at 100% (or a signed waiver); "assertions non-vacuous" must be backed by every antecedent cover HIT. A checklist item without attached evidence is a claim, not a gate.
- Level-correct sign-off. The glitch and reset-X classes are re-checked at gate-level; the value classes are checked by the scoreboard; the protocol classes by assertions. Signing off the RTL layer does not sign off the gate-level layer — they are distinct proof obligations.
The core sign-off assertion, showing bounded-completion made non-vacuous — the one property whose presence, correctness, and non-vacuity the review must all confirm:
// Non-vacuous bounded completion + its anti-vacuity witness (AMBA APB IHI 0024C §2.1).
property p_ready_implies_valid; // SAFETY: no early complete on stale data
@(posedge pclk) disable iff (!presetn)
(psel && penable && pready && !pwrite) |-> data_valid_q;
endproperty
a_ready_implies_valid: assert property (p_ready_implies_valid);
c_read_completion: cover property (@(posedge pclk) disable iff (!presetn)
(psel && penable && pready && !pwrite)); // must HITThe point: verify the checklist by traceability and attached evidence, exploit gate-level for the two RTL-invisible classes, and treat a non-vacuity or coverage-closure gap as unsigned, not "mostly signed" — because sign-off is a minimum over the checklist, and the escape lives at the weakest item.
9. Interview discussion
"How do you know an APB block is done being verified?" is a staff-level sign-off question, and the answer that signals real experience is "a green regression isn't the answer — a completed review checklist is."
Frame it as presence, non-vacuity, closure, and level, category by category. Every catalogue rule has a present assertion (stable PADDR, PENABLE only in ACCESS, one-hot PSEL, bounded completion, ready-implies-valid, PSLVERR rules); every assertion is non-vacuous (paired antecedent cover HIT — the single highest-value gate, because a vacuous assertion reads green and is worse than none); coverage is closed against a model whose bins include the address boundaries, both response codes, wait bins 0..N, and the read×write cross; and the level is right — the glitch and reset-X classes only surface at gate-level, so RTL clean is necessary, not sufficient. Land the depth points: assertions check protocol, the scoreboard checks values — a testbench without a self-checking reference model is blind to wrong-data escapes; negative tests must check the outcome — injecting an illegal address proves nothing unless the scoreboard predicted PSLVERR; and sign-off is a minimum over the checklist — a gap at any layer caps it. Closing with "the two escapes I've actually shipped were a vacuous bounded-completion assertion that passed for the wrong reason and a coverage model missing the top-register boundary bin — so my sign-off gate now hard-fails on any 0%-hit antecedent cover and requires explicit first/last/illegal address bins" signals silicon scars, not spec reading.
10. Practice
- Bin the gap. Given three sign-off reports — "assertion passes but its antecedent cover is 0%," "coverage 100% but no bin at the last register," and "RTL clean but no gate-level run" — name the category each belongs to and the specific escape each hides.
- Fix the vacuous property. Given
(psel && penable && pready) |-> ##[1:N] pready, explain why it passes vacuously and rewrite the antecedent so it genuinely proves bounded completion. Add the cover you'd pair with it. - Design the boundary bins. For a register map from
BASEtoTOP, write the address coverpoint bins that make closure demand the first legal, last legal, and first illegal address — and state the decode bug each catches. - Justify the scoreboard. Explain why a reference model that reuses the DUT's own decode logic cannot sign off the block, and what an independent model must predict for a read-after-write to the same address.
- Pick the level. For each of stability-drift,
PREADYglitch, ready-too-early, and reset-X, state whether an RTL run can sign it off or whether it needs gate-level / a never-X check, and the checklist item that owns it.
11. Q&A
12. Key takeaways
- A green regression is not sign-off. It only proves the environment checks everything in its plan and that passed — the review checklist audits the plan itself for presence, non-vacuity, closure, and level, category by category.
- The nine categories — protocol assertions, non-vacuity, functional coverage, scoreboard, negative tests, corner cases, X/reset, gate-level, and closure — map to the six sign-off layers, and sign-off is a minimum over them: a gap at any layer caps the whole thing.
- Non-vacuity is the highest-value gate. A vacuous assertion reads green and is worse than a missing one — pair every
assertwith acoveron its antecedent and treat a 0% hit as a suite failure. The classic APB instance is a bounded-completion property whose antecedent wrongly includespready. - Assertions check protocol; the scoreboard checks values; gate-level checks the RTL-invisible. A testbench needs all three — assertions can't catch wrong data, and RTL can't catch the
PREADYglitch or reset-X. - Coverage closure is only as complete as the model's bins. Audit the bins against the register map — explicit first-legal, last-legal, and first-illegal address bins — or a 100% number closes green over the boundary corner.
- The two escapes that ship most are a vacuous liveness assertion that passes for the wrong reason and an uncovered boundary bin — the checklist's whole value is finding the weakest item before silicon does, per the completion contract of AMBA APB IHI 0024C §2.1.