Verilog, a hardware description language (HDL), provides various ways to control the timing and synchronization of simulation events. These controls are essential for accurate simulation of digital circuits. Two primary types of timing controls are used in Verilog: delay control and event control.

1. Verilog Delay Control

Verilog provides a delay control mechanism to introduce a delay between the execution of a statement and the time the simulator actually performs the operation. This delay can be specified in time units, such as nanoseconds or picoseconds.

Key Points About Delay Control:
  • Delay Expression: Verilog uses delay expressions, which define the amount of time the simulator should wait before executing a statement.
  • Zero Delay: If the delay expression evaluates to an unknown ('x) or high-impedance ('z) value, it is treated as zero delay.
  • Negative Delay: A negative value in the delay expression is interpreted as a two’s complement unsigned integer.
  • Time Units: The delay time can be defined in different units such as nanoseconds, picoseconds, etc.
Example Code: Verilog Delay Control
`timescale 1ns/1ps

module tb;
  reg [3:0] a, b;

  initial begin
    {a, b} <= 0;
    $display("T=%0t a=%0d b=%0d", $realtime, a, b);

    #10;
    a <= $random;
    $display("T=%0t a=%0d b=%0d", $realtime, a, b);

    #10 b <= $random;
    $display("T=%0t a=%0d b=%0d", $realtime, a, b);

    #(a) $display("T=%0t After a delay of a=%0d units", $realtime, a);
    #(a+b) $display("T=%0t After a delay of a=%0d + b=%0d = %0d units", $realtime, a, b, a+b);
    #((a+b)*10ps) $display("T=%0t After a delay of %0d * 10ps", $realtime, a+b);

    #(b-a) $display("T=%0t Expr evaluates to a negative delay", $realtime);
    #('h10) $display("T=%0t Delay in hex", $realtime);

    a = 'hX;
    #(a) $display("T=%0t Delay is unknown, taken as zero a=%h", $realtime, a);

    a = 'hZ;
    #(a) $display("T=%0t Delay is in high impedance, taken as zero a=%h", $realtime, a);

    #1ps $display("T=%0t Delay of 10ps", $realtime);
  end

endmodule

2. Event Control in Verilog

Event control in Verilog uses event expressions to synchronize actions based on signal changes. These events can be triggered by transitions in signal values.

Types of Event Control:
  • Posedge (Positive Edge): Triggered when a signal changes from 0 to 1.
  • Negedge (Negative Edge): Triggered when a signal changes from 1 to 0.
  • Any Change: Triggered on any change of a signal.
Example Code: Verilog Event Control
module tb;
  reg a, b;

  initial begin
    a <= 0;
    #10 a <= 1;
    #10 b <= 1;
    #10 a <= 0;
    #15 a <= 1;
  end

  // Detect positive edge of signals
  initial begin
    @(posedge a);
    $display("T=%0t Posedge of a detected for 0->1", $time);
    @(posedge b);
    $display("T=%0t Posedge of b detected for X->1", $time);
  end

  initial begin
    @(posedge (a + b)) $display("T=%0t Posedge of a+b", $time);
    @(a) $display("T=%0t Change in a found", $time);
  end
endmodule

3. Named Events

Verilog allows you to define named events using the event keyword. These events do not carry data, but can be triggered or waited upon during simulation.

Example Code: Named Events
module tb;
  event a_event;
  event b_event[5];

  initial begin
    #20 -> a_event;
    #30; -> a_event;
    #50 -> a_event;
    #10 -> b_event[3];
  end

  always @(a_event) $display("T=%0t [always] a_event is triggered", $time);

  initial begin
    #25;
    @(a_event) $display("T=%0t [initial] a_event is triggered", $time);
    #10 @(b_event[3]) $display("T=%0t [initial] b_event is triggered", $time);
  end
endmodule

4. Using the or Operator with Events

The or operator (or) can be used to wait for any one of multiple events. The comma (,) operator is also supported as a shorthand.

Example Code: Using or for Event Synchronization
module tb;
  reg a, b;

  initial begin
    $monitor("T=%0t a=%0d b=%0d", $time, a, b);
    {a, b} <= 0;

    #10 a <= 1;
    #5  b <= 1;
    #5  b <= 0;
  end

  // Use "or" between events
  always @(posedge a or posedge b)
    $display("T=%0t posedge of a or b found", $time);

  // Use a comma between
  always @(posedge a, negedge b)
    $display("T=%0t posedge of a or negedge of b found", $time);

  always @(a, b)
    $display("T=%0t Any change on a or b", $time);
endmodule

5. Level-Sensitive Event Control

Verilog allows execution of procedural statements to be delayed until a specific condition is met, which can be accomplished using the wait statement. This is a level-sensitive control, as it waits for the condition to become true before proceeding.

Example Code: Level-Sensitive Event Control with wait
module tb;
  reg [3:0] ctr;
  reg clk;

  initial begin
    {ctr, clk} <= 0;

    wait(ctr);
    $display("T=%0t Counter reached non-zero value 0x%0h", $time, ctr);

    wait(ctr == 4) $display("T=%0t Counter reached 0x%0h", $time, ctr);

    $finish;
  end

  always #10 clk = ~clk;

  always @(posedge clk)
    ctr <= ctr + 1;

endmodule

Conclusion

Verilog provides several ways to control timing and synchronization during simulations. Delay controls introduce time delays before executing a statement, while event controls synchronize procedural statements based on signal transitions. Named events and the or operator allow for more complex event management. Finally, the wait statement enables level-sensitive waiting for conditions to become true, ensuring that statements execute at the right time.

By understanding and using these controls effectively, you can simulate digital circuits accurately and debug potential issues in your design.


Comparison Table: Delay Control vs. Event Control

FeatureDelay ControlEvent Control
Type of ControlTime-based delayBased on signal transitions (posedge/negedge)
PurposeIntroduces a delay before executionSynchronizes execution based on signal changes
Syntax#<delay_expression>@(posedge signal) or @(negedge signal)
Units SupportedNanoseconds, picoseconds, etc.Not time-based, based on signal edges
Used ForTiming control and simulation accuracyEvent detection and synchronization of procedural blocks