Verilog for-loops are perfectly synthesizable under certain conditions:
- You can use any procedural statement within a loop (e.g. if-else).
- The number of loops must be predetermined.
- The limiting expression must be a comparison between the loop variable and either a constant or a parameter.
- The step assignment must be incrementing the loop value by a constant amount.
- You can assign a different value to the same variable in each loops (e.g. calculating an index from the loop variable).
- For synthesis purposes, the loop is evaluated in zero time – i.e. if you tried to make a counter, you would only ever see the final value.
Those same rules apply whether you use a for-loop in a procedural block, or in a generate block.
When done in a procedural block, initial
and always
, you can use a for loop to change elements in an array (exactly as your example), or you could change the same value multiple times, for example:
for (idx = 0; idx < 4; idx=idx+1) begin
a = a + b[idx];
c = c + 2; //You can change more than one variable in a for loop
end
In that example, the resulting hardware will be a chain of adders, summing the values from four array indices.
The key thing is that you can't create new variables or modules in a procedural for loop. This rule applies to procedural blocks in general, not just for loops (i.e. you can't declare a variable in a procedural block).
Generate blocks on the other hand do allow the creation of variables and the instantiation of modules. That means in a generate block, you can use a generate for loop to infer modules. That's pretty much the only difference.
For generate for loops, you must use a genvar
as the loop variable (i.e. the value you use to count through each loop). You must also give the for loop a name:
for (loopVal = 0; loopVal < 4; loopVal = loopVal + 1) begin : loopName
This name is prepended to any piece of hardware you instantiate in the loop. So if you create an instance called bob
, the above loop would create instances:
loopName[0]|bob
loopName[1]|bob
loopName[2]|bob
loopName[3]|bob
This results in multiple instances with unique names.
Both generate and procedural for loops will perform loop unrolling as you say. The difference is simply how you can use them. Procedural can be used in procedural blocks (e.g. for initialising a memory). Generate can only be used in generate blocks.
They are both useful and preferred. One can't replace the other.