← Design Verification Interviews

Interview Question · Waveform

What Value Does an Assertion See at the Edge?

L0 FresherL1 Juniorsvasamplingscheduling

The Question

The interviewer asks

The design toggles req with a nonblocking assignment at every rising edge. At the edge where req goes from 0 to 1, which value does a concurrent assertion use?

Reveal the Model Answer

It uses 0. Concurrent assertions sample their variables in the Preponed region, before anything in that time step runs. So they see the value from just before the edge. The new 1 is seen at the next edge. This is what makes assertions race-free against flops written at the same edge.

Sampled versus current at each edge
0123edge (ns)5152535req after edgereq sampledreq rises at 5; the assertion still sees 0

The sampled value always lags the value written at the same edge by one edge.

The design raises req at the edge at 5. A monitor prints it 1 ns later; an assertion reports when it sees the rise.

RUNVerilator · simulator service
Edit the code, then run it
Expected: t=6 req is now 1 t=15 the assertion saw req rise

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Fresher)

A good fresher answer draws the clock edge, puts the sample just before it, and answers 0.

Cross-Questions

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

WhyWhat IfProve ItBreak ItCompare

  1. What Value Does an Assertion See at the Edge?
  2. WhyWhy Assertions Sample Before the EdgeL1 Junior

    Why sample in the Preponed region rather than reading the values when the assertion is evaluated?

    Reveal the Model Answer

    At an edge, flops written with <= update in the NBA region, and process order within a region is unspecified. Reading at evaluation time would make the result depend on whether the flops had updated yet. The Preponed sample is the value every flop saw at the edge, which matches what real hardware samples.

    The Regions of One Time StepThe regions of one time step in IEEE 1800-2017 order. Arrows show where the scheduler goes next. Preponed comes first, before any process runs or any flop updates.
    The regions of one time stepThe regions of one time step in IEEE 1800-2017 order. Arrows show where the scheduler goes next. Preponed comes first, before any process runs or any flop updates. region Preponed samples for #1stepand assertions region Active woken processes run;<= reads its rightside region Inactive processes resumedafter #0 region NBA pending <= updatesare written region Observed concurrentassertions evaluate region Reactive set program code andassertion actions region Postponed $strobe prints;nothing may change thenthenthen<= updateswakes readersall three emptythennothing left
    Read the diagram as text
    • Preponed: samples for #1step and assertions
    • Active: woken processes run; <= reads its right side
    • Inactive: processes resumed after #0
    • NBA: pending <= updates are written
    • Observed: concurrent assertions evaluate
    • Reactive set: program code and assertion actions
    • Postponed: $strobe prints; nothing may change
    • Preponed → Active: then
    • Active → Inactive: then
    • Inactive → NBA: then
    • Active → NBA: <= updates
    • NBA → Active: wakes readers
    • NBA → Observed: all three empty
    • Observed → Reactive set: then
    • Reactive set → Postponed: nothing left

    The NBA region writes the flops after the Preponed samples are taken. So an assertion never depends on which process ran first.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "It is a simulator optimisation."

    It is a semantic rule that makes the verdict independent of process order, and the same rule is what formal tools model.

    Source Mehta, SystemVerilog Assertions and Functional Coverage (3rd ed.), §6.3 (PDF p87-91)

  3. What IfA Testbench That Drives at the EdgeL1 JuniorL2 Mid-Level

    What if the testbench drives an input with a blocking assignment exactly at the clock edge?

    Reveal the Model Answer

    The sampled value is taken before that write, so the assertion sees the old value. A DUT flop may see the new one, because its process can run after the testbench write. Assertion and DUT then disagree about the same cycle. Drive inputs through a clocking block, or with <=.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "The assertion is wrong, because it disagrees with the DUT."

    The testbench created a race at the edge. The assertion read a defined sample; the DUT read whichever value the scheduler gave it.

    Source Lesson 6.2 key points

  4. CompareAssertion Sampling vs a Clocking Block InputL2 Mid-Level

    Compare how a concurrent assertion samples a signal with how a clocking block input with #1step skew samples it.

    Reveal the Model Answer

    They read the same value: both take the value from just before the clock event. The assertion's sample is built into its semantics. The clocking block makes the sample explicit, as a clockvar that testbench code reads. Other input skews, such as #2ns, sample earlier. Reading the raw signal in a monitor instead gives whichever value the process order happens to produce.

    Read withValue seen at the edge
    A concurrent assertionThe value from just before the edge
    A clocking block input, #1step skewThe value from just before the edge
    A clocking block input, #2ns skewThe value 2 ns before the edge
    The raw signal in a monitorWhatever the process order gives

    The first two always agree. The raw read is the one that races.

    Self-Check

    Tick each key point you covered in your answer.

    Missed Corner

    "A clocking block input with #0 skew samples like an assertion."

    An explicit #0 skew samples in the Observed region, after the NBA updates, so it can see the new value. Only #1step matches the Preponed sample.

    Source IEEE 1800-2017 §14.4

  5. Break ItThe Failure Message That Printed the Wrong ValueL1 JuniorL2 Mid-Level

    An assertion valid |-> data != 0 fails, but its else message prints data=5a. How can a nonzero value fail the check?

    log
    t=45 a_nonzero failed: data=5a
    Reveal the Model Answer

    The check used the Preponed sample. The action block runs later, in the Reactive region, after the design updated data at that edge. So the message shows the new value, not the one that failed. Print $sampled(data) in action blocks to report what the assertion actually saw.

    Sampled Value and Current Value at One EdgeThe regions of one time step, left to right, for a rule that fails at 15 ns on rready. Arrows show the order of the regions, and who writes or reads rready.
    Sampled value and current value at one edgeThe regions of one time step, left to right, for a rule that fails at 15 ns on `rready`. Arrows show the order of the regions, and who writes or reads `rready`. region Preponed Assertion samplestaken region Active and NBA Design and testbenchrun region Observed Properties evaluatedon samples region Reactive Action blocks run signal rready The variable itself thenthenfailswrites 1now=
    1. Preponed

      Before any process runs at 15, the assertion takes the sampled value of rready: 0, written right after the edge at 5.

    2. Active

      The testbench resumes after @(posedge clk) and writes rready = 1. The sample taken a moment ago does not change.

      Follow the calls, values and waits
      1. data sample: rready = 0: Preponed → Active and NBA
      2. data rready = 1: Active and NBA → rready
    3. Observed

      The property is evaluated on samples only: 1 at 5, 0 at 15. $fell(rready) is true, so !$fell(rready) fails.

      Follow the calls, values and waits
      1. data sample: rready = 0: Active and NBA → Observed
    4. Reactive

      The fail action prints now=1 sampled=0. Reading rready gives the value written in Active; $sampled(rready) gives the one the assertion used.

      More context

      A monitor that prints the current value at this point reports a different value from the one the rule checked. Print $sampled(x) next to it.

      Follow the calls, values and waits
      1. data $fell: 1 at 5, 0 at 15: Observed → Reactive
      2. data now=1: rready → Reactive
    Read the diagram as text
    • Preponed: Assertion samples taken
    • Active and NBA: Design and testbench run
    • Observed: Properties evaluated on samples
    • Reactive: Action blocks run
    • rready: The variable itself
    • Preponed → Active and NBA: then
    • Active and NBA → Observed: then
    • Observed → Reactive: fails
    • Active and NBA → rready: writes 1
    • rready → Reactive: now=

    Samples are taken first and evaluated after the design has moved on, so the result never depends on process order.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Action blocks run before the design updates, so plain names are fine."

    The standard runs action blocks in the Reactive region, after the NBA updates of that time step. So a plain name reads the new value.

    Source IEEE 1800-2017 §4.4.2.6

    Tool as Truth

    "On Verilator the message showed the value that failed, so the plain name is correct."

    Verilator 5.052 runs the action before the NBA update, so there both spellings agree. A simulator that follows the standard prints the new value; only $sampled is right on both.

    Source Measured for this batch on Verilator 5.052: the else action at 5 printed data=00 after data <= 8'h5a at that edge

  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

"Write the stimulus with #0 after the edge and the assertion sees it at that edge."

The sample was taken in the Preponed region before any process ran, so no delay after the edge can reach it. The twin's #0 write is seen one edge later.

Run It

A testbench write at edge 15 with #0 in front of it.

RUNVerilator · simulator service
Edit the code, then run it
Expected: t=15 testbench wrote req=1 t=25 the assertion saw req rise FAIL: #0 still runs after the Preponed sample, so edge 15 never saw the write
See the Fix
module tb;
  logic clk = 0, req = 0;
  always #5 clk = ~clk;                 // rising edges at 5, 15, 25, ...
  a_seen: assert property (@(posedge clk) !$rose(req))
    else $display("t=%0t the assertion saw req rise", $time);
  initial begin
    @(posedge clk); @(negedge clk);     // the fix: write at 10, between edges
    req = 1;
    $display("t=%0t testbench wrote req=1", $time);
    @(posedge clk); #1 $display("PASS: a write before the edge is sampled at that edge");
    $finish;
  end
endmodule

Prints: t=10 testbench wrote req=1 t=15 the assertion saw req rise PASS: a write before the edge is sampled at that edge

Spec Misquote

"The assertion is evaluated in the Active region with the flops."

Concurrent assertions are evaluated in the Observed region, after the NBA updates, but on the values sampled in Preponed.

Source IEEE 1800-2017 §4.4.2.5

Buzzword Without Mechanism

Says "assertions sample in the Preponed region" but cannot say which value that gives at the edge.

The term is only useful with its consequence: the value from before the edge, so a same-edge write appears one edge later.

Learn It, Then Prove It