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
    • Event Scheduling Puzzles
    • Race Condition Puzzles
      • Competing Active Writers on x
      • Blocking Writer vs NBA Writer Same Signal
      • Reading q Before the NBA (Not a Race)
      • Fork join_none Loop Variable Capture and kill()
      • Lost Update in Forked Counter
      • Two always_ff Writers, One Register
    • Clocking Block Puzzles
    • Semaphore & Mailbox Puzzles
    • Concurrency & Timing Puzzles: Tricky Q&A
  • Randomization & Constraint Puzzles25
  • SVA Assertion Puzzles25
  • Functional Coverage Puzzles25
  • Logic & Aptitude Puzzles25
  • Scenario & Debug Puzzles25
  • UVM Testbench Puzzles25
  • Clock, Reset & CDC Puzzles25
  • Bus and Interface Protocol Puzzles25
  • Interview Prep: Puzzle Rounds7
  • DV Puzzle Cheatsheet
Loading lesson

←Race Condition Puzzles
  1. Topics
  2. DV Interview Puzzles
  3. Concurrency & Timing Puzzles
  4. Race Condition Puzzles
  5. Lost Update in Forked Counter
On this page

    VLSI DV Interview PuzzlesAll levels

    Lost Update in Forked Counter

    Compute the final value of hits and explain why four increments produce exactly that value.

    Puzzle

    Difficulty: Medium · Puzzle 5 of 6 · Topic: Race Condition Puzzles

    Compute the final value of hits and explain why four increments produce exactly that value.

    Code

    tb.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    module tb;
      int hits = 0;
    
      task automatic add_hit();
        int snap;
        snap = hits;
        #0 hits = snap + 1;
      endtask
    
      initial begin
        fork
          repeat (2) add_hit();
          repeat (2) add_hit();
        join
        $display("[%0t] hits=%0d", $time, hits);
      end
    endmodule

    Hint

    Read-modify-write is not atomic across concurrent threads, and #0 yields in between.

    Step-by-step solution

    Diagram
    1) Both threads start in Active. Each reads snap=0 and yields on #0.
    2) In Inactive each thread writes hits=1 and starts its second add_hit. The second snapshot is taken right after the thread's own first write, with no yield in between, so both second snapshots see hits=1.
    3) Both threads yield again; both then write hits=2. Final value: 2.
    4) The result does not depend on the order in which the LRM lets the two inactive resumptions run, so the answer is exactly 2, never 3 or 4.
    5) A correct counter needs mutual exclusion: wrap snap/write in sem.get(1)/sem.put(1).

    Answer

    Answer: hits=2 at t=0 in every legal ordering (verified in Icarus and Verilator). Two of the four increments are lost.

    How this was checked

    Checked by running the code in Verilator 5 and Icarus Verilog 13; the printed output supports the answer above. Two of the four increments are lost, every time. Icarus gives the same hits=2, so the lost updates are not a tool quirk.

    Why candidates get it wrong

    Answering 'typically 2' or 'sometimes 4' is wrong: the lost updates are deterministic here. Four would only appear if #0 were treated as a no-op (some tools approximate it), or if a semaphore serialised the updates.

    Interviewer follow-up

    Show a semaphore-based rewrite that guarantees hits=4. Model answer: semaphore s = new(1); task automatic add_hit(); int snap; s.get(1); snap = hits; #0 hits = snap + 1; s.put(1); endtask. Each read-modify-write is now a critical section, so hits=4.

    Say it out loud

    The answer is exactly 2, and two of the four increments are lost. Each thread reads the counter and yields on #0, then both write 1, and their second increments also read 1 because nothing yields between a thread's write and its next read, so both write 2. This does not depend on the order of the two inactive resumptions, so it is not a toss-up. The trap is saying typically 2 or sometimes 4; the fix is a semaphore around the read-modify-write, and I would check the lock is released on every path.

    Related topics

    • Semaphores: One Key and Many

    • Threads and Control: Fork, Disable, Wait, Process

    • Back to Race Condition Puzzles

    • Concurrency & Timing Puzzles section

    Previous

    71 / 293

    Next: Two always_ff Writers, One Register

    Up next

    Up nextTwo always_ff Writers, One Register

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Competing Active Writers on x
    • Blocking Writer vs NBA Writer Same Signal
    • Reading q Before the NBA (Not a Race)