我正在这个网站上阅读关于SV合并的事件。代码如下:
module events_ex;
event ev_1; //declaring event ev_1
initial begin
fork
//process-1, triggers the event
begin
#40;
$display($time,"tTriggering The Event");
->ev_1;
end
//process-2, wait for the event to trigger
begin
$display($time,"tWaiting for the Event to trigger");
#60;
@(ev_1.triggered);
$display($time,"tEvent triggered");
end
join
end
initial begin
#100;
$display($time,"tEnding the Simulation");
$finish;
end
endmodule
同样的结果是:
0 Waiting for the Event to trigger
40 Triggering The Event
100 Ending the Simulation
在这个特定的代码中,触发器首先在40 time units
处执行,然后在60 time units
处应用等待。众所周知,如果触发器先执行,那么等待进程将保持阻塞状态。如果我在line 17
中使用#60 wait(ev_1.triggered);
,这可以解决。然而,它仍然显示相同的结果?我想知道这背后的概念。
机制非常简单:event.triggered
的值仅在触发时的相同模拟tick中设置。它不具有粘性,在下一个刻度变为0。
已知,如果触发器先执行,则等待进程保持阻塞状态。
是的,因为解除阻塞事件已经过去,#60已经太晚了,无法检测到它。因此,@
和wait
都无法再检测到它。
现在,您可以做的是在事件中设置一个粘性变量,例如下面的triggered
:
module events_ex;
event ev_1; //declaring event ev_1
logic triggered = 1'b0;
initial begin
fork
//process-1, triggers the event
begin
#40;
$display($time,"tTriggering The Event");
->ev_1;
end
begin
@(ev_1)
triggered = 1'b1; // << set the sticky var
end
//process-2, wait for the event to trigger
begin
$display($time,"tWaiting for the Event to trigger");
#60;
wait(triggered); // << wait for sticky var value of 1
$display($time, "tEvent triggered");
end
join
end
initial begin
#100;
$display($time,"tEnding the Simulation");
$finish;
end
endmodule
在中,您可以看到@
和wait
操作符之间的语义差异。@
等待值的变化,这发生在#40,它将无法捕捉到它在#60。另一方面,wait
等待关卡,因为触发变成1'b1。因此,它将在这里工作,因为已经设置了sticky变量。
那个网站上的例子不是很好。您永远不会想将@
与triggered
方法一起使用。
当您触发具有-> ev_1
或->> ev_1
的事件时,该事件的triggered
方法仅从触发时刻(或->>
触发器的NBA区域)到时间步长结束时有效。
@ev_1
必须在触发时刻之前执行。否则,它必须等待下一次触发。
wait(ev_1.triggered())
结构只有在触发器之前执行,或者在相同的时间步长内执行,并且在触发器点和等待触发器之间存在潜在的竞争条件时才有用。
我不建议大多数用户使用原始事件。通常有更多类似软件的机制来实现同样的事情。