System Verilog : Disable Fork & Wait Fork

To model concurrent and serial behavior, disable fork and wait fork will be used along with fork join constructs. These constructs allow one process to terminate or wait for the completion of other processes.

If you want to model your verification environment in such a way that, it has to spawn concurrent processes which will be waiting for events. And as soon as one event is received, terminate the other outstanding processes to go ahead with your next process. In this case disable fork would be the best option along with join_any.

Disable Fork :

class fork_join_class;
 task run(input event ev_blk1,ev_blk4);
 fork
   BLK1: begin
     # 2ns
     $display( "BLOCK 1\n" );
     # 10ns;
     ->ev_blk1;
   end
   BLK2: begin
     $display( "BLOCK 2\n" );
   end
   BLK3: begin
     @ev_blk4;
     $display( "BLOCK 3\n" );
   end
  BLK4: begin
     @ev_blk1
     $display( "BLOCK 4\n" );
     ->ev_blk4;
  end
  join_any
  disable fork;
 endtask
 endclass

program myprog;
  event ev_blk1,ev_blk4;
  fork_join_class c1 = new;
  
  initial begin
   c1.run(ev_blk1,ev_blk4);
   P1: begin
   $display("Parent Process Started\n");
   end
   #100ns;
  end
endprogram
/*
BLOCK 2
Parent Process Started
*/

The disable fork terminates all active descendants of the current process. In this case BLK1,BLK3 and BLK4 are terminated.

Wait Fork :

The wait fork statement blocks process execution flow until all immediate child subprocesses (processes
created by the current process, excluding their descendants) have completed their execution.

class fork_join_class;
 
 task run(input event ev_blk1,ev_blk4);
 FJ1 : fork
   BLK1: begin
     # 2ns
     $display( "FJ1 BLOCK 1\n" );
     # 10ns;
     ->ev_blk1;
   end
 
   BLK2: begin
     $display( "FJ1 BLOCK 2\n" );
   end
 
   BLK3: begin
     @ev_blk4;
     $display( "FJ1 BLOCK 3\n" );
   end

   BLK4: begin
     @ev_blk1
     $display( "FJ1 BLOCK 4\n" );
     ->ev_blk4;
  end
  join_any

 FJ2: fork
   BLK1: begin
     # 2ns
     $display( "FJ2 BLOCK 1\n" );
     # 10ns;
     ->ev_blk1;
   end
 
   BLK2: begin
     $display( "FJ2 BLOCK 2\n" );
   end
 
   BLK3: begin
     @ev_blk4;
     $display( "FJ2 BLOCK 3\n" );
   end

   BLK4: begin
     @ev_blk1
     $display( "FJ2 BLOCK 4\n" );
     ->ev_blk4;
  end
  join_none

//wait fork;

 endtask
 
 endclass

program myprog;
  event ev_blk1,ev_blk4;
  fork_join_class c1 = new;
  
  initial begin
   c1.run(ev_blk1,ev_blk4);
   P1: begin
   $display("Parent Process Started\n");
   end
   
   #10ns;
  end
  
endprogram

/*
-- Without wait-fork
FJ1 BLOCK 2

Parent Process Started

FJ2 BLOCK 2

FJ1 BLOCK 1

FJ2 BLOCK 1


-- With wait fork
FJ1 BLOCK 2

FJ2 BLOCK 2

FJ1 BLOCK 1

FJ2 BLOCK 1

FJ2 BLOCK 4

FJ1 BLOCK 4

FJ2 BLOCK 3

FJ1 BLOCK 3

Parent Process Started

*/


In the above code, FJ1 uses join_any and FJ2 uses join_none. Without wait fork construct (Line 52), BLK2 will be executed first and then P1 . Execution of other processes depend on when simulation ends. With wait fork construct(Line 52), all spawned child processes in FJ1 and FJ2 will be executed before going to P1 process.

1 comment on “System Verilog : Disable Fork & Wait Fork

  1. Novice

    Could u pls explain Why

    1] “FJ2 block4” occurs before “FJ1 block 4”
    2] “FJ2 block3” doesn’t occur right after “FJ2 block 4”
    “FJ1 block3” doesn’t occur just after “FJ1 block 4”

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *