← Design Verification Interviews

Interview Question · Concept

Accept_on, Reject_on and Disable Iff

L2 Mid-LevelL3 Seniorsvaabortreset

The Question

The interviewer asks

A burst can be aborted half way. Compare accept_on, reject_on and disable iff for a burst rule. What does each report when the abort comes?

Reveal the Model Answer

accept_on (c) ends the attempt as a pass when c is true. reject_on (c) ends it as a failure. disable iff (c) ends it as neither: the attempt is simply cancelled. Use accept_on or disable iff when an abort is legal. Use reject_on when the condition must never happen during the burst. The sync_ forms sample the condition only at clock edges.

A Flush Accepts the Pending CompletionOne lane per burst for start |=> sync_accept_on (flush) ##1 done.start |=> sync_accept_on (flush) ##1 doneMeasured on Verilator 5.052: one copy of the assertion per lane
attempt startspassfailaborted by accept_on or reject_on
A flush accepts the pending completionstart @15, from edge 2 (t=15): passes at edge 4 (t=35). start @65, from edge 7 (t=65): is aborted at edge 8 (t=75) (accepted). start @115, from edge 12 (t=115): fails at edge 14 (t=135).edgetime1521532543554565576587598510951110512115131251413515145clkstartflushdoneattemptsstart @15start @15: passes at edge 4 (t=35)start @65start @65: is aborted at edge 8 (t=75) (accepted)acceptedstart @115start @115: fails at edge 14 (t=135)
  1. Edge 2 · t=15

    Burst 1 starts at 15 and owes a done at 35.

  2. Edge 4 · t=35

    done at 35: pass.

  3. Edge 8 · t=75

    Burst 2 starts at 65, then flush is sampled at 75. The obligation is accepted there, so the missing done at 85 is no failure.

  4. Edge 14 · t=135

    Burst 3 starts at 115 with no flush and no done at 135: it fails.

Read the lanes as text
  • start @15, from edge 2 (t=15): passes at edge 4 (t=35).
  • start @65, from edge 7 (t=65): is aborted at edge 8 (t=75) (accepted).
  • start @115, from edge 12 (t=115): fails at edge 14 (t=135).

Sampled values, edge 1 to 15: start 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; flush 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0; done 0 0 0 1 0 0 0 0 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 done_or_flush 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 start = 0, busy = 0, err = 0, flush = 0, done = 0;

  done_or_flush: assert property (@(posedge clk) start |=> sync_accept_on (flush) ##1 done);

  initial begin
    @(negedge clk); start = 1;              // burst 1 starts at 15
    @(negedge clk); start = 0; busy = 1;    // busy at 25, 35, 45
    @(negedge clk); done = 1;               // done at 35
    @(negedge clk); done = 0;
    @(negedge clk); busy = 0;
    @(negedge clk); start = 1;              // burst 2 starts at 65
    @(negedge clk); start = 0; busy = 1; flush = 1;  // flush at 75
    @(negedge clk); err = 1; flush = 0;     // err at 85
    @(negedge clk); err = 0;
    @(negedge clk); busy = 0;
    @(negedge clk); start = 1;              // burst 3 starts at 115
    @(negedge clk); start = 0; busy = 1;
    @(negedge clk);
    @(negedge clk);                         // no done at 135
    @(negedge clk); busy = 0;
    $finish;
  end
endmodule
An Error Rejects the Burst in ProgressOne lane per burst for start |=> sync_reject_on (err) busy[*3].start |=> sync_reject_on (err) busy[*3]Measured on Verilator 5.052: one copy of the assertion per lane
attempt startspassaborted by accept_on or reject_on
An error rejects the burst in progressstart @15, from edge 2 (t=15): passes at edge 5 (t=45). start @65, from edge 7 (t=65): is aborted at edge 9 (t=85) (rejected).edgetime1521532543554565576587598510951110512115131251413515145clkstartbusyerrattemptsstart @15start @15: passes at edge 5 (t=45)start @65start @65: is aborted at edge 9 (t=85) (rejected)rejected
  1. Edge 2 · t=15

    Burst 1 starts at 15 and needs busy on the next three edges.

  2. Edge 5 · t=45

    busy held at 25, 35 and 45: burst 1 passes.

  3. Edge 7 · t=65

    Burst 2 starts at 65.

  4. Edge 9 · t=85

    err is sampled at 85 while burst 2 runs. The attempt is rejected here, although busy is still high.

Read the lanes as text
  • start @15, from edge 2 (t=15): passes at edge 5 (t=45).
  • start @65, from edge 7 (t=65): is aborted at edge 9 (t=85) (rejected).

Sampled values, edge 1 to 15: start 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; busy 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1; err 0 0 0 0 0 0 0 0 1 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 burst_clean 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 start = 0, busy = 0, err = 0, flush = 0, done = 0;

  burst_clean: assert property (@(posedge clk) start |=> sync_reject_on (err) busy[*3]);

  initial begin
    @(negedge clk); start = 1;              // burst 1 starts at 15
    @(negedge clk); start = 0; busy = 1;    // busy at 25, 35, 45
    @(negedge clk); done = 1;               // done at 35
    @(negedge clk); done = 0;
    @(negedge clk); busy = 0;
    @(negedge clk); start = 1;              // burst 2 starts at 65
    @(negedge clk); start = 0; busy = 1; flush = 1;  // flush at 75
    @(negedge clk); err = 1; flush = 0;     // err at 85
    @(negedge clk); err = 0;
    @(negedge clk); busy = 0;
    @(negedge clk); start = 1;              // burst 3 starts at 115
    @(negedge clk); start = 0; busy = 1;
    @(negedge clk);
    @(negedge clk);                         // no done at 135
    @(negedge clk); busy = 0;
    $finish;
  end
endmodule

One burst, aborted after one busy cycle, checked three ways.

RUNVerilator · simulator service
Edit the code, then run it
Expected: accept_on failures=0 reject_on failures=1 disable iff failures=0

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Mid-Level)

A good mid-level answer gives the three verdicts. It picks accept_on for a legal abort and reject_on for a forbidden event.

Cross-Questions

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

WhyWhat IfProve ItCompareScale It

  1. Accept_on, Reject_on and Disable Iff
  2. WhyWhy Three Ways to Stop an AttemptL2 Mid-Level

    Why does SVA need three ways to stop an attempt instead of one?

    Reveal the Model Answer

    They answer different questions. Reset means "this cycle does not count", so the attempt should vanish from the results. A legal abort means "the transfer ended properly", so it is a pass. A forbidden event means "this must never happen now", so it is a failure. One operator could not say all three.

    OperatorThe attempt ends asUse it for
    disable iff (c)Neither pass nor fail: it is cancelledReset: this cycle does not count
    accept_on (c)A passA legal abort: the transfer ended properly
    reject_on (c)A failureA forbidden event during the burst

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "accept_on is the same as disable iff with a different name."

    An accepted attempt counts as a pass and runs the pass action. A disabled attempt counts as nothing.

    Source Mehta, SystemVerilog Assertions and Functional Coverage (3rd ed.), §20.16

  3. What IfReset and a Forbidden Event TogetherL2 Mid-LevelL3 Senior

    What if reset and the forbidden event of a reject_on arrive in the same cycle?

    Reveal the Model Answer

    disable iff wins, because it sits outside the whole property. The attempt is disabled and counts as neither pass nor fail. That is usually right, since reset means the cycle does not count. But a real error in a reset cycle is hidden, so check reset sequencing separately.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "reject_on is checked first because it is the inner operator."

    disable iff sits outside the whole property. When its condition holds, nothing inside reports.

    Source IEEE 1800-2017 §16.12

  4. CompareAn Abort in Front of the Property vs in the ConsequentL2 Mid-LevelL3 Senior

    Compare sync_reject_on (err) start |=> busy[*3] with start |=> sync_reject_on (err) busy[*3].

    Reveal the Model Answer

    In front of the whole property, the abort also covers attempts whose antecedent did not match. So an err during an idle cycle fails the attempt that starts there. Inside the consequent, the abort only applies after start matched. Put it in the consequent unless the condition is forbidden at every cycle.

    Self-Check

    Tick each key point you covered in your answer.

    Missed Corner

    "The placement does not matter; the abort is checked either way."

    At the top it applies to every attempt, vacuous ones included, so an idle-time err becomes a failure.

    Source IEEE 1800-2017 §16.12.14

  5. Prove ItSolve 6.6.11: A Read-Channel Assertion SuiteSimulator-graded

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

    Open Problem 6.6.11

  6. 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

"reject_on just stops the check, like a reset."

It ends the attempt as a failure. The twin aborts a legal burst and reject_on reports it.

Run It

A legal abort checked with sync_reject_on.

RUNVerilator · simulator service
Edit the code, then run it
Expected: failures on a legal abort=1 FAIL: reject_on turns the abort into a failure; it does not just stop the check
See the Fix
module tb;
  logic clk = 0, start = 0, busy = 0, abort = 0;
  int fails = 0;
  always #5 clk = ~clk;
  // An aborted burst is legal; the checker should stop checking it.
  // The fix: accept_on ends the attempt as a pass when abort comes.
  p_burst: assert property (@(posedge clk) start |=> sync_accept_on (abort) busy[*3]) else fails++;
  initial begin
    @(negedge clk) start = 1;
    @(negedge clk) begin start = 0; busy = 1; end
    @(negedge clk) begin busy = 0; abort = 1; end   // legal abort half way
    @(negedge clk) abort = 0;
    repeat (3) @(negedge clk);
    $display("failures on a legal abort=%0d", fails);
    if (!fails) $display("PASS: accept_on ended the aborted burst as a pass");
    $finish;
  end
endmodule

Prints: failures on a legal abort=0 PASS: accept_on ended the aborted burst as a pass

Half-Truth

"Use disable iff for every abort; it is all the same."

Disabled attempts count as neither pass nor fail. If aborts are frequent, the burst rule may rarely finish a real check, and the report will not show it.

Source IEEE 1800-2017 §16.12

Tool as Truth

"accept_on and sync_accept_on are identical on our simulator, so they are identical."

Verilator 5.052 checks the async form only at clock edges. The standard lets accept_on react to a pulse between edges.

Source ASIC Point engine notes (Verilator 5.052 SVA probes), A3/A5 table row on reject_on / accept_on

Learn It, Then Prove It