Undeclared Identifiers in Conditional Generate Blocks

Verilog compilers seem to have inconsistent behavior when compiling different types of code in conditional generate blocks.

Here is an example:

1: module bar(input x, output y);
2: assign y = x;
3: endmodule
4:
5: module foo;
6: parameter BLAH = 2;
7: reg [BLAH - 1:0] xx;
8: reg y2;
9: reg y3;
10: if ( BLAH > 2 ) bar(x2, y2); // This compiles even though x2 does not exist
11: if ( BLAH > 3 ) assign y3 = x3; // Compile error: Undeclared identifier (all simulators)
12: if ( BLAH > 3 ) assign y3 = xx[3]; // This compiles even though xx[3] does not exist
13: if ( BLAH > 3 ) always @( posedge xx[0] ) y3 <= x3; // Compile error: Undeclared identifier (all simulators)
14: initial begin
15: $display(“Hello!”);
16: end
17: endmodule

Why do lines 11 and 13 cause compile errors but lines 10 and 12 compile with no errors? All four conditional generate blocks should be ignored at elaboration time because of the parameter value. It looks like there is no way around this except for using ifdef compiler directives.

  • Line 10 compiles because of implicit wire declaration rules. See `default_nettype none
  • Line 12 compiles because Verilog does not require array indexes to be in range. You might get a warning.
  • Lines 11 and 13 are errors because the code inside a generate block must always be legal syntax whether the block is used or not. A generate block controls the instantiation of statements during elaboration of the design. The compiler still needs create the representation of the statements from legal code.

You would need to show how this code would become legal if BLAH was overriden to know if there was another alternative to `ifdef.

I forgot about the reasons for lines 10 and 12. Thanks. Now it makes sense.

Sorry about my example. It is incomplete. The real code that was failing was more like the following:

if ( BLAH > 2 ) begin
assign y = dut.foo2.x;
end

And “dut” code was generated using some kind of VPP tool so that the number of foo instances were dependent on the same source variable as the BLAH parameter. Besides the `ifdef approach, I could use VPP to also generate the code with the DUT XMR’s but I’m not a big fan of VPP.

I wonder if/how it would work if “dut” uses generate to instantiate the foo instances instead of using VPP.

In reply to dplumb:

Yes, it seems that both the testbench and the DUT need to use either VPP or generate, but you can’t mix the two code generation schemes and have design references between them.

In reply to dave_59:

Thanks for your responses, dave_59.