In SystemVerilog, the wait fork statement is an essential tool that helps the main process wait until all forked processes are completed. This feature is particularly useful when the main process needs to spawn multiple threads and perform tasks before waiting for those threads to finish.

In this article, we will explore how wait fork works in SystemVerilog with examples, focusing on how it allows synchronization between the main process and forked sub-processes.

What is systemVerilog Wait Fork?

The wait fork statement is used to pause the main process until all the forked processes (threads) are finished. It is commonly used after the fork statement to ensure that the main thread waits until the completion of all parallel tasks.

The typical scenario for using wait fork is when you have multiple threads running in parallel, and the main thread needs to wait for all of them to complete before continuing.

Basic Example: Using systemVerilog Wait Fork with 3 Threads

Let’s walk through a simple example where we spawn three threads in parallel, and the main thread waits for all of them to finish.

module tb_top;

    initial begin
        // Fork 3 sub-threads in parallel
        // The main thread will finish when all sub-threads have completed
        fork

            // Thread 1: Finishes first at 40ns
            #40 $display ("[%0t ns] Show #40 $display statement", $time);

            // Thread 2: Finishes at 70ns
            begin
                #20 $display ("[%0t ns] Show #20 $display statement", $time);
                #50 $display ("[%0t ns] Show #50 $display statement", $time);
            end

            // Thread 3: Finishes at 60ns
            #60 $display ("[%0t ns] TIMEOUT", $time);
        join_any

        // Display when fork join is completed
        $display ("[%0t ns] Fork join is done, wait fork to end", $time);

        // Wait until all forked processes finish
        wait fork;
        $display ("[%0t ns] Fork join is over", $time);
    end
endmodule

Simulation Log:

ncsim> run
[20 ns] Show #20 $display statement
[40 ns] Show #40 $display statement
[40 ns] Fork join is done, wait fork to end
[60 ns] TIMEOUT
[70 ns] Show #50 $display statement
[70 ns] Fork join is over
ncsim: *W,RNQUIE: Simulation is complete.

How wait fork Synchronizes Multiple Threads

In the example above, we see that the fork statement starts three threads in parallel. The join_any ensures the main thread will continue as soon as any one of the threads finishes. After that, the wait fork command ensures the main process will pause until all the threads finish.

Key Points:

  1. Forking Threads: You can start multiple threads using the fork statement.
  2. Main Thread Continuation: With join_any, the main thread can continue after any thread finishes.
  3. Waiting for Completion: The wait fork command ensures that the main thread waits until all the threads have completed.

Extended Example: Forking Two Additional Threads

To see how this works with more threads, let’s modify the example to fork two more threads and make the main process wait for the completion of all of them.

module tb_top;

    initial begin
        // Fork 3 sub-threads in parallel
        // The main thread will finish when any of the sub-threads have completed
        fork

            // Thread 1: Finishes first at 40ns
            #40 $display ("[%0t ns] Show #40 $display statement", $time);

            // Thread 2: Finishes at 70ns
            begin
                #20 $display ("[%0t ns] Show #20 $display statement", $time);
                #50 $display ("[%0t ns] Show #50 $display statement", $time);
            end

            // Thread 3: Finishes at 60ns
            #60 $display ("[%0t ns] TIMEOUT", $time);
        join_any

        // Display when fork join is completed
        $display ("[%0t ns] Fork join is done, wait fork to end", $time);

        // Fork two additional processes
        fork
            #10 $display ("[%0t ns] Wait for 10", $time);
            #20 $display ("[%0t ns] Wait for 20", $time);
        join_any

        // Wait until all forked processes finish
        wait fork;
        $display ("[%0t ns] Fork join is over", $time);
    end
endmodule

Simulation Log:

ncsim> run
[20 ns] Show #20 $display statement
[40 ns] Show #40 $display statement
[40 ns] Fork join is done, wait fork to end
[50 ns] Wait for 10
[60 ns] TIMEOUT
[60 ns] Wait for 20
[70 ns] Show #50 $display statement
[70 ns] Fork join is over
ncsim: *W,RNQUIE: Simulation is complete.

Comparison of Forked Processes:

To understand the behavior better, here’s a table comparing the different threads and their finish times in both examples.

ThreadFinish Time (Example 1)Finish Time (Example 2)
Thread 140ns40ns
Thread 270ns70ns
Thread 360ns60ns
Thread 4N/A50ns
Thread 5N/A60ns

As you can see from the table, the main thread continues its execution once any thread finishes in Example 1, but in Example 2, it waits until all the threads, including the two new ones, are done.

Conclusion: Effective Use of systemVerilog Wait Fork

The wait fork statement is a powerful tool in SystemVerilog for managing multiple threads. By using this command, you can ensure that the main process waits for all forked processes to complete before continuing its execution. This allows for better synchronization in testbenches where parallel execution is crucial.

When working with multiple threads, always remember to use wait fork for proper synchronization, ensuring that the main process only continues after all forked threads have finished their tasks.

Scroll to Top