Verilog Non-Synthesizable Constructs: What to Avoid
In Verilog, constructs like
initial blocks, wait statements, fork-join parallel blocks, and file I/O operations are not synthesizable because they describe simulation-only behavior. Also, delays using # and system tasks like $display cannot be converted into hardware.Syntax
Here are some common non-synthesizable Verilog constructs and their syntax:
initialblock: runs once at simulation startwaitstatement: pauses until a condition is truefork-join: runs parallel threads- Delay control:
#10delays execution by 10 time units - System tasks:
$display,$finish, etc.
verilog
initial begin $display("This runs once at simulation start"); end always @(posedge clk) begin wait (reset == 0); // wait until reset is deasserted end fork // parallel threads thread1(); thread2(); join always @(posedge clk) begin #5 data <= data + 1; // delay not synthesizable end
Example
This example shows an initial block and a delay, both not synthesizable. The always block with posedge clk is synthesizable.
verilog
module example(input clk, input reset, output reg [3:0] count); initial begin $display("Simulation start"); end always @(posedge clk) begin if (!reset) begin #2 count <= count + 1; // delay not synthesizable end end endmodule
Output
Simulation start
Common Pitfalls
Using non-synthesizable constructs in your design can cause synthesis tools to fail or ignore parts of your code. For example, initial blocks are often used for testbench setup but should not be used for hardware logic. Delays (#) are for simulation timing and have no hardware equivalent.
Wrong way (non-synthesizable):
initial begin led = 1; #10 led = 0; end
Right way (synthesizable):
always @(posedge clk or posedge reset) begin if (reset) led <= 1; else led <= 0; end
Quick Reference
| Construct | Synthesizable? | Reason |
|---|---|---|
| initial block | No | Runs once at simulation start, no hardware equivalent |
| wait statement | No | Pauses simulation, no hardware equivalent |
| fork-join | No | Parallel threads for simulation only |
| Delay (#) | No | Simulation timing control, no hardware delay |
| System tasks ($display, $finish) | No | Simulation output and control |
| always block | Yes | Describes hardware behavior |
| assign statement | Yes | Continuous hardware assignment |
Key Takeaways
Avoid using
initial blocks and delays in synthesizable Verilog code.Simulation-only constructs like
wait and fork-join cannot be converted to hardware.Use
always blocks and assign statements for hardware logic.System tasks such as
$display are for simulation and not synthesizable.Check synthesis tool warnings to catch non-synthesizable code early.