Hardware behavior cannot be implemented without conditional statements and other ways to control the flow of logic. Verilog has a set of control flow blocks and mechanisms to achieve the same.
What You'll Learn
- How if-else-if makes a decision in procedural code
- How the forever, repeat, while and for loops repeat statements
- When to choose each loop type, with an example of each
- Common control block mistakes, and how to avoid them
if-else-if
This conditional statement is used to make a decision about whether certain statements should be executed or not. This is very similar to the if-else-if statements in C. If the expression evaluates to true, then the first statement will be executed. If the expression evaluates to false and if an else part exists, the else part will be executed.
// if statement without else part
if (expression)
[statement]
// if statment with an else part
if (expression)
[statement]
else
[statement]
// if else for multiple statements should be
// enclosed within "begin" and "end"
if (expression) begin
[multiple statements]
end else begin
[multiple statements]
end
// if-else-if statement
if (expression)
[statement]
else if (expression)
[statement]
else
[statement]
The code examples shown above are synthesizable and can be implemented in hardware. Always simulate your design before synthesis to verify correct functionality.
The else part of an if-else is optional and can cause a confusion if an else is omitted in a nested if sequence. To avoid this confusion, it's easier to always associate the else to the previous if that lacks an else. Another way is to enclose statements within a begin-end block. The last else part handles none-of-the-above or default case where none of the other conditions were satisfied.
Click here to read more about if-else-if
Loops provide a way of executing single or multiple statements within a block one or more number of times. There are four different types of looping statements in Verilog.
forever loop
This will continuously execute the statements within the block.
forever
[statement]
forever begin
[multiple statements]
end
Example
module my_design;
initial begin
forever begin
$display ("This will be printed forever, simulation can hang ...");
end
end
endmodule
ncsim> run
This will be printed forever, simulation can hang ...
This will be printed forever, simulation can hang ...
...
...
This will be printed forever, simulation can hang ...
This will be printed forever, simulation can hang ...
This will be printed forever, simulation can hang ...
This will be printed forever, simulation can hang ...
Result reached the maximum of 5000 lines. Killing process.
repeat loop
This will execute statements a fixed number of times. If the expression evaluates to an X or Z, then it will be treated as zero and will not be executed at all.
repeat ([num_of_times]) begin
[statements]
end
repeat ([num_of_times]) @ ([some_event]) begin
[statements]
end
Example
module my_design;
initial begin
repeat(4) begin
$display("This is a new iteration ...");
end
end
endmodule
ncsim> run This is a new iteration ... This is a new iteration ... This is a new iteration ... This is a new iteration ... ncsim: *W,RNQUIE: Simulation is complete.
while loop
This will execute statements as long as an expression is true and will exit once the condition becomes false. If the condition is false from the start, statements will not be executed at all.
while (expression) begin
[statements]
end
Example
module my_design;
integer i = 5;
initial begin
while (i > 0) begin
$display ("Iteration#%0d", i);
i = i - 1;
end
end
endmodule
ncsim> run Iteration#5 Iteration#4 Iteration#3 Iteration#2 Iteration#1 ncsim: *W,RNQUIE: Simulation is complete.
for loop
for ( initial_assignment; condition; increment_variable) begin
[statements]
end
This will control statements using a three-step process:
- Initialize a loop counter variable
- Evaluate the expression, usually involving the loop counter variable
- Increment loop counter variable so that at a later time the expression will become false and loop will exit.
Example
module my_design;
integer i = 5;
initial begin
for (i = 0; i < 5; i = i + 1) begin
$display ("Loop #%0d", i);
end
end
endmodule
ncsim> run Loop #0 Loop #1 Loop #2 Loop #3 Loop #4 ncsim: *W,RNQUIE: Simulation is complete.
Click here to read more about for loops.
Common Beginner Mistakes
Mistake #1: Latches from Incomplete If-Else Statements
In combinational always @(*) blocks, if you don't provide an else case for every if, Verilog assumes the signal should "hold its value." This forces the synthesis tool to create a physical latch, which can cause timing nightmares. Always use a default else or assign a default value at the top of the block.
Mistake #2: Using 'forever' or 'while' without a Time Delay
In simulation, forever and while loops execute in zero simulation time. If you write forever a = ~a; without a delay like #5, the simulator will enter an infinite loop at the current time step and hang. These blocks are primarily for testbenches, not synthesizable hardware.
Mistake #3: Treating 'for' Loops like Software Iterations
Beginners often think a for loop in Verilog happens over time (one iteration per clock cycle). In reality, the synthesizer "unrolls" the loop to create multiple copies of the hardware at the same time. If you put complex logic inside a loop with a large range, you will accidentally consume massive amounts of chip area.
Mistake #4: Logic Errors with 'repeat' in Synthesis
The repeat block is great for testbenches (e.g., repeat(10) @(posedge clk);), but most synthesis tools require the repetition count to be a constant. Trying to use repeat(variable_count) for hardware generation will usually result in a synthesis error because the tool cannot determine the fixed hardware structure at compile time.
Mistake #5: Procedural Block Confusion with 'if'
You cannot use if-else or for loops directly in the "module" level of your code. They must reside inside a procedural block like always or initial. Beginners often try to write if(rst) a = 0; outside of a block, leading to "syntax error near if" messages.
Best Practice: For complex combinational logic, prefer a case statement over long if-else if chains. case statements are often more readable and easier for synthesis tools to optimize into efficient multiplexer trees.
Practice Exercise
Challenge: Loop with a Running Total
Use a repeat loop in an initial block to print the first five multiples of 3, together with the running total of the values printed so far.
Hint
Keep two integer variables, one for the current multiple and one for the total, and update both inside the loop.
Solution
module tb;
integer n, total;
initial begin
n = 0;
total = 0;
repeat (5) begin
n = n + 3;
total = total + n;
$display("n=%0d total=%0d", n, total);
end
end
endmodule
The output is n=3 total=3, n=6 total=9, n=9 total=18, n=12 total=30 and n=15 total=45. A for loop with a counter from 1 to 5 would give the same result.
Summary
In this tutorial, you learned:
if-else-ifdecides which statements run; only the first true branch executesforevernever ends on its own,repeatruns a fixed number of times,whiletests its condition first andforadds an initial assignment and a step- A loop without a delay or event control runs in zero simulation time and can hang the simulation
- In synthesizable code, a loop is unrolled into parallel hardware and needs constant bounds
- An
ifwithout anelsein a combinational block creates a latch