Verilog · Chapter 14.6.1 · Behavioural Modeling
For Loop in Verilog — The Synthesizable Count Loop
The for loop is the synthesizable workhorse of Verilog iteration, a count-controlled loop with an initialization, a condition, and an update. When its bound is static, meaning a constant or a parameter, it unrolls at elaboration into replicated parallel hardware. Each iteration becomes a copy of the body, and all of them exist at once. This makes it the compact way to describe bit-sliced and regular logic, such as a per-bit operation across a vector, a reduction across many inputs, or a small array of identical computations. This page drills the loop, covering its syntax, how it unrolls, the bit-sliced patterns it expresses, and the rule that its bound must be static. A loop whose limit is a runtime signal cannot be unrolled and will not synthesize. It is the loop you reach for in synthesizable RTL.
Foundation12 min readVerilogfor loopUnrollingBit-SlicedRTL Design
Chapter 14 · Section 14.6.1 · Behavioural Modeling
1. The Engineering Problem
The for loop is the one loop you write in synthesizable RTL, and using it correctly means holding the unrolling model and the static-bound rule:
A
forloop with a static bound unrolls into replicated parallel hardware; aforloop bounded by a runtime signal cannot unroll and will not synthesize.
This page drills the for loop and the bit-sliced patterns it builds.
2. Mental Model — Count, Then Unroll
3. Syntax and Unrolling
// bit-wise AND of two vectors — unrolls into WIDTH AND gates
always @(*)
for (i = 0; i < WIDTH; i = i + 1)
y[i] = a[i] & b[i];
// equivalent unrolled form (for WIDTH = 4):
// y[0] = a[0] & b[0];
// y[1] = a[1] & b[1];
// y[2] = a[2] & b[2];
// y[3] = a[3] & b[3];The loop describes WIDTH parallel AND operations; the synthesizer unrolls it into WIDTH AND gates. The index i parameterizes the slice. (A single assign y = a & b; does the same in dataflow, 10.4 — the loop generalizes to per-bit operations that aren't a single operator.)
4. Bit-Sliced and Accumulation Patterns
The common synthesizable for patterns:
// bit reversal — y is a reversed
always @(*)
for (i = 0; i < WIDTH; i = i + 1)
y[i] = a[WIDTH-1-i];
// count set bits (population count) — an adder tree, unrolled
always @(*) begin
count = 0;
for (i = 0; i < WIDTH; i = i + 1)
count = count + a[i]; // accumulate (blocking, combinational)
end
// per-element operation across a small array
always @(*)
for (i = 0; i < N; i = i + 1)
out[i] = in[i] + offset;Bit reversal, population count (an unrolled adder tree), and per-element array operations are all for loops with static bounds. Note the accumulation uses blocking = (combinational, 14.3) and a default (count = 0) before the loop. These unroll into parallel combinational hardware.
5. The Static-Bound Rule
A for loop's bound must be known at elaboration:
// SYNTHESIZABLE — static bound:
for (i = 0; i < WIDTH; i = i + 1) ... // WIDTH is a parameter
// NOT SYNTHESIZABLE — runtime bound:
for (i = 0; i < n; i = i + 1) ... // n is a runtime signal → can't unrollThe synthesizer must know how many copies to make, so the count must be a constant or parameter. A loop limited by a runtime signal (n) has an unknown iteration count at elaboration and cannot be unrolled — it does not synthesize. To do something a runtime-variable number of times, use a clocked state machine with a counter (over cycles), not an unrollable loop (in space).
6. Common Mistakes
- Runtime-bounded
for— can't unroll; not synthesizable; use a static bound (§5, DebugLab 1). - Thinking the loop runs over time — it unrolls into parallel hardware (§2).
- Non-blocking in a combinational loop accumulation — use blocking
=(14.3). - Missing default before an accumulation loop — initialize the accumulator (e.g.
count = 0) first (§4).
7. Debugging Lab
One for-loop debug post-mortem
8. Interview Q&A
9. Exercises
Exercise 1 — Unroll the loop
Write the unrolled form of for (i = 0; i < 4; i = i + 1) y[i] = a[i] ^ b[i];.
Exercise 2 — Static or runtime?
Which of these synthesize: (a) for (i = 0; i < WIDTH; ...) with WIDTH a parameter; (b) for (i = 0; i < cnt; ...) with cnt an input?
Exercise 3 — Fix the bound
Rewrite a for loop bounded by a runtime input m to be statically bounded with m gating each iteration.
10. Summary
The for loop is the synthesizable count loop:
- Unrolls at elaboration into replicated parallel hardware (one body copy per iteration).
- Static bound required — constant/
parameter; runtime-bounded loops don't synthesize. - Bit-sliced patterns — per-bit operations, bit reversal, population count, per-element array ops (blocking
=for combinational accumulation). - vs runtime iteration — use a clocked counter for over-time behaviour, not an unrolled loop.
The next sub-topic is the condition loop: Chapter 14.6.2 While Loop drills while — synthesizable only when statically bounded, otherwise a testbench construct.
Related Tutorials
- Loops — Chapter 14.6; the loop overview and unrolling concept.
- Reduction Operators — Chapter 10.5; the one-line alternative to a bit-wise loop.
- Generate Block — Chapter 14.7; structural replication (vs a procedural
for). - Blocking & Non-Blocking Assignments — Chapter 14.3; blocking
=in combinational loop bodies.