Skip to main content

SystemVerilog fork...join – Parallel Execution Explained

· loading · loading · ·
Verification SystemVerilog Fork Join Parallel Execution Testbench Join_any Join_none
Verification
Axolot Logic
Author
Axolot Logic
Digital Design Engineer
Table of Contents
SystemVerilog Design Series - This article is part of a series.
Part 15: This Article

🧵 SystemVerilog fork...join – Parallel Execution Explained
#

In SystemVerilog, the fork...join construct allows you to execute multiple statements or processes in parallel, similar to threads in software programming. This is especially useful in testbenches, stimulus generation, and concurrent checks.


🔧 Basic Syntax
#

fork
  statement_1;
  statement_2;
  statement_3;
join
  • All the statements inside fork...join start executing simultaneously
  • The simulation waits for all of them to complete before moving to the next statement after the join

📌 Variants of join
#

KeywordBehavior
joinWaits for all threads to finish (blocking)
join_anyContinues as soon as any one thread finishes
join_noneDoes not wait for any thread; all child processes run in background

Example with join:
#

fork
  #10 $display("A");
  #5  $display("B");
join
$display("All done");  // Executes after both A and B

Example with join_any:
#

fork
  #20 $display("Slow task");
  #5  $display("Fast task");
join_any
$display("One of them finished");  // Executes after first task completes

Example with join_none:
#

fork
  #10 $display("Running...");
  #20 $display("Still running...");
join_none
$display("No wait, move on immediately");

🔁 disable fork
#

SystemVerilog allows you to terminate all child processes started within a fork...join block using disable fork;.

initial begin
  fork
    forever begin
      #1 $display("Looping forever...");
    end
    #10 disable fork;  // Stop the forever loop after 10 time units
  join
end

🚨 Synthesis Warning
#

  • fork...join is not synthesizable
  • It is intended for testbenches and behavioral modeling only
  • Do not use in RTL code

🧪 Typical Use Cases
#

  • Launching parallel stimulus in testbenches

  • Waiting for multiple monitors or checks

  • Running concurrent tasks like:

    • packet send + scoreboard check
    • stimulus + timeout monitor
  • Creating timeouts or watchdogs with join_any


✅ Best Practices
#

  • Use join when all parallel threads must complete
  • Use join_any for timeouts or race conditions
  • Use join_none to launch background tasks
  • Use disable fork to gracefully abort all threads

🧠 Summary Table
#

VariantWaits For?Use Case
joinAll threadsSynchronized completion
join_anyFirst to finishTimeout or race-based logic
join_noneNo waitingBackground monitoring or delayed checks
disable forkManually terminates allForce stop child processes (e.g., loops)

The fork...join family in SystemVerilog enables powerful concurrent behaviors, especially in UVM and testbench environments. Understanding and using it correctly makes your simulations more realistic, modular, and controlled.


module tb_fork_join_demo;

  initial begin
    $display("== fork...join Demo ==");

    // Basic fork...join: Waits for all to complete
    $display("\n[1] fork...join");
    fork
      #10 $display("  Task A done at %0t", $time);
      #5  $display("  Task B done at %0t", $time);
    join
    $display("  -> All tasks finished at %0t", $time);

    // fork...join_any: Continues after first finishes
    $display("\n[2] fork...join_any");
    fork
      #20 $display("  Slow task done at %0t", $time);
      #5  $display("  Fast task done at %0t", $time);
    join_any
    $display("  -> One task finished at %0t", $time);

    // fork...join_none: Moves on immediately
    $display("\n[3] fork...join_none");
    fork
      #10 $display("  Background A at %0t", $time);
      #20 $display("  Background B at %0t", $time);
    join_none
    $display("  -> Proceeding immediately at %0t", $time);

    // fork with disable fork
    $display("\n[4] fork with disable fork");
    fork 
      forever begin
        #1 $display("  Looping... %0t", $time);
        if($time == 100) break;
      end
    join

    $display("== Simulation done at %0t ==", $time);
    #10 $finish;
  end

endmodule

SystemVerilog Design Series - This article is part of a series.
Part 15: This Article

Related

SystemVerilog Arrays
· loading · loading
Hardware Design Verification SystemVerilog Arrays Packed Dynamic Arrays Queues Testbench
Hardware Design Verification
SystemVerilog Loops and Control Flow – for, while, foreach, repeat, break
· loading · loading
Hardware Design Verification SystemVerilog Loops Control Flow Testbench RTL Design Break/Continue
Hardware Design Verification
SystemVerilog Tasks and Functions
· loading · loading
Hardware Design Verification SystemVerilog Tasks Functions RTL Design Testbench Reusability
Hardware Design Verification
SystemVerilog Enum Data Type
· loading · loading
Hardware Design Verification SystemVerilog Enum FSM RTL Design Testbench Debugging
Hardware Design Verification
SystemVerilog String Data Type
· loading · loading
Verification SystemVerilog String Testbench Simulation File I/O Non-Synthesizable
Verification
SystemVerilog Interface – Modular Signal Grouping with modport and Clocking Blocks
· loading · loading
Hardware Design Verification SystemVerilog Interface Modport Testbench RTL Design Connectivity
Hardware Design Verification