4
\$\begingroup\$

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 works 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?

\$\endgroup\$
  • 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 Jan 15 '18 at 7:31
5
\$\begingroup\$

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.

\$\endgroup\$
  • \$\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 Jan 15 '18 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 Jan 15 '18 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\$ – JaeHyuk Lee Jan 16 '18 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 Jan 16 '18 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 Jan 30 '18 at 9:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.