Verilog · Chapter 14.4 · Behavioural Modeling
Timing Controls in Verilog — Delay (#), Event (@), and Level (wait)
Timing controls decide when a procedural statement runs. Verilog has three of them. A delay-based control waits a fixed number of time units, an event-based control waits for a signal event such as a clock edge or a value change, and a level-sensitive control waits until a condition becomes true. One of these is the backbone of synchronous design, the event control that triggers every clocked always block on a clock edge. The other two are mainly simulation and testbench tools, since delays model time and pace stimulus while a level wait blocks on a condition. This lesson surveys all three controls, makes clear which are synthesizable and which are simulation only, and sets up the deeper sub-topics that drill each one, including advanced techniques such as intra-assignment delays and named events.
Foundation13 min readVerilogTiming ControlsDelayEventwaitBehavioural
Chapter 14 · Section 14.4 · Behavioural Modeling
1. The Engineering Problem
A procedural statement runs when its block is triggered — but within a block, you often need to control when a statement executes: wait for a clock edge, pace a testbench by time, or block until a condition holds. The question:
How do you control when a procedural statement runs — after a delay, on an event, or when a condition becomes true — and which of these mechanisms is synthesizable?
The answer is the three timing controls: delay (#), event (@), and level (wait). The event control @(posedge clk) is the synthesizable one — it is how clocked logic is triggered — while # delays and wait are simulation/testbench tools. This page surveys all three; the sub-topics drill each.
2. Mental Model — Three Ways to Control "When"
3. The Three Timing Controls
// DELAY (#) — wait a fixed time (simulation/testbench):
#10 a = 1; // a = 1 after 10 time units
// EVENT (@) — wait for a signal event (synthesizable for clock edges):
@(posedge clk) q <= d; // on the rising clock edge
@(a or b) y = a & b; // on a change in a or b
@(done) ... // on a named event
// LEVEL (wait) — wait until a condition is true (simulation/testbench):
wait(ready) data = bus; // block until ready=1, then assign#introduces a delay; the statement runs after the specified time. Used to pace testbench stimulus and to model timing in simulation. Not synthesizable.@introduces an event control; the statement runs when the event occurs (an edge, a value change, or a named event trigger). Edge-sensitive@is the trigger of clockedalwaysblocks — synthesizable.waitintroduces a level-sensitive control; the statement runs once the condition holds. A testbench/simulation tool. Not synthesizable.
Visual A — the three timing controls
When does the statement run?
data flow4. Synthesizable vs Simulation-Only
The practical division, central to using timing controls correctly:
| Control | Form | Synthesizable? | Use |
|---|---|---|---|
| Event (edge) | @(posedge clk) | yes | clocked always blocks |
| Event (level) | @(*) / @(a, b) | yes | combinational sensitivity |
| Delay | #10 | no | testbench pacing, sim timing |
| Level | wait(c) | no | testbench synchronization |
- Event control is the synthesizable timing mechanism —
@(posedge clk)triggers flip-flops,@(*)triggers combinational logic (Chapter 14.1). - Delays and
waitare simulation-only — synthesis ignores#delays (real timing comes from the library, Chapter 11.2) and has no hardware forwait. They belong in testbenches and timing models.
So in synthesizable design you use @ event control (especially @(posedge clk)); # and wait live in testbench code.
5. The Sub-Topics
| § | Sub-topic | Covers |
|---|---|---|
| 14.4.1 | Delay Based Timing | # delays — simple, intra-assignment; pacing and modeling (sim) |
| 14.4.2 | Event Based Timing | @ event control — edges, level, named events; the synthesizable trigger |
| 14.4.3 | Level Sensitive Timing | wait — blocking on a condition (sim) |
| 14.4.4 | Advanced Timing Techniques | intra-assignment delays, named events, combinations |
6. Common Misconceptions
"# delays create hardware timing." False. Delays model time in simulation only; synthesis ignores them, and real timing comes from the cell library. # belongs in testbenches.
"wait is synthesizable." False. wait blocks on a condition in simulation; there is no hardware equivalent. It is a testbench synchronization tool.
"Event control is only for clocks." Misleading. @(posedge clk) triggers sequential logic, but @(*)/@(a, b) is the level-sensitive event control that triggers combinational logic (14.1). Both are synthesizable event controls.
7. Debugging Lab
One timing-control debug post-mortem
8. Interview Q&A
9. Summary
Timing controls decide when a procedural statement runs:
- Delay (
#) — after a fixed time; simulation/testbench only. - Event (
@) — on a signal event (edge, change, named event);@(posedge clk)and@(*)are synthesizable (the triggers of clocked and combinational logic). - Level (
wait) — until a condition is true; simulation/testbench only.
The split: event control is synthesizable (it triggers hardware); delays and wait are simulation-only.
The sub-topics drill each: Chapter 14.4.1 Delay Based Timing (#), 14.4.2 Event Based Timing (@ — the synthesizable trigger), 14.4.3 Level Sensitive Timing (wait), and 14.4.4 Advanced Timing Techniques (intra-assignment delays, named events). After timing controls, the chapter covers branching: 14.5 Multiway Branching (if/case).
Related Tutorials
- always & initial Blocks — Chapter 14.1; the event control (
@) that triggersalwaysblocks. - Gate Delays — Chapter 11.2; the simulation-only nature of
#delays. - Time Functions — Chapter 8.3; the simulation time that delays advance.
- Simulation Control — Chapter 8.5; testbench timing and control.