Synthesizable vs Non-Synthesizable Constructs in Verilog
📖 Scenario: You are designing a simple digital circuit using Verilog. You need to understand which parts of your code can be turned into hardware (synthesizable) and which parts are only for simulation or testing (non-synthesizable).
🎯 Goal: Build a Verilog module that includes both synthesizable and non-synthesizable constructs. You will create a counter that increments on a clock and a testbench-like block that prints messages for simulation only.
📋 What You'll Learn
Create a synthesizable 4-bit counter using an always block triggered by a clock
Add a non-synthesizable initial block that prints a message at simulation start
Use a parameter to set the maximum count value
Display the counter value during simulation using $display
Understand the difference between synthesizable and non-synthesizable code
💡 Why This Matters
🌍 Real World
Digital designers use synthesizable Verilog to create hardware circuits like counters, registers, and processors. Non-synthesizable code helps test and verify designs before building hardware.
💼 Career
Understanding which Verilog constructs are synthesizable is essential for FPGA and ASIC engineers to write correct hardware designs and avoid simulation-only code in their final products.
Progress0 / 4 steps
1
Create a 4-bit counter module
Create a Verilog module called counter with inputs clk and reset, and a 4-bit output count. Inside, declare count as a reg and initialize it to 0.
Verilog
Hint
Use initial count = 0; to set the starting value of the counter.
2
Add a parameter for maximum count
Add a parameter called MAX_COUNT with value 10 inside the counter module.
Verilog
Hint
Use parameter MAX_COUNT = 10; to define a constant maximum count value.
3
Implement synthesizable counting logic
Add an always @(posedge clk or posedge reset) block inside the counter module. Inside it, reset count to 0 if reset is high. Otherwise, increment count by 1 until it reaches MAX_COUNT, then reset to 0.
Verilog
Hint
Use non-blocking assignments <= inside the always block for synthesizable logic.
4
Add non-synthesizable initial block to display count
Add an initial block outside the always block that uses $display to print "Simulation started" once. Then add an always @(posedge clk) block that uses $display to print the current count value each clock cycle. This code is for simulation only and not synthesizable.
Verilog
Hint
Use initial and always @(posedge clk) blocks with $display for simulation messages.
Practice
(1/5)
1. Which of the following Verilog constructs is non-synthesizable and used only for simulation?
easy
A. Module instantiations
B. Initial blocks (initial)
C. Continuous assignments (assign)
D. Always blocks (always)
Solution
Step 1: Understand the role of initial blocks
initial blocks run once at simulation start and are not synthesizable into hardware.
Step 2: Compare with synthesizable constructs
always blocks, assign statements, and module instantiations describe hardware and are synthesizable.
Final Answer:
Initial blocks (initial) -> Option B
Quick Check:
initial = Non-synthesizable [OK]
Hint: Remember: initial blocks only simulate, never synthesize [OK]
Common Mistakes:
Confusing always with initial
Thinking assign is non-synthesizable
Assuming module instantiations are simulation-only
2. Which of the following is the correct syntax for a synthesizable always block sensitive to the positive edge of clock clk?
easy
A. always @(clk or reset) begin ... end
B. always @(clk) begin ... end
C. always @(negedge clk or posedge reset) begin ... end
D. always @(posedge clk) begin ... end
Solution
Step 1: Identify correct edge sensitivity
Synthesizable clocked logic uses posedge clk or negedge clk to trigger on clock edges.
Step 2: Check syntax correctness
always @(posedge clk) is correct; always @(clk) triggers on any change, which is not typical for clocked logic.
Final Answer:
always @(posedge clk) begin ... end -> Option D
Quick Check:
Use posedge clk for clock edge sensitivity [OK]
Hint: Use posedge or negedge for clock edges [OK]
Common Mistakes:
Using level sensitivity instead of edge sensitivity
Mixing clock and reset signals incorrectly
Omitting begin and end for multiple statements
3. What will be the output of the following Verilog code snippet during simulation?
reg [3:0] count;
initial begin
count = 0;
#5 count = 4'b1010;
end
always @(posedge clk) begin
count <= count + 1;
end
Assuming clk toggles every 1 time unit starting at 0.
medium
A. Count stays 0 until time 5, then becomes 10 and increments every clock cycle
B. Count increments every clock cycle starting from 0, then changes to 10 at time 5
C. Count increments every clock cycle starting from 0, ignoring the initial block
D. Count remains 0 throughout simulation
Solution
Step 1: Analyze initial block effect
The initial block sets count to 0 at time 0, then to 10 at time 5 (delay #5).
Step 2: Analyze always block behavior
The always block increments count on every positive clock edge, but the non-blocking assignment means the update happens after the clock edge, so the delayed assignment at time 5 overrides the count value at that time.
Final Answer:
Count stays 0 until time 5, then becomes 10 and increments every clock cycle -> Option A
Quick Check:
initial #delay executes after clock edges [OK]
Hint: Delayed initial affects count after clock increments [OK]
Common Mistakes:
Ignoring the initial block's delayed assignment
Assuming count increments from 10 immediately
Confusing blocking and non-blocking assignments
4. Identify the error in the following Verilog code snippet that prevents synthesis:
always @(posedge clk) begin
integer i;
for (i = 0; i < 4; i = i + 1) begin
data[i] = i;
end
end
medium
A. Using an integer variable inside an always block for synthesis
B. Declaring a loop variable inside the always block
C. Using blocking assignment (=) instead of non-blocking (<=) inside always block
D. Using a for loop inside an always block is not synthesizable
Solution
Step 1: Check variable declarations and loop usage
Declaring integer i inside the always block is allowed for synthesis as loop variable.
Step 2: Identify assignment type issue
Using blocking assignment = inside clocked always block causes unintended behavior; non-blocking <= is required for registers.
Final Answer:
Using blocking assignment (=) instead of non-blocking (<=) inside always block -> Option C
Quick Check:
Use non-blocking (<=) in clocked always blocks [OK]
Hint: Use <= for registers inside clocked always blocks [OK]
Common Mistakes:
Thinking loop variables cannot be declared inside always blocks
Believing for loops are non-synthesizable
Ignoring difference between blocking and non-blocking assignments
5. You want to create a synthesizable Verilog module that counts the number of times an input signal sig is high during clock cycles, but also print the count value for debugging during simulation. Which approach correctly separates synthesizable and non-synthesizable constructs?
hard
A. Use an always @(posedge clk) block to increment count and an initial block with $display to print count
B. Use an always @(posedge clk) block to increment count and a separate always block with $display to print count
C. Use a continuous assignment to increment count and initial block to print count
D. Use a task to increment count and a function to print count
Solution
Step 1: Identify synthesizable counting logic
Counting on clock edges must be in an always @(posedge clk) block using non-blocking assignments.
Step 2: Identify non-synthesizable debugging code
Printing with $display is simulation-only and must be placed in an initial or separate simulation-only block.
Final Answer:
Use an always @(posedge clk) block to increment count and an initial block with $display to print count -> Option A
Quick Check:
Separate hardware logic and simulation prints [OK]
Hint: Put printing in initial, counting in clocked always [OK]
Common Mistakes:
Trying to print inside synthesizable always block
Using continuous assignment for counting
Confusing tasks/functions for simulation prints
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.