Menu

Verilog Initial Block: Running Setup Code at Simulation Start

How initial blocks differ from always, why they only exist in simulation, and the common patterns - stimulus, waveform setup, log headers - they're used for.

This page includes runnable editors - edit, run, and see output instantly.

A One-Shot Procedural Block

initial begin ... end is always's sibling. The difference: initial runs exactly once, starting at time 0, and then terminates. There's no sensitivity list and no looping.

It exists for one reason: testbench setup. Setting initial values, kicking off stimulus, opening log files, calling $finish after a fixed simulation time - all the things you want to happen once at the start of a run, in a known order.

Step through what the simulator does:

  1. Time advances to 0.
  2. The initial block starts. First $display prints.
  3. data is set to 8'hA5.
  4. #10 advances simulated time by 10 units.
  5. Second $display prints.
  6. $finish ends the simulation.

The block ran once. There's no second pass.

The Canonical Testbench Skeleton

Almost every testbench you'll ever write uses an initial block like this:

Look at the shape - it's the testbench template you'll reach for every time:

  1. Open the VCD dump file ($dumpfile, $dumpvars) - covered in Dumpfile and VCD.
  2. Set initial values and hold reset for a few cycles.
  3. Drive stimulus through a series of changes interspersed with # delays.
  4. $finish to end the simulation cleanly.

That's it. Every Verilog test you'll see, including the ones in vendor examples, follows this pattern.

Multiple initial Blocks Are Parallel

Several initial blocks in the same module all start at time 0 simultaneously. They each run their own statements in their own time slice:

The simulator starts both blocks at time 0. Block B's first $display runs immediately. Block A waits 5 units before printing. Block B prints again at time 2. Block A's second print fires at time 15. Block B's $finish kills the simulation at time 22.

Splitting setup, clock generation, and stimulus into separate initial blocks is a common style - each block is short and does one thing.

Inline Initialization in Declarations

A common compact form: initialize a reg right at declaration time. Most simulators treat this the same as an initial:

reg clk = 0;
reg reset = 1;
reg [7:0] count = 0;

That's equivalent to:

reg clk;
reg reset;
reg [7:0] count;

initial begin
    clk = 0;
    reset = 1;
    count = 0;
end

The compact form is what you'll see in testbenches - it puts the initial value right next to the declaration where it's easy to scan.

initial Is Simulation-Only

Synthesis tools ignore initial blocks. Real hardware doesn't have a "moment zero" when setup code runs - it has power-on, reset signals, and the configuration that comes from those events. If you need a register to start in a known state in real hardware, drive it with a reset signal inside an always @(posedge clk):

always @(posedge clk) begin
    if (reset) state <= IDLE;
    else       state <= next_state;
end

That if (reset) branch is the synthesizable equivalent of initial state = IDLE. Reset is the answer to "how do I initialize a register on real hardware?"

Some FPGA flows do accept a restricted initial for register reset values (Xilinx tools, for instance), but that's a per-vendor extension. Don't rely on it in portable code.

Things You'll See Inside initial

A few common patterns beyond the standard testbench skeleton:

Time-Delayed Termination

initial begin
    #1000 $finish;   // safety net: kill the sim after 1000 time units
end

A separate initial whose only job is to put a hard upper bound on the simulation. Even if your main stimulus block deadlocks waiting for a signal that never comes, this block fires and ends the run.

Waveform Setup

initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, test);   // dump everything under the `test` scope
end

These two lines tell the simulator to write a VCD file with every signal in the test scope. Without them, you get no waveform.

Initial Memory Image

reg [7:0] memory [0:255];

initial begin
    $readmemh("image.hex", memory);
end

$readmemh loads a hex-formatted file into the array. Used in CPU testbenches to pre-load instruction memory. Simulation-only.

Common Mistakes

Using initial for synthesizable logic. It won't synthesize. Use reset signals instead.

Forgetting $finish. Without it the simulator runs until something else stops it (a default time limit, manual interrupt, etc.). For a quick test that's fine; for a regression script, always $finish.

Forgetting #delay between stimulus assignments. If you write a = 0; b = 1; with no delay, both happen at the same simulation time and the DUT might see them simultaneously rather than as separate events. Insert #1 or longer between distinct stimulus events.

Trying to drive a wire from initial. Same rule as always: only reg is a legal target.

What Comes Next

You've seen the two procedural-block flavors. The next doc covers the single most-confused topic in beginner Verilog: Blocking vs Non-blocking Assignment. Knowing when to use = and when to use <= is the difference between a working flip-flop and a race-condition mess.

Frequently Asked Questions

What is an initial block in Verilog?

initial begin ... end is a procedural block that runs exactly once at the start of simulation, at time 0. It's the standard place to set up testbench state: initialize signals, open log files, call $dumpfile/$dumpvars, drive stimulus, and finish the simulation with $finish. Multiple initial blocks can coexist in a module; they all start at time 0 in parallel.

What is the difference between initial and always in Verilog?

initial runs once at time 0 and then terminates. always re-runs forever - it has a sensitivity list and wakes up whenever the listed signals change. initial is used almost exclusively in testbenches. always is the workhorse of both testbenches and synthesizable RTL.

Is initial block synthesizable?

Not in plain Verilog. Synthesis tools ignore initial blocks because real hardware doesn't have a 'time zero' moment when setup code runs. Some FPGA toolchains accept a restricted form to set register reset values, but the general case is simulation-only. Keep initial blocks in testbenches; use reset signals to initialize synthesizable logic.

Can you have multiple initial blocks in a Verilog module?

Yes. Each initial block starts at time 0 and runs to completion independently. Splitting setup into multiple blocks is a common testbench pattern - one block for clock generation, one for stimulus, one for waveform dumping. They run concurrently from time 0; the simulator interleaves their statements as time advances.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED