Events in SystemVerilog

Events are synchronization objects that allow one process to signal another process. Think of them as flags that say "something happened!"

What Are Events?

An event is like a doorbell. One process rings it (triggers), and another process waiting for it wakes up. Events have no data - they just signal "something happened".

Basic Event Example
event done;  // Declare an event

initial begin
    fork
        // Process 1: Wait for event
        begin
            $display("[%0t] Waiting for event...", $time);
            @(done);  // Block until event triggers
            $display("[%0t] Event received!", $time);
        end
        
        // Process 2: Trigger event
        begin
            #10;
            $display("[%0t] Triggering event!", $time);
            -> done;  // Trigger the event
        end
    join
end

// Output:
// [0] Waiting for event...
// [10] Triggering event!
// [10] Event received!

Triggering Events

-> (Named Event Trigger)

The standard way to trigger an event:

Standard Trigger
event my_event;

initial begin
    -> my_event;  // Trigger immediately
end

->> (Non-blocking Event Trigger)

Schedules the trigger for a later time in the same time slot. Useful to avoid race conditions:

Non-blocking Trigger
event my_event;

initial begin
    ->> my_event;  // Schedule trigger (non-blocking)
    $display("This prints first");
end

Waiting for Events

@ operator

Blocks until the event triggers. Simple but can miss events:

Using @ Operator
@(my_event);  // Wait for next trigger
$display("Event happened!");

wait() with .triggered

Better approach - catches events triggered in the same time slot:

Using wait(.triggered)
event my_event;

initial begin
    fork
        begin
            wait(my_event.triggered);  // Catches same-timestep triggers
            $display("Event caught!");
        end
        begin
            -> my_event;  // Trigger immediately
        end
    join
end

Practical Example: Driver-Monitor Sync

Driver-Monitor Synchronization
class Testbench;
    event transaction_complete;
    event check_done;
    
    task run();
        fork
            driver();
            monitor();
        join
    endtask
    
    task driver();
        repeat(5) begin
            // Drive transaction
            $display("[%0t] Driving transaction", $time);
            #10;
            
            // Signal that transaction is complete
            -> transaction_complete;
            
            // Wait for checker to finish before next transaction
            @(check_done);
        end
    endtask
    
    task monitor();
        repeat(5) begin
            // Wait for transaction to complete
            @(transaction_complete);
            $display("[%0t] Checking transaction", $time);
            #5;  // Simulation of checking time
            
            // Signal checker is done
            -> check_done;
        end
    endtask
endclass

Event Variables and Assignment

Events can be assigned to each other, creating aliases:

Event Assignment
event e1, e2;

initial begin
    e2 = e1;  // e2 now points to same event as e1
    
    fork
        begin
            @(e2);  // Wait on e2
            $display("e2 triggered!");
        end
        begin
            #10;
            -> e1;  // Trigger e1 (also triggers e2!)
        end
    join
end

Quick Summary

  • event - Synchronization object with no data
  • -> - Trigger event (blocking)
  • ->> - Trigger event (non-blocking)
  • @(event) - Wait for event trigger
  • wait(event.triggered) - Better wait, catches same-timestep
  • Events can be assigned (aliased) to each other