首页 > 解决方案 > Is it possible to conditionally generate a for loop in System Verilog?

问题描述

Currently when I try to conditionally generate a for loop I get a compile error stating that I "Cannot nest generate regions".

Example of what I'm trying to do:

generate 
   if (x == 0) begin
      for (genvar i = 0; i < 16; i++) begin
          *some code here*
      end
   end
   else begin
      for (genvar k = 0; k < 16; k++) begin
          *some code here*
   end
endgenerate

Edit: Thank you all for the responses and help, but I've discovered the problem. Thank you Greg for reminding me about not being able to use generate within another generate.

Here's the Minimal Reproducible example that was causing me problems.

module test ();
  parameter x = 1;
  parameter y = 1;
  if (y == 1) begin
    generate 
     if (x == 1) begin
        for (genvar i = 0; i < 16; i++) begin
            test_inner test_inner1();
        end
     end
     else begin
        for (genvar k = 0; k < 16; k++) begin
            test_inner test_inner2();
        end
     end
    endgenerate
  end

endmodule

As you can see I had a conditional statement nested within another conditional statement. Because I didn't use the generate keyword in the outer conditional I didn't realize that it counted as a generate within another generate.

To solve the problem I moved the generate to the outer conditional, as such:

module test ();
  parameter x = 1;
  parameter y = 1;
  generate 
  if (y == 1) begin
     if (x == 1) begin
        for (genvar i = 0; i < 16; i++) begin
            test_inner test_inner1();
        end
     end
     else begin
        for (genvar k = 0; k < 16; k++) begin
            test_inner test_inner2();
        end
     end
  end
  endgenerate

endmodule

标签: verilogsystem-verilog

解决方案


keyword generate is optional in system verilog. If used, its starts a new generate block. Such generate blocks cannot be nested.

However, if you use generate if or for statements without the generate keyword, the compiler will take care of correct generate block boundaries for you.

In your case #1 you are missing the end keyword, it cannot be compiled.

In your case #2 you use if (y == 1) begin which starts a generate block. Then you use the keyword generate inside the already started block. It makes them nested.

Case #3 is correct use of the generate block.

You do not have case #4, but if you just get rid or both generate and endgenerate, it should work the same way as #3.

It always a good idea to name your generated blocks in order to control generated instance names. Like this:

module test ();
  parameter x = 1;
  parameter y = 1;
  if (y == 1) begin: y1
     if (x == 1) begin: x1
        for (genvar i = 0; i < 16; i++) begin: x1_loop
            test_inner test_inner1();
        end
     end
     else begin
        for (genvar k = 0; k < 16; k++) begin: x2_loop
            test_inner test_inner2();
        end
     end
  end 
endmodule

推荐阅读