I am using the Verilog language and Zedboard as a target board.
As far as I know, the for
loop can be synthesized, and the synthesis tool translates the for
loop as a sequence of duplicated instructions like the loop unrolling.
For example,
for ( i = 0; i < 4; i=i+1) begin
mem[i] = i;
end
will be translated to
mem[0] = 0;
mem[1] = 1;
mem[2] = 2;
mem[3] = 3;
Therefore, as far as I know, the for
loop can be used if the resource is available to infer the multiple but same purposed gates.
However, it seems that the generate
in Verilog can be used to not only imply the multiple instances, but also the multiple instructions same as the for
loop.
I understand the generate
can only imply the multiple instances of the module and the for
loop cannot be used for that purpose.
Then what is the difference between the generate
+ for
loop and just for
loop? I think both work like the loop unrolling though. Is there any noticeable difference? If there is no difference, which one is preferable coding style to induce loop-unrolling?
-
1\$\begingroup\$ Just for clarity, it's: I imply, you infer. e.g. you imply a RAM in Verilog/VHDL, the synthesis software infers that RAM from your Verilog/VHDL. Very common mistake, worth learning. \$\endgroup\$TonyM– TonyM2018年01月15日 07:31:01 +00:00Commented Jan 15, 2018 at 7:31
1 Answer 1
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.
-
\$\begingroup\$ another way to think of generate is as a sort of pre-processor, your verilog compiler 'executes' things in generate blocks at the point where it's instantiating the block containing the generates - they don't happen at run time (unlike procedural loops) \$\endgroup\$Taniwha– Taniwha2018年01月15日 10:15:24 +00:00Commented Jan 15, 2018 at 10:15
-
\$\begingroup\$ @Taniwha procedural loops don't execute at run time either. They are unrolled by the compiler. It all boils down to hardware in the end. Also don't confuse the preprocessor with generate statements, they are not the same concept - Verilog has a preprocessor including if-else type statements. \$\endgroup\$Tom Carpenter– Tom Carpenter2018年01月15日 10:19:10 +00:00Commented Jan 15, 2018 at 10:19
-
\$\begingroup\$ @TomCarpenter I appreciate a great answer. I could understand all your points except the generate for loop. It seems that begin: something should be added right before the for loop, but cannot understand how does it work in instantiating modules. Is the loopName a variable or just string? And how they can be indexed by [1] to [4]. \$\endgroup\$ruach– ruach2018年01月16日 14:55:21 +00:00Commented Jan 16, 2018 at 14:55
-
\$\begingroup\$ @JaeHyukLee
loopName
is just text, like an instance name or a signal name. It can be anything you want. \$\endgroup\$Tom Carpenter– Tom Carpenter2018年01月16日 16:03:54 +00:00Commented Jan 16, 2018 at 16:03 -
\$\begingroup\$ @TomCarpenter - it depends on the compiler - if you're compiling gates yes they get unrolled, if you're compiling code for simulation more likely not (disclaimer, I've written a Verilog compiler) \$\endgroup\$Taniwha– Taniwha2018年01月30日 09:11:33 +00:00Commented Jan 30, 2018 at 9:11