← Design Verification Interviews

Interview Question · Concept

Disable Iff and the Attempt Already in Flight

L0 FresherL1 Juniorsvaresetdisable iff

The Question

The interviewer asks

A colleague turns checking off during reset by adding !rst to the antecedent instead of using disable iff. What is the difference?

systemverilog
// "No checking while reset is asserted"
a_ack: assert property (@(posedge clk) !rst && req |-> ##3 ack) else errors++;
Reveal the Model Answer

!rst in the antecedent only stops new attempts from starting during reset. An attempt that started before reset keeps running and can fail when the design clears its state. disable iff (rst) abandons every attempt, including those in flight, as soon as the condition is true. An abandoned attempt counts as neither pass nor fail.

A request at 15, reset across the edge at 35
0123edge (ns)15253545reqrstackdisable iff abandons the attempt here!rst version still checks ack here: fail

The attempt started before reset. Only disable iff reaches it.

Disabled, Not FailedOne lane per request for disable iff (!rst_n) req |-> ##2 gnt.disable iff (!rst_n) req |-> ##2 gntMeasured on Verilator 5.052: one copy of the assertion per lane
attempt startspassfaildisabled by disable iff
Disabled, not failedreq @15, from edge 2 (t=15): passes at edge 4 (t=35). req @45, from edge 5 (t=45): is disabled between edges 5 and 6. req @85, from edge 9 (t=85): fails at edge 11 (t=105).edgetime15215325435545655765875985109511105clkrst_nreqgntattemptsreq @15req @15: passes at edge 4 (t=35)req @45req @45: is disabled between edges 5 and 6req @85req @85: fails at edge 11 (t=105)
  1. Edge 2 · t=15

    A request at 15 waits for gnt two edges later.

  2. Edge 4 · t=35

    gnt at 35: the attempt passes.

  3. Edge 5 · t=45

    A second request at 45 waits for gnt at 65.

  4. Edge 6 · t=55

    Reset arrived at 50, between edges 5 and 6. The attempt from 45 was disabled at that moment, and no verdict is ever reported for it.

  5. Edge 9 · t=85

    Reset ended at 70. A request at 85 starts a fresh attempt.

  6. Edge 11 · t=105

    No gnt at 105, so this attempt fails. Outside reset the rule still checks everything.

Read the lanes as text
  • req @15, from edge 2 (t=15): passes at edge 4 (t=35).
  • req @45, from edge 5 (t=45): is disabled between edges 5 and 6.
  • req @85, from edge 9 (t=85): fails at edge 11 (t=105).

Sampled values, edge 1 to 11: rst_n 1 1 1 1 1 0 0 1 1 1 1; req 0 1 0 0 1 0 0 0 1 0 0; gnt 0 0 0 1 0 0 0 0 0 0 0.

The program behind the lanes

The lanes come from running this program on Verilator 5.052. Each lane is a separate copy of gnt_in_2 that can start only at that lane's edge, so every verdict and its edge are read from that copy's own output.

module tb;
  logic clk = 0;
  always #5 clk = ~clk;                 // rising edges at 5, 15, 25, ...
  logic rst_n = 1, req = 0, gnt = 0;

  gnt_in_2: assert property (@(posedge clk) disable iff (!rst_n) req |-> ##2 gnt);

  initial begin
    @(negedge clk); req = 1;            // request at 15
    @(negedge clk); req = 0;
    @(negedge clk); gnt = 1;            // granted at 35
    @(negedge clk); gnt = 0; req = 1;   // request at 45
    @(negedge clk); req = 0; rst_n = 0; // reset from 50 to 70
    @(negedge clk);
    @(negedge clk); rst_n = 1;
    @(negedge clk); req = 1;            // request at 85
    @(negedge clk); req = 0;
    @(negedge clk);                     // no grant at 105
    @(negedge clk);
    $finish;
  end
endmodule

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Fresher)

A good fresher answer knows that disable iff turns checks off during reset. It adds that attempts already running are abandoned too.

Cross-Questions

Where the interviewer goes next. Open a node to practise that follow-up.

WhyWhat IfProve ItCompareScale It

  1. Disable Iff and the Attempt Already in Flight
  2. WhyWhy the Disable Condition Is Not SampledL1 JuniorL2 Mid-Level

    Everything else in a concurrent assertion is sampled at the clock. Why is the disable iff condition evaluated on current values?

    Reveal the Model Answer

    Reset is usually asynchronous: it can arrive with no clock running, and the design reacts at once. Suppose the disable condition were sampled. Then an attempt could still fail at the first edge after reset, because the sample came from just before reset rose. Using current values makes the check stop exactly when the design stops being bound by the rule.

    Self-Check

    Tick each key point you covered in your answer.

    Spec Misquote

    "It is sampled like everything else, one edge late."

    The standard makes the disable condition an exception to sampling; it acts as soon as it becomes true.

    Source Mehta, SystemVerilog Assertions and Functional Coverage (3rd ed.), §6.8 (PDF p104)

  3. What IfAn Assertion Under Reset for the Whole TestL2 Mid-Level

    What if reset stays asserted for the whole test? What does an assertion with disable iff (rst) report?

    systemverilog
    // rst remains asserted throughout this test.
    assert property (@(posedge clk) disable iff (rst) req |=> ack);
    Reveal the Model Answer

    Every attempt is disabled, so the assertion reports no passes and no failures. A summary that only lists failures looks clean, which is the same trap as vacuity. An antecedent cover with the same disable iff reads zero and exposes it.

    Disabled, Not FailedOne lane per request for disable iff (!rst_n) req |-> ##2 gnt.disable iff (!rst_n) req |-> ##2 gntMeasured on Verilator 5.052: one copy of the assertion per lane
    attempt startspassfaildisabled by disable iff
    Disabled, not failedreq @15, from edge 2 (t=15): passes at edge 4 (t=35). req @45, from edge 5 (t=45): is disabled between edges 5 and 6. req @85, from edge 9 (t=85): fails at edge 11 (t=105).edgetime15215325435545655765875985109511105clkrst_nreqgntattemptsreq @15req @15: passes at edge 4 (t=35)req @45req @45: is disabled between edges 5 and 6req @85req @85: fails at edge 11 (t=105)
    1. Edge 2 · t=15

      A request at 15 waits for gnt two edges later.

    2. Edge 4 · t=35

      gnt at 35: the attempt passes.

    3. Edge 5 · t=45

      A second request at 45 waits for gnt at 65.

    4. Edge 6 · t=55

      Reset arrived at 50, between edges 5 and 6. The attempt from 45 was disabled at that moment, and no verdict is ever reported for it.

    5. Edge 9 · t=85

      Reset ended at 70. A request at 85 starts a fresh attempt.

    6. Edge 11 · t=105

      No gnt at 105, so this attempt fails. Outside reset the rule still checks everything.

    Read the lanes as text
    • req @15, from edge 2 (t=15): passes at edge 4 (t=35).
    • req @45, from edge 5 (t=45): is disabled between edges 5 and 6.
    • req @85, from edge 9 (t=85): fails at edge 11 (t=105).

    Sampled values, edge 1 to 11: rst_n 1 1 1 1 1 0 0 1 1 1 1; req 0 1 0 0 1 0 0 0 1 0 0; gnt 0 0 0 1 0 0 0 0 0 0 0.

    The program behind the lanes

    The lanes come from running this program on Verilator 5.052. Each lane is a separate copy of gnt_in_2 that can start only at that lane's edge, so every verdict and its edge are read from that copy's own output.

    module tb;
      logic clk = 0;
      always #5 clk = ~clk;                 // rising edges at 5, 15, 25, ...
      logic rst_n = 1, req = 0, gnt = 0;
    
      gnt_in_2: assert property (@(posedge clk) disable iff (!rst_n) req |-> ##2 gnt);
    
      initial begin
        @(negedge clk); req = 1;            // request at 15
        @(negedge clk); req = 0;
        @(negedge clk); gnt = 1;            // granted at 35
        @(negedge clk); gnt = 0; req = 1;   // request at 45
        @(negedge clk); req = 0; rst_n = 0; // reset from 50 to 70
        @(negedge clk);
        @(negedge clk); rst_n = 1;
        @(negedge clk); req = 1;            // request at 85
        @(negedge clk); req = 0;
        @(negedge clk);                     // no grant at 105
        @(negedge clk);
        $finish;
      end
    endmodule
    

    Self-Check

    Tick each key point you covered in your answer.

  4. CompareDisabled, Vacuous and Failed in a ReportL1 JuniorL2 Mid-Level

    Compare a disabled attempt, a vacuous success and a failure. Which ones show up in a typical end-of-test summary?

    Reveal the Model Answer

    A failure runs the else action and is counted as an error. A vacuous success is a pass, and the pass action runs for it. So a pass count can be huge with nothing checked. A disabled attempt is neither, and most summaries do not show it at all. That is why a clean summary needs a separate count of real antecedent matches outside reset.

    OutcomeAction that runsIn a typical end-of-test summary
    FailureThe else actionYes, as an error
    Vacuous successThe pass actionYes, as a pass
    DisabledNoneUsually not shown at all

    Two of the three outcomes say nothing was checked, and one of them looks like a pass.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Disabled attempts are reported as vacuous."

    They are a separate outcome. A vacuous attempt completed and passed; a disabled one was abandoned.

    Source IEEE 1800-2017 §16.14.1

  5. Prove ItWriting the Cover That Proves an Assertion Checked SomethingL1 JuniorL2 Mid-Level

    Write the cover you would add next to assert property (@(posedge clk) disable iff (rst) req |=> ack);.

    Reveal the Model Answer

    Cover the antecedent with the same clock and reset: cover property (@(posedge clk) disable iff (rst) req);. A nonzero count shows the consequent was checked at least that often. Many teams also cover the whole scenario, req ##1 ack, to show the good path happened.

    Self-Check

    Tick each key point you covered in your answer.

    Missed Corner

    Writes the cover without the assertion's disable iff.

    Then it counts req during reset, when the assertion was disabled, and overstates how often the check ran.

    Source IEEE 1800-2017 §16.12 (disable iff); Mehta, SystemVerilog Assertions and Functional Coverage (3rd ed.) §6.8 p102-104

  6. Prove ItSolve 6.6.6: Hold the OfferSimulator-graded

    Show it, don't just say it: this Silicon Lab problem is graded by the simulator.

    Open Problem 6.6.6

  7. Scale ItWhich Reset Disables Which CheckerL3 Senior

    An SoC has a power-on reset, per-block soft resets and a warm reset that keeps some state. How do you choose the disable iff for each assertion?

    Reveal the Model Answer

    Disable each property with the reset that clears the state it talks about. A rule on a block's FIFO uses that block's reset, not the chip's. A warm reset must not disable rules about state that survives it. That state gets its own checks that it really survived. Write the mapping into the checker's parameters and review it with the design owner, because a too-broad disable silently hides checks.

    Self-Check

    Tick each key point you covered in your answer.

    What Interviewers Listen For (Senior)

    A good senior answer maps each rule to the reset that clears its state. It adds checks for state that must survive a warm reset, instead of disabling them.

    Wrong Altitude

    "Disable everything on any reset; it is the safe choice."

    It hides bugs in logic that should keep running, or keep state, across a partial reset. Those are classic reset escapes.

What People Get Wrong

Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.

Misconception

"Putting !rst in the antecedent does the same as disable iff."

It only gates where attempts start. In the twin an attempt from 15 is still waiting when reset hits at 35, and it fails at 45; disable iff abandons it.

Run It

A request at 15 owes an ack at 45. Reset is asserted across the edge at 35.

RUNVerilator · simulator service
Edit the code, then run it
Expected: failures=1 FAIL: !rst only stops new attempts; the one in flight failed after the reset
See the Fix
module tb;
  logic clk = 0, rst = 0, req = 0, ack = 0;
  int fails = 0;
  always #5 clk = ~clk;                 // rising edges at 5, 15, 25, ...
  // The fix: disable iff also abandons attempts already in flight.
  a_ack: assert property (@(posedge clk) disable iff (rst) req |-> ##3 ack) else fails++;
  initial begin
    @(negedge clk) req = 1;             // attempt at 15, ack due at 45
    @(negedge clk) req = 0;
    @(negedge clk) rst = 1;             // reset asserted across the edge at 35
    @(negedge clk) rst = 0;
    repeat (4) @(negedge clk);
    $display("failures=%0d", fails);
    if (fails == 0) $display("PASS: the reset abandoned the attempt that was in flight");
    $finish;
  end
endmodule

Prints: failures=0 PASS: the reset abandoned the attempt that was in flight

Tool as Truth

"A reset glitch between two clock edges is ignored, because assertions only look at edges."

The disable condition is evaluated on current values, not samples, so a pulse between edges disables attempts in flight. Verilator 5.052 ignores such a pulse, which is a tool limitation, not the rule.

Source ASIC Point engine notes (Verilator 5.052 SVA probes), row "disable iff: reset pulse between two edges"

Misconception

"A disabled attempt counts as a pass."

It is neither a pass nor a failure, so a test spent entirely in reset reports no passes and no failures.

Source IEEE 1800-2017 §16.12

Learn It, Then Prove It