@event Vs wait(event.triggered) in SystemVerilog
SystemVerilog supports two ways through which we can wait for a particular event to be triggered. So let’s understand what is the exact difference between those two ways of event trigger with the following example.
event e;
// Triggered event 'e'
->e;
// wait for event 'e' to be triggered (instantaneous)
@(e);
An event trigger ->e is an instantaneous event. The event control @e has to execute and block the current process before the trigger occurs in another process, and the blocking process resumes. Many times there are race conditions between the two processes and the trigger executes before the event control, and the event is missed, and the event control has to wait for another trigger.
// wait for event 'e' to be triggered (Persistent)
wait(e.triggered);
The wait(e.triggered) statement says wait for the condition that event e has been triggered in the current time slot means it evaluates as true (1’b1) if event e has been triggered in the current time slot else false (1’b0).
Now you no longer have to worry about which came first, the trigger or the wait statement. But you still have to execute the wait statement in the current time slot to catch the event.
the triggering process –> or the waiting process @ statement. But you still have to execute the waiting process @ in the current time slot to catch the event.
Let’s see the actual behavior of event trigger and wait statements with below examples
Example_1: Missed Event Trigger
class event_class;
event e;
task trigger;
->e;
endtask : trigger
task execute;
@(e);
$display("Testing of the event @");
endtask : execute
// First trigger event and after that
// wait for event to be triggered in same simulation time
task ex;
trigger;
execute;
endtask : ex
endclass : event_class
program main();
event_class E;
initial begin
E = new();
fork
begin
E.ex; // wait using @
end
begin
#10;
$display("Missed Event trigger");
end
join_any
disable fork;
end
endprogram : main
Example_2: Testing of the event @ (wait)
class event_class;
event e;
task trigger;
->e;
endtask : trigger
task execute;
wait(e.triggered);
$display("Testing of the event @(wait)");
endtask : execute
// First trigger event and after that
// wait for event to be triggered in same simulation time
task ex;
trigger;
execute;
endtask : ex
endclass : event_class
program main;
event_class E;
initial begin
E = new();
fork
begin
E.ex; // wait using wait(event.triggered)
end
begin
#10;
$display("Missed Even Trigger");
end
join_any
disable fork;
end
endprogram : main
Non-Blocking Event ->>
Non-blocking events are triggered using the ->> operator.
The effect of the ->> operator is that the statement executes without blocking and it creates a non-blocking assign update event in the time in which the delay control expires or the event control occurs. The effect of this update event shall be to trigger the referenced event in the nonblocking assignment region of the simulation cycle.
Let’s understand behavior of Non-blocking Event with below example
program main;
event blocking_e;
event non_blocking_e;
process process_b;
process process_nb;
initial begin
fork
begin
process_b = process::self();
-> blocking_e;
@ blocking_e;
end
begin
process_nb = process::self();
->> non_blocking_e;
@ non_blocking_e;
end
join_none
#10;
$display("process_b.status:%s", process_b.status);
$display("process_nb.status:%s", process_nb.status);
end
endprogram : main