← Design Verification Interviews

Interview Question · Code Reading

Until or Until With: Who Owns the Last Cycle?

L1 JuniorL2 Mid-Levelsvauntilproperties

The Question

The interviewer asks

The spec says req stays high up to and including the grant cycle. A design drops req in the grant cycle. Does this assertion catch it?

systemverilog
// Spec: once raised, req stays high up to and including the cycle where gnt is high.
a_req: assert property (@(posedge clk) $rose(req) |-> req until gnt) else errors++;
Reveal the Model Answer

No. p until q requires p at every edge before the first edge where q holds, but not at that edge. So dropping req in the grant cycle passes. until_with also requires p at the edge where q arrives, which is what "up to and including" means. Both are weak: if gnt never comes they never fail, and s_until, s_until_with are the strong forms.

req drops in the grant cycle
0123edge (ns)15253545reqgntuntil: not checked here, pass; until_with: req needed, fail

The two operators differ only at the edge where gnt is first true.

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Junior)

A good junior answer places the difference on the grant edge. It picks until_with for "up to and including".

Cross-Questions

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

WhyWhat IfProve ItBreak ItCompare

  1. Until or Until With: Who Owns the Last Cycle?
  2. CompareUntil_with vs Throughout a GotoL2 Mid-Level

    Compare req until_with gnt with req throughout gnt[->1].

    Reveal the Model Answer

    They give the same verdict when the grant comes: req must hold at every edge up to and including the first gnt. The difference is what they are. until_with is a property operator, so nothing can follow it in a sequence. throughout builds a sequence that you can extend or use in a cover. If the grant never arrives, both are weak and do not fail.

    req until_with gntreq throughout gnt[->1]
    Verdict when the grant comesSameSame
    What it buildsA propertyA sequence with an end point
    Can be followed by more sequenceNoYes
    Grant never comesWeak: no failureWeak: no failure

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Throughout checks the condition only at the start and end."

    It requires the condition at every tick of the sequence's match.

    Source Mehta, SystemVerilog Assertions and Functional Coverage (3rd ed.), §8.16 (PDF p161-163)

  3. Break ItA Throughout That Stopped FailingL2 Mid-LevelL3 Senior

    You extended a working rule to (req throughout gnt[->1]) ##1 done, and now it never fails, even when you remove done from the design. Is the rule wrong?

    systemverilog
    // passes on a design that never drives done
    a_req: assert property (@(posedge clk)
      $rose(req) |-> (req throughout gnt[->1]) ##1 done) else errors++;
    Reveal the Model Answer

    The rule is legal and should fail one edge after the grant when done is missing. Verilator 5.052 reports no failure for a throughout over a goto followed by more sequence, so the silence is the tool. Split it: keep req throughout gnt[->1] as the whole consequent, and add gnt |=> done as a second assertion.

    Self-Check

    Tick each key point you covered in your answer.

    Tool as Truth

    "It passed after the edit, so the design drives done correctly."

    The design never drives done at all. A rule that cannot fail on a broken design is broken evidence; always rerun a must-fail case after editing a property.

    Source ASIC Point engine notes (Verilator 5.052 SVA probes), "A3/A5 forms" ((v throughout r[->1]) ##1 done row)

  4. What IfA Grant That Never CameL2 Mid-Level

    What if the grant never arrives before the test ends? What do until, until_with and s_until report?

    Reveal the Model Answer

    The weak forms report nothing: an attempt still waiting at the end of simulation is not a failure. s_until is strong, so the open attempt fails at the end of simulation. Use the strong form when "the grant must come" is part of the rule. Make tests drain traffic before they stop, or legal stimulus fails it too.

    until_with: The Edge of r Is Checked TooOne lane per start for start |-> v until_with r. Attempt C is still waiting for r when the test ends.start |-> v until_with rMeasured on Verilator 5.052: one copy of the assertion per lane
    attempt startsfailstill running at the end: weak, no failure
    until_with: the edge of r is checked toostart @15, from edge 2 (t=15): fails at edge 4 (t=35). start @55, from edge 6 (t=55): fails at edge 6 (t=55). start @75, from edge 8 (t=75): is still running at the end of the run: weak, so no failure.edgetime152153254355456557658759851095end100clkstartvrattemptsstart @15start @15: fails at edge 4 (t=35)start @55start @55: fails at edge 6 (t=55)start @75start @75: is still running at the end of the run: weak, so no failure
    1. Edge 2 · t=15

      A starts at 15 with v high.

    2. Edge 4 · t=35

      At 35 r arrives, and until_with needs v on this edge as well. v is low, so A fails.

    3. Edge 6 · t=55

      B starts with r high, so its first edge is also its last. v is low there: B fails.

    4. End of the run · t=100

      C is still waiting at the end. until_with is weak too, so no verdict.

    Read the lanes as text
    • start @15, from edge 2 (t=15): fails at edge 4 (t=35).
    • start @55, from edge 6 (t=55): fails at edge 6 (t=55).
    • start @75, from edge 8 (t=75): is still running at the end of the run: weak, so no failure.

    Sampled values, edge 1 to 10: start 0 1 0 0 0 1 0 1 0 0; v 0 1 1 0 0 0 0 1 1 1; r 0 0 0 1 0 1 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 hold_until_with 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, v = 0, r = 0;
    
      hold_until_with: assert property (@(posedge clk) start |-> v until_with r);
    
      initial begin
        @(negedge clk); start = 1; v = 1;   // A starts at 15
        @(negedge clk); start = 0;
        @(negedge clk); v = 0; r = 1;       // r at 35, v already low
        @(negedge clk); r = 0;
        @(negedge clk); start = 1; r = 1;   // B starts at 55 with r already high
        @(negedge clk); start = 0; r = 0;
        @(negedge clk); start = 1; v = 1;   // C starts at 75; r never comes
        @(negedge clk); start = 0;
        @(negedge clk);
        @(negedge clk);
        $finish;                            // the test stops at 100
      end
    endmodule
    

    The weak form leaves attempt C with no verdict. The strong form, s_until_with, would fail it at the end.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Strong operators are only for formal."

    Simulators evaluate them too: a strong obligation still open when simulation ends is reported as a failure.

    Source Mehta, SystemVerilog Assertions and Functional Coverage (3rd ed.), §20.11 (PDF p325-328)

  5. WhyWhy Nothing Can Follow an UntilL2 Mid-Level

    Why can't you write (req until gnt) ##1 done?

    Reveal the Model Answer

    until produces a property, a verdict over time, not a sequence with an end point, and ## concatenates sequences. Some tools accept the expression anyway, Verilator 5.052 among them, which makes it easy to ship illegal code. Use req throughout gnt[->1] when you need a sequence with an end point.

    Self-Check

    Tick each key point you covered in your answer.

    Tool as Truth

    "It compiled, so it is legal."

    Verilator 5.052 compiles (v until r) ##1 done although until is not a sequence operator in the standard.

    Source ASIC Point engine notes (Verilator 5.052 SVA probes), "A3/A5 forms" ((v until r) ##1 done row)

  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

What People Get Wrong

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

Misconception

"until already includes the cycle where gnt arrives."

The left side is required only before the terminating edge. The twin's req drops at the grant edge: until passes and until_with catches it.

Run It

A request held two cycles and dropped in the grant cycle.

RUNVerilator · simulator service
Edit the code, then run it
Expected: failures=0 FAIL: until stops checking at the gnt edge, so req dropping there passed
See the Fix
module tb;
  logic clk = 0, req = 0, gnt = 0;
  int fails = 0;
  always #5 clk = ~clk;
  // The fix: until_with also demands req at the gnt edge.
  a_req: assert property (@(posedge clk) $rose(req) |-> req until_with gnt) else fails++;
  initial begin
    @(negedge clk) req = 1;             // request at 15
    @(negedge clk);
    @(negedge clk) begin gnt = 1; req = 0; end   // bug: req drops in the grant cycle (35)
    @(negedge clk) gnt = 0;
    repeat (2) @(negedge clk);
    $display("failures=%0d", fails);
    if (fails == 1) $display("PASS: until_with caught req dropping in the grant cycle");
    $finish;
  end
endmodule

Prints: failures=1 PASS: until_with caught req dropping in the grant cycle

Missed Corner

"req until gnt fails at the end of the test if no grant ever came."

until is weak: an attempt still waiting at the end is not a failure. Use s_until when the grant must come.

Source IEEE 1800-2017 §16.12.12

Tool as Truth

"s_until failures show up in the else block like any other."

On Verilator 5.052, an s_until attempt still open at $finish prints the tool's own error and stops. The else action never runs, so counters miss it.

Source ASIC Point engine notes (Verilator 5.052 SVA probes), "A3/A5 forms" (s_until row)

Learn It, Then Prove It