绿皮书 Systemverilog 180页提到:begin…end中的语句以顺序方式执行,而fork…join中的语句则以并发形式。
由于对书中例子理解不到位,一度以为begin…end块之间是并发执行, 内部是顺序执行。因此环境中出现了如下写法, code 1。
//===============code 1========================//
virtual task drive_one_pkt(crg_transfer tr);
fork
begin
clk_driver(tr);
end
begin
rst_driver(tr);
end
join_none
endtask
由于begin end 包起来的顺序执行用的太多了,总觉得以上代码很别扭。今天看到了别人的fork join里没有begin…end,于是怀疑自己的写法,因此做了如下测试。
module test_fork;
initial begin
fork:A
$display($time, " FORK A: first execute);
$dispaly($time, " FORK A: second execute");
join
fork:B
$display($time, " FORK B: first execute);
#10;
$dispaly($time, " FORK B: second execute");
join
fork:C
$display($time, " FORK C: first execute);
begin
#10;
$display($time, " FORK C: when execute);
end
$dispaly($time, " FORK C: second execute");
join
fork:D
begin
$display($time, " FORK D: first execute);
#10;
end
begin
#10;
$dispaly($time, " FORK D: second execute");
end
join
end
endmodule
执行结果如下:
0 FORK A:first execute
0 FORK A:second execute
0 FORK B:first execute
0 FORK B:second execute
10 FORK C:first execute
10 FORK C:second execute
20 FORK C:when execute
20 FORK C:first execute
30 FORK C:second execute
fork A的执行结果看不出来是并发还是顺序执行。
fork B的执行结果表明里面的三句代码是并发执行,因为first和second 同时发送,second并没有wait 10ns再打印。
fork C的执行结果表明,first second和 begin…end 块是并发执行。
fork D的执行结果表明,begin…end 块内部顺序执行。
因此,在fork … join中,不需要加begin…end去区分是否并发。无论加不加,都是并发。begin…end仅作用于内部,进行顺序执行。
因此 , code1 的正确写法是:
//===============code 1========================//
virtual task drive_one_pkt(crg_transfer tr);
fork
clk_driver(tr);
rst_driver(tr);
join_none
endtask
clk_driver和rst_dirver会并发执行,而非顺序。