Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Puzzle Bank
  • SystemVerilog Language Puzzles25
  • Difficulty Guide
  • Full Topic Map
  • Interview-Day Tips
  • Study Route: One Week Before the Interview
  • Study Route: Two Weeks
  • Study Route: Four Weeks (Full Course)4
  • OOP & Testbench Puzzles25
  • Concurrency & Timing Puzzles25
  • Randomization & Constraint Puzzles25
  • SVA Assertion Puzzles25
  • Functional Coverage Puzzles25
  • Logic & Aptitude Puzzles25
    • Classic Brain Teasers
    • Probability Puzzles
    • Digital Logic Puzzles
    • Debugging Riddles
      • Race-Region Printout: What Does Each Monitor Print?
      • Reset Release Leaves the FSM in an Illegal State
      • always_comb with NBA and Missing Else
      • UVM Analysis Port Handle Reuse
      • join_any Timeout Ghost Thread
      • Randomization Always Fails: Hidden Unsat
    • Logic & Aptitude Puzzles: Tricky Q&A
  • Scenario & Debug Puzzles25
  • UVM Testbench Puzzles25
  • Clock, Reset & CDC Puzzles25
  • Bus and Interface Protocol Puzzles25
  • Interview Prep: Puzzle Rounds7
  • DV Puzzle Cheatsheet
Loading lesson

←Debugging Riddles
  1. Topics
  2. DV Interview Puzzles
  3. Logic & Aptitude Puzzles
  4. Debugging Riddles
  5. Race-Region Printout: What Does Each Monitor Print?
On this page

    VLSI DV Interview PuzzlesAll levels

    Race-Region Printout: What Does Each Monitor Print?

    A monitor 'appears one cycle stale' on a few seeds while the DUT waveform looks right. Before blaming the DUT, predict exactly what each of the three monitors below prints (module with `timescale 1ns/1ns, clk period 10, rising edges at 5, 15, 25, and the run ends with initial #27 $finish so the last print is at 26). Then say which one is a true race and how a clocking block fixes it.

    Puzzle

    Difficulty: Medium · Puzzle 1 of 6 · Topic: Debugging Riddles

    A monitor 'appears one cycle stale' on a few seeds while the DUT waveform looks right. Before blaming the DUT, predict exactly what each of the three monitors below prints (module with `timescale 1ns/1ns, clk period 10, rising edges at 5, 15, 25, and the run ends with initial #27 $finish so the last print is at 26). Then say which one is a true race and how a clocking block fixes it.

    Code

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    `timescale 1ns/1ns
    logic clk = 0;  logic [3:0] q = 0;
    always #5 clk = ~clk;
    always @(posedge clk) q <= q + 1;                       // DUT: nonblocking
    always @(posedge clk) $display("%0t M1 edge     q=%0d", $time, q);
    always @(posedge clk) begin #1; $display("%0t M2 edge+1   q=%0d", $time, q); end
    always @(negedge clk) $display("%0t M3 negedge  q=%0d", $time, q);
    
    initial #27 $finish;
    
    // Variant (separate run): DUT written with a blocking assignment
    int b = 0;
    always @(posedge clk) b = b + 1;                        // blocking
    always @(posedge clk) $display("%0t mon b=%0d", $time, b);

    Hint

    NBA updates happen after every active-region read at the same time step.

    Step-by-step solution

    Diagram
    1) The DUT flop uses q <= q+1: the new value is committed in the NBA region, after all active-region code of that time step has run.
    2) M1 reads in the active region at the edge, so it sees the pre-edge value: 5 q=0, 15 q=1, 25 q=2. This is deterministic, not a race. The 'stale' feel is that the monitor sees the same data a synchronous flop would see.
    3) M2 waits 1 time unit, after the NBA update: 6 q=1, 16 q=2 (26 q=3, the last print before $finish at 27). M3 reads at the falling edge: 10 q=1, 20 q=2. Both see the post-edge value. (Icarus and Verilator printed exactly this.)
    4) So decide what the scoreboard expects. If the reference model is cycle-aligned with registered outputs, M1's pre-edge view is correct and the scoreboard should compare against the previous-cycle expectation; if it expects post-edge data, sampling must move later.
    5) The true race is the blocking variant. Both always blocks wake at the same edge in arbitrary order, so mon may print b before or after the increment at each edge, so the output depends on the tool and on the order of the two blocks, and can change from edge to edge. In one trial of the same source (with int b = 0) Icarus printed 0, 2, 2 at 5, 15, 25 and Verilator 5.048 printed 0, 1, 2; swapping the two blocks changed Icarus to 1, 1, 3. Never rely on any of these.
    6) Fix the race by never driving with blocking assignments from a clocked block that others sample, or by driving and sampling through a clocking block (default input #1step samples the pre-edge value, output skew drives after the edge). Note #1step is not a cure for stale data: it returns what M1 returns, only without the race.
    7) The related bug of reusing one transaction handle for every sample is covered in the UVM analysis-port puzzle.

    Answer

    Answer: M1 prints 0,1,2 (pre-edge, deterministic), M2 prints 1,2,3 and M3 prints 1,2; only the blocking-assignment variant is a real race.

    How this was checked

    Checked by running the code in Icarus Verilog 13 and Verilator 5; the printed output supports the answer above. Icarus: M1 samples the pre-edge value (0,1,2), M2 one unit later sees 1,2,3, M3 on the falling edge sees 1,2. Verilator 5.048 prints exactly the same lines: the NBA-driven case is deterministic across tools. Blocking-assignment variant in Icarus: the monitor reads 0, 2, 2 depending on which same-edge block runs first. Same variant with the two always blocks swapped: Icarus now prints 1, 1, 3, so the result depends on source order (a real race). The unswapped variant in Verilator prints 0, 1, 2: a different answer from Icarus on the same source.

    Why candidates get it wrong

    Calling every one-cycle-late sample a race and reaching for #1step. A pre-edge sample of an NBA-driven signal is deterministic; the real defect is mixing blocking drives with same-edge sampling.

    Interviewer follow-up

    How would you prove in logs that the monitor sampled pre-NBA values? Model answer: print $time together with the DUT value after the edge (a $strobe or an #1 print) next to the monitor's sample: if the sample equals the value before the edge and the strobe shows the new one at the same time stamp, the monitor sampled pre-NBA. Or run with two different tools or seeds: identical results mean deterministic pre-edge sampling, differing results mean a real race.

    Say it out loud

    Let me first work out what each monitor sees, because a flop updates in the NBA region, after all the active code at that edge. Monitor one samples at the edge in the active region, so it sees the pre-edge value and prints 0, 1, 2, which is deterministic and not a race. Monitor two waits one time unit and prints 1, 2, 3, and monitor three samples at the falling edge and prints 1, 2. The real race is the blocking-assignment variant, where two blocks wake on the same edge in arbitrary order, so the fix is nonblocking drives or a clocking block. The trap is calling every late sample a race and reaching for a one-step delay.

    Related topics

    • Anatomy of a TB/RTL Race

    • Scheduling Regions: the Full Map

    • Blocking vs Nonblocking Assignments

    • Back to Debugging Riddles

    • Logic & Aptitude Puzzles section

    Previous

    179 / 293

    Next: Reset Release Leaves the FSM in an Illegal State

    Up next

    Up nextReset Release Leaves the FSM in an Illegal State

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • always_comb with NBA and Missing Else
    • UVM Analysis Port Handle Reuse
    • join_any Timeout Ghost Thread