What are SystemVerilog threads or processes ?
A thread or process is any piece of code that gets executed as a separate entity. In verilog, each of the initial and always blocks are spawned off as separate threads that start to run in parallel from zero time. A fork join
block also creates different threads that run in parallel.
What are different fork - join styles ?
We have three different styles of fork join
in SystemVerilog.

fork join | Finishes when all child threads are over |
fork join_any | Finishes when any child thread gets over |
fork join_none | Finishes soon after child threads are spawned |
Where is this used in the testbench ?
Components in a verification environment may require the ability to run multiple tasks concurrently. For example, one process may wait for something to happen while another process continues to perform some other task. They are all spawned off as separate threads via fork ... join
. For example, a checker can spawn different tasks in parallel to capture and validate data originating from different parts of the testbench.
What is the limitation of a Verilog fork join ?
Code after a fork ... join
is executed only when all the threads spawned off inside the fork-join has finished. So, the checker will have to wait until all the threads spawned in the fork-join to finish, before it can proceed.
fork join Example
SystemVerilog fork join
waits until all forked processes are complete.
module tb_top;
initial begin
#1 $display ("[%0t ns] Start fork ...", $time);
// Main Process: Fork these processes in parallel and wait untill all
// of them finish
fork
// Thread1 : Print this statement after 5ns from start of fork
#5 $display ("[%0t ns] Thread1: Orange is named after orange", $time);
// Thread2 : Print these two statements after the given delay from start of fork
begin
#2 $display ("[%0t ns] Thread2: Apple keeps the doctor away", $time);
#4 $display ("[%0t ns] Thread2: But not anymore", $time);
end
// Thread3 : Print this statement after 10ns from start of fork
#10 $display ("[%0t ns] Thread3: Banana is a good fruit", $time);
join
// Main Process: Continue with rest of statements once fork-join is over
$display ("[%0t ns] After Fork-Join", $time);
end
endmodule
ncsim> run [1 ns] Start fork ... [3 ns] Thread2: Apple keeps the doctor away [6 ns] Thread1: Orange is named after orange [7 ns] Thread2: But not anymore [11 ns] Thread3: Banana is a good fruit [11 ns] After Fork-Join ncsim: *W,RNQUIE: Simulation is complete.
Click here to learn about more on fork join !
fork join_any Example
SystemVerilog fork join_any
waits until any one of the forked processes is complete.
module tb_top;
initial begin
#1 $display ("[%0t ns] Start fork ...", $time);
// Main Process: Fork these processes in parallel and wait until
// any one of them finish
fork
// Thread1 : Print this statement after 5ns from start of fork
#5 $display ("[%0t ns] Thread1: Orange is named after orange", $time);
// Thread2 : Print these two statements after the given delay from start of fork
begin
#2 $display ("[%0t ns] Thread2: Apple keeps the doctor away", $time);
#4 $display ("[%0t ns] Thread2: But not anymore", $time);
end
// Thread3 : Print this statement after 10ns from start of fork
#10 $display ("[%0t ns] Thread3: Banana is a good fruit", $time);
join_any
// Main Process: Continue with rest of statements once fork-join is exited
$display ("[%0t ns] After Fork-Join", $time);
end
endmodule
ncsim> run [1 ns] Start fork ... [3 ns] Thread2: Apple keeps the doctor away [6 ns] Thread1: Orange is named after orange [6 ns] After Fork-Join [7 ns] Thread2: But not anymore [11 ns] Thread3: Banana is a good fruit ncsim: *W,RNQUIE: Simulation is complete.
Click here to learn about more on fork join_any !
fork join_none Example
SystemVerilog fork join_none
does not wait and immediately exits the block allowing forked processes to run in background. The main thread resumes execution of statements that follow after the fork join_none
block.
module tb_top;
initial begin
#1 $display ("[%0t ns] Start fork ...", $time);
// Main Process: Fork these processes in parallel and exits immediately
fork
// Thread1 : Print this statement after 5ns from start of fork
#5 $display ("[%0t ns] Thread1: Orange is named after orange", $time);
// Thread2 : Print these two statements after the given delay from start of fork
begin
#2 $display ("[%0t ns] Thread2: Apple keeps the doctor away", $time);
#4 $display ("[%0t ns] Thread2: But not anymore", $time);
end
// Thread3 : Print this statement after 10ns from start of fork
#10 $display ("[%0t ns] Thread3: Banana is a good fruit", $time);
join_none
// Main Process: Continue with rest of statements once fork-join is exited
$display ("[%0t ns] After Fork-Join", $time);
end
endmodule
ncsim> run [1 ns] Start fork ... [1 ns] After Fork-Join [3 ns] Thread2: Apple keeps the doctor away [6 ns] Thread1: Orange is named after orange [7 ns] Thread2: But not anymore [11 ns] Thread3: Banana is a good fruit ncsim: *W,RNQUIE: Simulation is complete.
Click here to learn about more on fork join_none !