Events construct in SV

I am not able to understand the difference between @(e1.triggered) & wait(e1.triggered) operator.

example–

event e1; // event declaration

initial
begin
->e1;
@(e1.triggered()); //using @(e1.triggered())
end

initial
begin
->e1;
wait(e1.triggered()); //using wait(e1.triggered());
end

First, I will caution you on the use of events in SystemVerilog. They should be used only by advanced users, and the use of event.triggered() is for people working around the mistakes they made incorrectly using events. Actually, it’s not that bad, but I would always think of a better way before reverting to using an event.

Remember that @(expression) means block waiting for any change in the value of that expression, or block waiting for the valueless trigger of an event. Both the change and triggering are instantaneous occurrences, and the ordering of the @() versus the change/trigger is critical. Trying to do both at the same time is the cause of many race conditions.

wait(expression) means block waiting for the expression to become true. If the expression is already true when executing the wait statement, it does not block at all, so ordering is not as critical. You cannot use the wait statement with a named event because an event has no value, it can only be triggered instantaneously.

The triggered method of an event is a function that returns true if the event has been triggered in the current time step. It continues to return true until the end of the current time step.

In both your examples, e1.triggered() is already true. So @(e1.triggered()) blocks until the end of the time step when e1.triggered() changes to return false. wait(e1.triggered() never blocks because it is already true.

In reply to dave_59:

dave_59,

Thanks sir, for the wonderful explanation.

In reply to arvind kumar:

Dave, What is the expected behavior when i use event.triggered in sensitivity list?

always@ (e1.triggered) begin
$display("Event triggered");
end

lets say in timestep t1 event is triggered then i expected above code to execute once in t1 and again in t2. because event.triggered will change to false in t2. But the block is getting executed only once. even when i trigger e1 twice the above block is executing only once.
What is wrong with the above code?

In reply to Naven8:

dave_59 writes:

First, I will caution you on the use of events in SystemVerilog. They should be used only by advanced users, and the use of event.triggered() is for people working around the mistakes they made incorrectly using events. Actually, it’s not that bad, but I would always think of a better way before reverting to using an event.

Can you describe how you typically avoid events? Here, I’m not
looking for a rule just a rather a guideline or a preferred
approach to avoid them. Thanks.

In reply to mpettigr:

It really depends on what you are trying to accomplish with the event. In the simplest case with a single trigger and a single spot in the code waiting on the trigger, you might be able to restructure your code to call a task instead. The UVM provides many other kinds of synchronization mechanisms like TLM ports and objections that be used instead.