0
votes

I was reading about SV Merging events from this website. The code is as follows:

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

The result for the same is:

0  Waiting for the Event to trigger
40  Triggering The Event
100 Ending the Simulation

In this particular code, the trigger is being executed first at 40 time units, then the waiting is applied at 60 time units. It is known that, if the trigger executes first, then the waiting process remains blocked. If I use #60 wait(ev_1.triggered); in the line 17 this can be resolved. However, it is still showing the same result? I want to know the concept behind this.

2

2 Answers

2
votes

Mechanism is pretty simple: value of event.triggered is only set in the same simulation tick as when it was triggered. It is not sticky and becomes 0 in the next tick.

It is known that, if the trigger executes first, then the waiting process remains blocked.

Yes, because the unblocking event has already passed and #60 is too late for it to be detected. So, it cannot be detected any longer neither by @ nor by wait.

Now, what you can do is to set a sticky variable at the event, for example as triggered in the following:

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

There however, you can see a difference in semantics between @ and wait operators. @ waits for a change of the value, which happened at #40 and it will not be able to catch it at #60 as well. wait on the other hand, waits for a level, for triggered to become 1'b1. So, it will work here since the sticky var has been already set.

1
votes

The example on that website is not very good. You would never want to use @ with the triggered method.

When you trigger an event with -> ev_1 or ->> ev_1, The triggered method of that event is only valid from moment of the trigger (or NBA region of the trigger for ->>) until the end of the time step.

The @ev_1 must be executed before the moment of the trigger. Otherwise it has to wait for the next trigger.

The wait(ev_1.triggered()) construct is only useful if it gets executed before the trigger, OR within the same timestep and there is potential race condition between the point of trigger AND waiting for that trigger.

Using raw events is not something I would recommend for most users. There are usually more software like mechanisms to achieve the same thing.