标准的Verilog对语句有两种分组方式——使用begin…end或fork…join,begin…end中的语句以顺序方式执行,而fork…join中的语句则以并发方式执行。后者的不足是必须等fork…join内的所有语句都执行完以后才能继续块内后续的处理。因此,在Verilog的测试平台中很少用到它。
System Verilog引入了两种新的创建线程的方法——使用fork…join_none和fork…join_any语句
1.join:The parent process blocks until all the processes spawned by this fork complete.
简单来说:fork…join内的所有语句都是并发执行(对于begin…end内部是顺序执行)
2.join_any:The parent process blocks until any one of the processes spawned by this fork completes.
简单来说:一旦fork…join_any内任何一个线程完成,父线程就会继续运行
3.join_none:The parent process continues to execute concurrently with all the processes spawned by the fork. The spawned processes do not start executing until the parent thread executes a blocking statement or terminates.
简单来说:子线程和父线程会同时执行
下面看一下代码简单分析:
//---------fork...join-------------
initial begin
$display("@ %0t: start fork...join example", $time);
#10 $display("@ %0t: sequential after # 10", $time);
fork
$display("@ %0t: parallel start", $time);
#50 $display("@ %0t: parallel start # 50", $time);
#10 $display("@ %0t: parallel after #10", $time);
begin
#30 $display("@ %0t: sequential after # 30", $time);
#10 $display("@ %0t: sequential after # 10", $time);
end
join
$display("@ %0t: after join", $time);
#80 $display("@ %0t: finish after # 80", $time);
end
程序运行结果:
@ 0: start fork...join example
@ 10: sequential after # 10
@ 10: parallel start
@ 20: parallel after #10
@ 40: sequential after # 30
@ 50: sequential after # 10
@ 60: parallel start # 50
@ 60: after join
@ 140: finish after # 80
fork…join_none块在调度其块语句时,父线程继续执行。下面的代码与上面代码除了join被换成了join_none以外,其余均相同。
//---------fork...join_none-------------
initial begin
$display("@ %0t: start fork...join_none example", $time);
#10 $display("@ %0t: sequential after # 10", $time);
fork
$display("@ %0t: parallel start", $time);
#50 $display("@ %0t: parallel start # 50", $time);
#10 $display("@ %0t: parallel after #10", $time);
begin
#30 $display("@ %0t: sequential after # 30", $time);
#10 $display("@ %0t: sequential after # 10", $time);
end
join_none
$display("@ %0t: after join_none", $time);
#80 $display("@ %0t: finish after # 80", $time);
end
程序运行结果:
@ 0: start fork...join_none example
@ 10: sequential after # 10
@ 10: after join_none
@ 10: parallel start
@ 20: parallel after #10
@ 40: sequential after # 30
@ 50: sequential after # 10
@ 60: parallel start # 50
@ 90: finish after # 80
fork…join_any块对块内语句进行调度,当第一个语句完成后,父线程才继续执行,其他停顿的线程也得以继续。代码如下:
//---------fork...join_any-------------
initial begin
$display("@ %0t: start fork...join_any example", $time);
#10 $display("@ %0t: sequential after # 10", $time);
fork
$display("@ %0t: parallel start", $time);
#50 $display("@ %0t: parallel start # 50", $time);
#10 $display("@ %0t: parallel after #10", $time);
begin
#30 $display("@ %0t: sequential after # 30", $time);
#10 $display("@ %0t: sequential after # 10", $time);
end
join_any
$display("@ %0t: after join_any", $time);
#80 $display("@ %0t: finish after # 80", $time);
end
运行结果如下:
@ 0: start fork...join_any example
@ 10: sequential after # 10
@ 10: parallel start
@ 10: after join_any
@ 20: parallel after #10
@ 40: sequential after # 30
@ 50: sequential after # 10
@ 60: parallel start # 50
@ 90: finish after # 80