Close Menu
VLSI Web
  • Home
    • About Us
    • Contact Us
    • Privacy Policy
  • Digital Design
    • Digital Circuits
    • Verilog
    • VHDL
    • System Verilog
    • UVM
  • VLSI Roles
    • RTL Design
    • Design Verification
    • Physical Design
    • DFT
    • STA
  • Interviews
  • Informative
  • VLSI Forge
Instagram LinkedIn WhatsApp Telegram
Instagram LinkedIn WhatsApp Telegram
VLSI Web
  • Home
    • About Us
    • Contact Us
    • Privacy Policy
  • Digital Design
    • Digital Circuits
    • Verilog
    • VHDL
    • System Verilog
    • UVM
  • VLSI Roles
    • RTL Design
    • Design Verification
    • Physical Design
    • DFT
    • STA
  • Interviews
  • Informative
  • VLSI Forge
VLSI Web
System Verilog

Threads in SystemVerilog: fork-join, Mailboxes, Semaphores and Events

Raju GorlaBy Raju Gorla11 July 2026Updated:11 October 2026No Comments4 Mins Read
Threads in SystemVerilog
Share
Facebook Twitter LinkedIn Email Telegram WhatsApp

The short answer: SystemVerilog testbenches run many threads at once. fork…join starts threads and waits for all of them; join_any waits for the first; join_none returns immediately. Threads exchange data through mailboxes (typed FIFOs), share resources with semaphores, and synchronise with events. Use disable fork to stop leftover threads and wait fork to wait for all children, and copy loop variables into automatic variables before forking inside a loop.

A testbench is naturally parallel: a generator creates transactions, a driver sends them, a monitor watches the bus and a scoreboard checks results, all at the same time. This post covers the tools SystemVerilog gives you to start those threads and let them work together.

  1. The building blocks
  2. fork-join variants
  3. The classic loop bug
  4. Mailboxes
  5. Semaphores
  6. Events
  7. How UVM uses this

Table of Contents

  • Part 1: The building blocks
  • Part 2: fork-join variants
  • Part 3: The classic loop bug
  • Part 4: Mailboxes
  • Part 5: Semaphores
  • Part 6: Events
  • Part 7: How UVM uses this
  • FAQ
    • What is the difference between join, join_any and join_none?
    • What is a mailbox in SystemVerilog?
    • What is the difference between a mailbox and a queue?
    • Why do all my forked threads see the same loop value?

Part 1: The building blocks

SystemVerilog fork join, join_any and join_none, plus mailbox, semaphore and event for inter-process communication
Three ways to start threads, three ways to coordinate them.

Part 2: fork-join variants

fork
  begin #10 $display("A"); end
  begin #20 $display("B"); end
join           // continues at time 20

fork
  wait_for_response();
  begin #1000; $error("timeout"); end
join_any       // continues when either finishes
disable fork;  // stop the one still running

fork
  monitor.run();          // runs forever in the background
join_none

Part 3: The classic loop bug

// WRONG: all threads see i == 4 by the time they run
for (int i = 0; i < 4; i++)
  fork
    drive_port(i);
  join_none

// RIGHT: copy into an automatic variable per iteration
for (int i = 0; i < 4; i++) begin
  automatic int idx = i;
  fork
    drive_port(idx);
  join_none
end
wait fork;     // wait for all four

Threads started by join_none don’t run until the parent blocks, so by then the loop has finished. This is one of the most common SystemVerilog interview questions.

Part 4: Mailboxes

mailbox #(bus_txn) gen2drv = new();     // unbounded, typed

// generator
repeat (10) begin
  bus_txn t;
  t = new();
  assert(t.randomize());
  gen2drv.put(t);          // blocks only if the mailbox is bounded and full
end

// driver
forever begin
  bus_txn t;
  gen2drv.get(t);          // blocks until an item is available
  drive(t);
end

try_get and try_put are non-blocking versions; peek reads without removing. A bounded mailbox (new(4)) gives back-pressure.

Part 5: Semaphores

semaphore bus_lock = new(1);   // one key

task automatic use_bus();
  bus_lock.get(1);             // wait for the key
  // ... drive the shared bus ...
  bus_lock.put(1);             // give it back
endtask

Part 6: Events

event reset_done;

initial begin
  apply_reset();
  -> reset_done;                // trigger
end

initial begin
  wait (reset_done.triggered);  // safe even if triggered in the same time step
  start_traffic();
end

@reset_done misses a trigger that happened earlier in the same time step; wait(reset_done.triggered) doesn’t, which avoids a common race.

Part 7: How UVM uses this

UVM wraps these ideas: phases decide when threads start, TLM FIFOs and analysis ports replace raw mailboxes, and objections replace hand-written “wait until done” logic. Knowing the underlying constructs makes UVM much easier to debug. See testbench architecture.

Practise this on VLSI Forge

I built VLSI Forge so you can write RTL in your browser, run it on a real simulator and check every signal in the waveform. Free, nothing to install.

Design Verification problems · Daily challenge

Previous in my SystemVerilog series: Constrained randomisation. Next: SystemVerilog assertions.

FAQ

What is the difference between join, join_any and join_none?

join waits for all forked threads, join_any for the first one, and join_none doesn’t wait at all.

What is a mailbox in SystemVerilog?

A built-in FIFO for passing data, usually transaction objects, between threads. get blocks until data is available.

What is the difference between a mailbox and a queue?

A queue is just a data structure. A mailbox adds blocking put and get and optional bounding, so it’s safe for thread synchronisation.

Why do all my forked threads see the same loop value?

Because join_none threads start after the loop ends. Copy the loop variable into an automatic variable inside the loop before forking.

Concurrent Programming in SV Multi-Threading Best Practices Parallel Processing Techniques Software Parallelism Concepts SV Multi-Core Processing SV Thread Synchronization SystemVerilog Programming
Share. Facebook Twitter LinkedIn Email Telegram WhatsApp
Previous ArticleConstrained Randomisation in SystemVerilog: Constraints That Find Bugs
Next Article SystemVerilog Assertions (SVA) with Examples
Raju Gorla
  • Website

Related Posts

System Verilog

Design Patterns in SystemVerilog Testbenches: Factory, Callbacks and More

16 July 2026
System Verilog

DPI in SystemVerilog: Calling C from Your Testbench (and Back)

15 July 2026
System Verilog

SystemVerilog Testbench Architecture: A Self-Checking Testbench Without UVM

14 July 2026
Add A Comment
Leave A Reply Cancel Reply

Topics
  • Digital Circuits
  • Informative
  • Interview Questions
  • Physical Design
  • RTL Design
  • STA
  • System Verilog
  • UVM
  • Verilog
Instagram LinkedIn WhatsApp Telegram
  • About
  • Contact
  • Privacy Policy
  • VLSI Forge
  • Courses
  • Feedback
© 2026 VLSI Web

Type above and press Enter to search. Press Esc to cancel.