systemverilog中fork..join, join_any, join_none的用法和解析

1、fork.. join, join_any以及join_none的用法进行总结

1.1、   fork..join

        fork..join: 必须等到statement1,statement2,statement3全部执行完之后,statement4才可以执行。fork…join内的所有语句都是并发执行(对于begin…end内部是顺序执行)
示例:

//---------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_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

1.2、fork..join_any

        fork..join_any: 等到statement1,statement2,statement3之中任何一个执行完毕之后,statement4才可以执行。一旦fork…join_any内任何一个线程完成,父线程就会继续运行。fork…join_none块在调度其块语句时,父线程继续执行。

//---------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

程序运行结果:

1.3、fork..join_none

        fork..join_none: statement4的执行与否不依赖于statement1,statement2和statement3,他们可以同步执行。子线程和父线程会同时执行。

//---------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


 

在使用过程中经常需要多线程操作,多线程的正确写法为:

for(int i=0;i<3;i++)begin
    fork
        automatic idx = i
        begin
            `uvm_do(do[i]);
        end        
    join_none
end

        这样就完成了一个简单的多线程,这里为什么要用automatic关键字定义idx,可以参考下面的详细解释。

2、局部数据存储 automatic作用

        Verilog中由于任务中局部变量会使静态存储区,当在多个地方调用同一个任务时,不同线程之间会窜用这些局部变量。

        Systemverilog中,module和program块中,缺省使用静态存储;如果想使用自动存储,需加入automatic关键词。

你可能感兴趣的:(Systemverilog,SystemVerilog)