Skip to content

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

timing-controls.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   // 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 clocked always blocks — synthesizable.
  • wait introduces 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 flow
When does the statement run?# delayafter N time units · sim@ eventon a signal event · synthesizablewait conditionuntil condition true · sim
Three timing controls decide when a procedural statement runs: a delay (#) waits a fixed time, an event (@) waits for a signal event, and wait blocks until a condition is true. Event control (@(posedge clk)) is synthesizable — it triggers clocked logic; delays and wait are simulation/testbench tools.

4. Synthesizable vs Simulation-Only

The practical division, central to using timing controls correctly:

ControlFormSynthesizable?Use
Event (edge)@(posedge clk)yesclocked always blocks
Event (level)@(*) / @(a, b)yescombinational sensitivity
Delay#10notestbench pacing, sim timing
Levelwait(c)notestbench synchronization
  • Event control is the synthesizable timing mechanism@(posedge clk) triggers flip-flops, @(*) triggers combinational logic (Chapter 14.1).
  • Delays and wait are simulation-only — synthesis ignores # delays (real timing comes from the library, Chapter 11.2) and has no hardware for wait. 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-topicCovers
14.4.1Delay Based Timing# delays — simple, intra-assignment; pacing and modeling (sim)
14.4.2Event Based Timing@ event control — edges, level, named events; the synthesizable trigger
14.4.3Level Sensitive Timingwait — blocking on a condition (sim)
14.4.4Advanced Timing Techniquesintra-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).