Always and Initial block in Verilog
Introduction¶
In Verilog, two fundamental procedural constructs control how simulation and hardware behavior are described — the and blocks. While they look similar syntactically, they serve very different purposes in RTL design.
This article explains in detail the difference, syntax, use cases, and best practices of always and initial blocks in Verilog.
What Are Procedural Blocks?¶
Procedural blocks describe behavioral code — statements that execute in time order (unlike continuous assignments that model combinational logic directly).
There are two kinds:
alwaysblock → can execute repeatedly throughout simulation.initialblock → executes only once at the start of simulation.
Both blocks contain procedural statements such as if, case, for, and procedural assignments (= and <=).
The initial Block¶
 Purpose¶
The initial block is used for code that should run only once at the beginning of simulation. It is not synthesizable in most designs (with exceptions like FPGA initialization).
Syntax¶
initial begin
  // statements
end
Behavior¶
- Executes once at time 0.
 - Used for testbenches, initialization, or stimulus generation.
 - Can contain time delays (#), loops, and display statements.
 
Example: Testbench Initialization¶
module tb;
  reg clk, reset;
  initial begin
    clk = 0;
    reset = 1;
    #10 reset = 0;   // release reset after 10 time units
  end
  always #5 clk = ~clk; // clock generation
endmodule
In this example:
- The 
initialblock runs once to initialize signals. - The 
alwaysblock toggles the clock every 5 units. 
initial begin
  #10 data = 8'hFF;  // delay — simulation only
end
Delays (#) are not synthesizable.
Key Use Cases¶
- Testbench stimulus
 - Setting initial register values
 - Generating files or logs with 
$display,$fwrite, etc. 
The always Block¶
 Purpose¶
always blocks describe repetitive behavior — they keep executing whenever signals in the sensitivity list change or when triggered by clock edges. A sensitivity list is a list of signals or events that trigger the execution of a procedural block, such as an always block. The list controls when the statements inside the block are re-evaluated by the simulator. The sensitivity list is declared after the @ symbol, as in always @(sensitivity_list).
Syntax¶
always @(sensitivity_list) begin
  // procedural statements
end
For always blocks that model combinational logic, the sensitivity list must include all input signals to prevent a mismatch between simulation and synthesis.
always @(a, b, c)
  out = a & b | c;
A better alternative featuring wildcard/automatic (*) sensitivity list is mentioned below. It includes all the signals.
always @(*) 
  out = a & b | c;
A problematic sensitivity list
always @(a, b) 
  out = a & b | c;
It leaves out c which can cause unexpected synthesis.
Sensitivity List Types¶
- Combinational Logic → 
always @(*) - Sequential Logic → 
always @(posedge clk)or@(negedge clk) 
Example: Sequential Logic (Flip-Flop)¶
always @(posedge clk or posedge reset) begin
  if (reset)
    q <= 0;
  else
    q <= d;
end
This block executes on every rising edge of the clock or reset.
Example: Combinational Logic (Mux)¶
always @(*) begin
  if (sel)
    y = a;
  else
    y = b;
end
This executes whenever any input changes.
Key Use Cases¶
- Modeling combinational and sequential logic
 - Describing RTL behavior
 - Synthesizable hardware design
 
Difference Between always and initial¶
 | Feature | initial Block |  always Block |  
|---|---|---|
| Execution | Runs once at start of simulation | Runs continuously whenever triggered | 
| Sensitivity | Implicit (starts at time 0) | Explicit sensitivity list required | 
| Synthesizable | Generally no | Yes (with correct style) | 
| Common use | Testbenches, stimulus | RTL logic, clocks, registers | 
| Timing controls | Allowed (#5, wait) |  Allowed, but not in synth code | 
| Number of blocks | Usually one or few | Often many (per logic group) | 
| Typical location | Testbench files | RTL design modules | 
Example: initial + always Together in Testbench¶
 module tb_counter;
  reg clk, reset;
  wire [3:0] count;
  // DUT instance
  counter uut (.clk(clk), .reset(reset), .count(count));
  // Generate clock
  always #5 clk = ~clk;
  // Apply reset and monitor
  initial begin
    clk = 0;
    reset = 1;
    #10 reset = 0;
    #100 $finish;
  end
  // Display output values
  initial begin
    $monitor("Time=%0t Count=%0d", $time, count);
  end
endmodule
Here:
- The `` block generates a clock signal forever.
 - The `` block provides stimulus (reset, finish).
 
Multiple Procedural Blocks¶
You can have multiple initial and always blocks in one module. Each runs independently and concurrently — similar to multiple parallel processes.
initial clk = 0;
always #5 clk = ~clk;
initial begin
  #100 $finish;
end
All start at time 0 and execute in parallel.
Synthesizable vs Non-Synthesizable Context¶
| Construct | Simulation | Synthesizable | Typical Use | 
|---|---|---|---|
initial begin #10; end |  Yes | No | Testbench | 
always @(posedge clk) |  Yes | Yes | RTL logic | 
always @(*) |  Yes | Yes | Combinational logic | 
initial begin value = 0; end |  Yes | depends on FPGA | Register init | 
FPGA synthesis tools sometimes allow initializing registers using initial (e.g., Xilinx Vivado). ASIC tools usually do not.
Blocking vs Non-Blocking Assignments in These Blocks¶
- Inside combinational 
always @(*)→ use blocking (=). - Inside sequential 
always @(posedge clk)→ use non-blocking (<=). 
Example:
initial begin
  a = 0;
  b = 1;
  c <= 2; // fine, executes once
end
Common Mistakes¶
| Mistake | Description | Consequence | 
|---|---|---|
Using initial for synthesizable timing |  Non-synthesizable | Ignored by tools | 
Missing sensitivity list in always |  Incomplete simulation | Wrong behavior | 
Using # delay in RTL |  Not synthesizable | Hardware mismatch | 
Mixing = and <= incorrectly |  Race conditions | Unpredictable results | 
Summary¶
| Concept | initial |  always |  
|---|---|---|
| Executes | Once at time 0 | Repeats on trigger | 
| Used in | Testbench | Design logic | 
| Synthesizable | Usually no | Yes | 
| Typical purpose | Initialization, stimulus | Combinational / Sequential logic | 
| Delay allowed | Yes | No (for synth) | 
| Example | initial clk = 0; |  always @(posedge clk) |  
Key Takeaways¶
initialexecutes once;alwaysexecutes forever.- Only 
alwaysblocks can infer flip-flops or logic during synthesis. - Both blocks run concurrently in simulation.