Multiple generates using the same if condition does not evaluate right

I have run into an issue when I use multiple generate blocks with the same condition to pick a desired configuration. I am not sure if I am violating anything in the standard but I noticed that things work as desired if I combine everything to a single generate block. Consider the snippet of code below. Here bus is not recognized as a bus and the simulator complains of mismatch in port size.

module test ();

defparam test_tb.DUT_TOP= "PC";

test_tb test_tb();

initial
  force test_tb.dutsa.bus = 16'hdead;


endmodule


module test_tb #(parameter DUT_TOP = "") ();

generate 

 if (DUT_TOP == "PC")
   begin:duts
    logic [15:0] bus;
   end:duts

endgenerate

generate

if (DUT_TOP == "PC")
   begin:dutsa
     dut dut (.bus (bus));
   end:dutsa

endgenerate

endmodule

module dut(input [15:0] bus);

initial
  #5 $display ("bus is %h\n", bus);
endmodule

However, if I rewrite the code to a single generate it works as desired in the snippet below. Since I am dealing with a lot of declarations I was hoping to improve readability by having multiple generates - any reason why this is an issue?.

The following works:

module test2 ();

defparam test_tb.DUT_TOP= "PC";

test_tb test_tb();

initial
  force test_tb.duts.bus = 16'hdead;


endmodule


module test_tb #(parameter DUT_TOP = "") ();

generate 
 if (DUT_TOP == "PC")
   begin:duts
    logic [15:0] bus;

     dut dut (.bus (bus));

   end:duts

endgenerate
endmodule

module dut(input [15:0] bus);

initial
  #5 $display ("bus is %h\n", bus);
endmodule

In reply to noel:

You have to remember that generate blocks creates scopes and they have to be included in the paths when you trying to reference things from outside the block.

module test (); 
  test_tb #(.DUT_TOP("PC")) test_tb(); // don't use defparam
  initial
    force test_tb.dutsa.dut.bus = 16'hdead; // include the instance name 
endmodule
 
module test_tb #(parameter DUT_TOP = "") ();
  generate 
    if (DUT_TOP == "PC")
      begin:duts
        logic [15:0] bus;
      end:duts
  endgenerate
  generate
    if (DUT_TOP == "PC")
      begin:dutsa
        dut dut (.bus (duts.bus)); // bus is declared inside duts
      end:dutsa
  endgenerate
endmodule
 
module dut(input [15:0] bus);
  initial
    #5 $display ("bus is %h\n", bus);
endmodule

In reply to noel:

Thanks Dave. I didn’t realize that the bus has to be referenced using the scope too - makes sense.