Timing Controls
Delay control #, event control @, wait statement.
Timing controls in Verilog are mechanisms that specify when a statement should execute relative to simulation time or signal events. They are fundamental to writing behavioral models that correctly simulate sequential and combinational logic. Without timing controls, all statements in an initial or always block would execute in zero simulation time, which does not reflect real hardware behavior.
Core Concept: Timing Controls in Verilog
Verilog provides three fundamental timing control constructs: the delay control using the # operator, the event control using the @ operator, and the wait statement. Each of these suspends execution of a procedural block for a different reason — time-based, event-based, or condition-based — and each is used in different design and verification contexts.
The delay control #N causes the simulator to advance simulation time by N units before executing the next statement. For example, #10 a = b; means: wait 10 time units, then assign b to a. This is widely used in testbenches to generate stimulus with realistic timing. In synthesizable RTL code, delay controls are ignored by synthesis tools, but they are critical for simulation accuracy.
The event control @ suspends execution until a specified signal event occurs. The most common form is @(posedge clk), which waits for a rising clock edge. The sensitivity list in a combinational always block uses @(*) or @(a or b or c), which triggers whenever any listed signal changes. Omitting a signal from the sensitivity list is a common mistake that causes simulation-synthesis mismatch.
Wait Statement: Level-Sensitive Blocking
The wait statement operates on signal levels rather than edges. The statement wait(condition) blocks execution until the Boolean condition evaluates to true. If the condition is already true when the wait statement is reached, execution proceeds immediately without any delay. This makes it fundamentally different from the @ event control, which always waits for a transition.
The wait statement is primarily used in testbenches for handshaking sequences. For example, a testbench might use wait(ready == 1) before driving data onto a bus, ensuring the design under test has signaled readiness. Using wait in synthesizable RTL is generally not recommended and is not supported by most synthesis tools.
Intra-Assignment Delay
Verilog also supports intra-assignment delay, where the delay is placed between the assignment operator and the right-hand side expression. The syntax a = #5 b; means: sample the current value of b immediately, wait 5 time units, then assign the sampled value to a. This is different from #5 a = b; where both the sampling and assignment are delayed. Intra-assignment delay is useful when the right-hand side signal might change during the delay period and you want to capture its present value.
Mathematical Expression
Simulation time advances according to the event queue. When a delay #N is encountered, the current process is suspended and re-activated at time T_current + N. For event control @(E), the process suspends until signal E has an event at some future time T_event where T_event is greater than or equal to T_current. The wait statement suspends while condition C is false and resumes at the earliest time T_resume where C becomes true.
Practical Understanding
A clock generator in a testbench uses the delay control in a forever loop: always #5 clk = ~clk; creates a clock with a period of 10 time units and 50% duty cycle. This is one of the most common uses of delay control in Verilog. Changing #5 to #4 and #6 alternately in two assignments would create an asymmetric clock.
For synchronous flip-flop modeling, the always @(posedge clk) block ensures the flip-flop state updates only on rising clock edges. Adding or missing an edge qualifier in the sensitivity list dramatically changes circuit behavior during simulation and synthesis inference.
Numerical Example: Clock Period Calculation
Given:
Verilog testbench: always #20 clk = ~clk;
Initial state of clk: 0
Timescale: `timescale 1ns/1ps
Why this formula applies:
Each toggle happens every 20 time units (20ns). One full clock cycle = two toggles.
Formula:
Clock Period T = 2 x delay value
Clock Frequency f = 1 / T
Substitution:
T = 2 x 20ns = 40ns
Calculation:
f = 1 / 40ns = 25 MHz
Duty cycle = 20ns HIGH / 40ns period = 50%
Final Answer:
Clock period = 40 ns, Frequency = 25 MHz, Duty cycle = 50%Exam Tip: In GATE and university exams, always check whether the sensitivity list in a combinational always block is complete. A missing signal in @(a or b) when the output also depends on c causes a latch to be inferred — this is a classic simulation-synthesis mismatch trap.
Mechanism: How Timing Controls Work in the Simulator
- Delay control #N suspends the process and re-activates it exactly N simulation time units later. Used extensively in testbenches for stimulus generation.
- Event control @(signal) suspends until a signal event (edge or level change) occurs. @(posedge clk) and @(negedge clk) are edge-triggered; @(*) is a wildcard sensitivity list.
- The wait statement is level-sensitive and blocks until the specified condition becomes true. If already true, execution continues without suspension.
- Intra-assignment delay (a = #N b;) samples the right-hand side immediately but defers the left-hand side assignment. Regular delay (#N a = b;) defers both sampling and assignment.
Quick Revision
- Three timing controls: # (delay, time-based), @ (event-based, edge or level), wait (condition-based, level-sensitive).
- Clock generator: always #T clk = ~clk; produces clock period = 2T.
- Synthesis ignores # delays. They are simulation-only constructs in RTL context.
- Incomplete sensitivity list in @() causes latches in synthesis — always use @(*) for combinational logic.
- wait vs @: wait is level-sensitive (condition must be true), @ is edge-sensitive (transition must occur).
- Intra-assignment delay: RHS sampled now, LHS updated after delay. Regular delay: both deferred.
- Common GATE trap: #0 delay does not mean no delay — it defers execution to the end of the current simulation time step.
Verilog Timing Controls
Test your knowledge on this topic.
Q1.What is the function of the @(posedge clk) event control?
Related Articles
Control Statements
If-else, case, casez, casex statements.
4 min read
Loops in Verilog
For, while, repeat, forever loops.
8 min read
Procedural Blocks
Always block, initial block, sensitivity lists.
4 min read
Blocking vs Non-Blocking
Operators = vs <=, scheduling semantics.
7 min read
Task and Function
Subroutines, differences, automatic re-entrancy.
5 min read