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
Feature | Delay Control | Event Control |
---|---|---|
Type of Control | Time-based delay | Based on signal transitions (posedge/negedge) |
Purpose | Introduces a delay before execution | Synchronizes execution based on signal changes |
Syntax | #<delay_expression> | @(posedge signal) or @(negedge signal) |
Units Supported | Nanoseconds, picoseconds, etc. | Not time-based, based on signal edges |
Used For | Timing control and simulation accuracy | Event detection and synchronization of procedural blocks |