If there is a delay in a task and when it is called, it blocks the execution flow. Many times in verification it requires to start a process and continue with the rest of the flow. The following example demonstrated how the task block the execution flow.
EXAMPLE: module tb();
initial begin blocking_task();
#5 $display(" Statement after blocking_task at %t ",$time);
end
task blocking_task();
begin #10;
$display(" statement inside blocking task at %t",$time);
end endtask endmodule RESULTS:
statement inside blocking task at 10 Statement after blocking_task at 15
To make the task call does not block the flow, use events as follows. The event triggers the always block and the task is started. This does not block the flow.
EXAMPLE: module tb();
event e;
initial begin #1 ->e;
#5 $display(" Statement after blocking_task at %t ",$time);
#20 $finish;
end
always@(e)
begin blocking_task();
end
task blocking_task();
begin #10;
$display(" statement inside blocking task at %t",$time);
end endtask endmodule RESULTS
Statement after blocking_task at 6 statement inside blocking task at 11
Fork/Join Recap:
Fork/join is a parallel block. Statements shall execute concurrently. Delay values for each statement shall be considered relative to the simulation time of entering the block. Delay control can be used to provide time-ordering for assignments Control shall pass out of the block when the last time-ordered statement executes. The timing controls in a fork-join block do not have to be ordered sequentially in time.
EXAMPLE:
module fork_join();
integer r ;
initial fork #50 r = 35;
#100 r = 24;
#150 r = 00;
#200 r = 7;
#250 $finish;
join
initial $monitor("%t , r is %d",$time,r);
endmodule
RESULTS:
50 , r is 35 100 , r is 24 150 , r is 0 200 , r is 7
As the statements are parallel running, there is race condition between some statements. In the following example, first statement after delay of 50 + 100, r is 24 and in second statement at 150 r is 00. But only the statement which is executed last overrides previous value.
EXAMPLE: module fork_join();
integer r ;
initial fork begin #50 r = 35;
#100 r = 24;
end #150 r = 00;
#200 r = 7;
#250 $finish;
join
initial $monitor("%t , r is %d",$time,r);
endmodule
RESULTS:
50 , r is 35 150 , r is 24 200 , r is 7
Fork/Join None
In the fork join, the parent process continues to execute after all the fork/join processes are completed. To continue the parent process concurrently with all the processes spawned by the fork use this trick. This is as simple as above nonblocking task example. Just use fork/join the always block as shown below.
EXAMPLE: module tb();
event e;
initial begin #1 ->e;
#5 $display(" Statement after blocking_task at %t ",$time);
#40 $finish;
end
always@(e)
begin fork blocking_task_1();
blocking_task_2();
join end
task blocking_task_1();
begin #10;
$display(" statement inside blocking task_1 at %t",$time);
end endtask
task blocking_task_2();
begin #20;
$display(" statement inside blocking task_2 at %t",$time);
end endtask
endmodule RESULTS
Statement after blocking_task at 6 statement inside blocking task_1 at 11 statement inside blocking task_2 at 21
Fork/Join Any
If you want to continue the parent process after finishing any of the child process, then block the parent process until an event if triggered by the forked threads.
EXAMPLE: module tb();
event e,ee;
initial begin #1 ->e;
@(ee);
$display(" Statement after blocking_task at %t ",$time);
#40 $finish;
end
always@(e)
begin fork begin blocking_task_1(); -> ee;end begin blocking_task_2(); -> ee;end join end
task blocking_task_1();
begin #10;
$display(" statement inside blocking task_1 at %t",$time);
end endtask
task blocking_task_2();
begin #20;
$display(" statement inside blocking task_2 at %t",$time);
end endtask endmodule RESULTS
statement inside blocking task_1 at 11 Statement after blocking_task at 11 statement inside blocking task_2 at 21