Interprocess communication is a way to communicate between different processes and testbench components. There are three mechanisms:
Events
Events are static objects in SystemVerilog, used to synchronize different testbench components. The events are triggered using -> or ->> and the process can wait for the event to be triggered using @ operator or wait() construct.
Event | Description |
---|---|
- > | Blocking events, also know as instanteous event, block the process untill the event is triggered. |
- >> | Non-blocking events, using this operator does not block the process. Can be used when two events are triggere at the same time. |
@ | Blocks the calling process untill the given event is triggered. This is an edge-sensitive operator, hence, waiting event should be triggered before triggering an event to aviod blocking the waiting process. |
wait() | Unlike @ operator, the wait() construct does not block the process. Triggering an event and waiting for an event can occur at the same time. |
This is a two stage mechanism where:
- First Stage: trigger an event.
- Second Stage: wait for an event to be triggered.
Three Types of Event Trigger
Events are distinguished based on which stage occurs first.
- Type A: Second stage and then first stage.
- Type B: First stage followed by second stage.
- Type C: First and second stage occurs at the same time.
Combination of event triggers(-> and ->>) and wait responses(@ and wait()) can be used to synchronize processes based on the requirement.
Type A
The wait event is triggered first followed by the event.
// class
class event_typeA;
event ev;
task ev_trg();
#10;
$display("t= %0t => Trigger event", $time);
->ev;
$display("t= %0t => Event is triggered", $time);
endtask
task wait_trg();
#5;
$display("t= %0t => Wait for the event", $time);
@ev;
//wait(ev.triggered); // uncomment to comment @ev to see the difference
$display("t= %0t => Wait event is triggered", $time);
endtask
endclass
module test;
event_typeA ev_a; // class handle
task run(event_typeA arg);
arg.ev_trg();
arg.wait_trg();
endtask
initial begin
ev_a = new( ); // construct the class object
$display("---------------------- Event: Type A ----------------------");
run(ev_a);
end
endmodule
Execute the code in EDA Playground
Type B
The event is triggered first followed by the wait event.
// class
class event_typeB;
event ev;
task ev_trg();
#10;
$display("t = %0t => Trigger event", $time);
->ev;
$display("t = %0t => Event is triggered", $time);
endtask
task wait_trg();
#15;
$display("t = %0t => Wait for the event", $time);
@(ev);
//wait(ev.triggered);
$display("t= %0t => Wait event is triggered", $time);
endtask
endclass
module test;
event_typeB ev_b; // class handle
task run(event_typeB arg);
fork
arg.ev_trg();
arg.wait_trg();
join
endtask
initial begin
ev_b = new( ); // construct the class object
$display("---------------------- Event: Type B ----------------------");
run(ev_b);
end
endmodule
Execute the code in EDA Playground
Type C
Event trigger and wait event both are triggered at the same time.
// class
class event_typeC;
event ev;
task ev_trg();
$display("t = %0t => Trigger event", $time);
->ev;
$display("t = %0t => Event is triggered", $time);
endtask
task wait_trg();
$display("t = %0t => Wait for the event", $time);
@(ev);
//wait(ev.triggered);
$display("t= %0t => Wait event is triggered", $time);
endtask
endclass
module test;
event_typeC ev_c; // class handle
task run(event_typeC arg);
fork
arg.ev_trg();
arg.wait_trg();
join
endtask
initial begin
ev_c = new( ); // construct the class object
$display("---------------------- Event: Type C ----------------------");
run(ev_c);
end
endmodule
Execute the code in EDA Playground
Difference between @ Operator and wait() Construct
The wait event does not block the process. When both the event and wait event is triggered at the same it always best to use a wait() construct. If the event triggering and waiting for event trigger with @ operator happens at the same time, @ operator may miss detecting the event trigger.
// class
class event_typeC;
event ev;
task ev_trg();
$display("t = %0t => Trigger event", $time);
->ev;
$display("t = %0t => Event is triggered", $time);
endtask
task wait_trg();
$display("t = %0t => Wait for the event", $time);
//@(ev);
wait(ev.triggered);
$display("t= %0t => Wait event is triggered", $time);
endtask
endclass
module test;
event_typeC ev_c; // class handle
task run(event_typeC arg);
fork
arg.ev_trg();
arg.wait_trg();
join
endtask
initial begin
ev_c = new( ); // construct the class object
$display("---------------------- Event: Type C ----------------------");
run(ev_c);
end
endmodule
Execute the code in EDA Playground
Difference between -> and ->> Event Triggers
Similar to the @ operator and the wait() construct, the -> operator blocks the process until it is triggered, while the ->> operator does not block the process. When using the ->> operator, irrespective of the @ operator or the wait() construct, the process continues to execute. The following code illustrates these differences more clearly.
// class
class event_typeC;
event ev;
task ev_trg();
$display("t = %0t => Trigger event", $time);
->>ev;
$display("t = %0t => Event is triggered", $time);
endtask
task wait_trg();
$display("t = %0t => Wait for the event", $time);
@(ev); // comment and uncomment
//wait(ev.triggered); // comment and uncomment
$display("t= %0t => Wait event is triggered", $time);
endtask
endclass
module test;
event_typeC ev_c; // class handle
task run(event_typeC arg);
fork
arg.ev_trg();
arg.wait_trg();
join
endtask
initial begin
ev_c = new( ); // construct the class object
$display("---------------------- Event: Type C ----------------------");
run(ev_c);
end
endmodule