Working of "wait fork" construct in system verilog


  program exp;
      task consume_time;
          $display("Entry: %0t",$time);
          fork: timeout_fork
              begin
                  #100;
                  $display("T1 finished - %0t",$time);
              end
              #5;
          join_any
          $display("Exit: %0t",$time);
      endtask
 
      initial begin
          consume_time();
      end
  
      initial begin
          wait fork;
          $display("All forked threads completed. time = %0t",$time);                                                  
      end
  endprogram

When running the above code, I get following output.


Entry: 0
All forked threads completed. time = 0
Exit: 5

Shouldn’t the $display after the “wait fork”, wait till timeout_fork’s T1. Why is the simulation ending at 5 instead of 100?

In reply to Balaji Murugan:

wait fork waits for all children of the current process to end before continuing. Each initial block is an independent process and there are no child processes of the last initial block.

Your simulation ends at time 5 instead of time 100 is reason #3 of why I recommend never using program blocks. Use a module instead.

In reply to dave_59:

Hi Dave,

What make the module to wait for “timeout_fork” process to finish?

In reply to kuki2002:

I’m not sure I understand your question. There is no module in the example. There is a program block that waits for all initial blocks to finish. timeout_fork is a fork/join_any block that waits for any statement inside the fork to finish. The #5; statement is the first to finish, so that makes the task consume_time return and its initial block finish.

In reply to dave_59:

Hi Dave,

Sorry for not being clear. I mean when I used module instead of program (as suggested by you in one of the comments), the test waited for timeout_fork process to finish which was not the case for program i.e. module code ended at time 100 while program at time 5. What property of the module makes it wait for the timeout_fork process to finish?

In reply to kuki2002:

Simulation normally ends when the current time slot event queue is empty, and there is nothing scheduled in any other future time slot. Exception are an explicit call to $finish or the implicit call to $finish caused by the program block.

In reply to dave_59:

In reply to kuki2002:
Simulation normally ends when the current time slot event queue is empty, and there is nothing scheduled in any other future time slot. Exception are an explicit call to $finish or the implicit call to $finish caused by the program block.

Dave :
" Simulation normally ends when the current time slot event queue is empty, and there is nothing scheduled in any other future time slot. "
Would you also explain how “always” thread works in current time slot event queue and being scheduled/terminated?
Thanks

In reply to dave_59:

Thanks Dave

In reply to VE:

If you have code like

always #5 clk = ! clk;

That is a process that repeatedly suspends itself and schedules something for a future time slot—you must use $finish to finish the simulation.

But if you have

always @(posedge clk) Q <= D;

That is a process that repeatedly suspends itself waiting for a clock edge. It does not schedule anything for a future time slot. The resumption of the process only goes onto the active event queue after the clock edge happens.