在SystemVerilog中,用來觸發事件時,使用->;用來等待事件使用@或者wait。那么@和wait有什么區別呢?
在Verilog中當一個線程在一個事件上發生阻塞的同時,正好另一個線程觸發了這個事件,則競爭就出現了。如果觸發線程先於阻塞線程,則觸發無效(觸發是一個零寬度的脈沖);
例如:verilog中使用@等待某個event產生競爭
`timescale 1ns/10fs
module event_test();
event a; //使用關鍵字event來聲明一個事件a
initial begin
#50ns;
->a;
end
initial begin
#50ns;
@a; //第一個進程在50ns后觸發了事件a,第二個進程在50ns的時候等待a,有可能等的到,有可能等不到,產生競爭
end
endmodule
一、解決方法:
Systemverilog 引入了triggered()函數,用於檢測某個事件是否已被觸發過,包括正在觸發。線程可以等待這個結果,而不用在@操作符上阻塞。
1.2、使用wait(event_a.triggered)等待event
module event_test();
event a; //使用關鍵字event來聲明一個事件a
initial begin
#50;
->a;
$display("Event a is being triggered!");
end
initial begin
#20;
wait(a.triggered); **//使用wait來等待事件a,這種方式是一定可以等到a的**
$display("#20 a.triggered!");
end
initial begin
#50;
wait(a.triggered); **//使用wait來等待事件a,這種方式是一定可以等到a的,這是和使用@來等待的區別**
$display("#50 a.triggered!");
end
initial begin
#60;
wait(a.triggered); **//使用wait來等待事件a,a會被trigger一次,並且並且發生在wait之前,永遠等不到**
$display("#60 a.triggered!"); //不會被打印
end
endmodule
從上面可以看出,使用wait(event.triggered)要優於使用@event的方法,但wait(event.triggered)的方法在任何時候都會優於@event嗎?
看下面這個例子:
forever begin
wait(handshake.triggered); //注意不要寫成wait(handshake.triggered()),會有編譯錯誤,因為triggered不是一個function
$display("get nexr event ...");
process_in_zero_time();
end
如果是在循環中使用wait(event.triggered),並且在下次等待之前沒有延時,那么該事件一旦被觸發就會反復執行,對上面的例子,如果某一時刻觸發了handshake事件,則該Thread就會一直display(導致仿真Hang死),這種結果不是我們想要的,解法有兩種:
1、wait(handshake.triggered)之后增加讓時間推進的操作,如@(clk)。
forever begin
wait(handshake.triggered);
$display("get nexr event ...");
process_in_zero_time();
@clk;
end
2、將wait(handshake.triggered)換成@handshake,可以避免零延時循環。
forever begin
@handshake;
$display("get nexr event ...");
process_in_zero_time();
end