verilogsystem-verilog

Use loop to access generated modules


I have the following example design:

module test_module();
  logic data;
  task set_data(input logic data_i);
    data = data_i;
  endtask
endmodule

module test();
  for (genvar i = 0; i < 2; i++) begin: module_gen
    test_module module_instance();
  end
endmodule

My question is, if I want to call set_data for all instances of test_module, is there a way to use a for loop of some sort to do the call?

Calling the tasks like this is tedious:

module_gen[0].module_instance.set_data(1'b0);
module_gen[1].module_instance.set_data(1'b0);

I would like to do something along the lines of:

for (int i = 0; i < 2; i++) begin
  module_gen[i].module_instance.set_data(1'b0);
end

I understand why this is not possible. But is there some workaround?

P.S: please keep in mind this is a toy example to explain the problem, yes, it's easy to write 2 lines instead of 1, but in real life example, I end up having way too many lines.


Solution

  • Since this is for a testbench, you can wrap the task in a class object, then create an array of objects. Now you can procedurally call the task in each object.

    module test_module();
      logic data;
      task set_data(input logic data_i);
        data = data_i;
        $display("%m data set to %b",data);
      endtask
    endmodule
    
    module test();
      interface class wrapper; // ideally put in a package
        pure virtual task set_data(input logic data_i);
      endclass
      wrapper list[2];
      for (genvar i = 0; i < 2; i++) begin: module_gen
        class concrete implements wrapper;
          virtual task set_data(input logic data_i);
            module_instance.set_data(data_i);
          endtask
        endclass
        concrete h = new;
        initial list[i] = h;
        test_module module_instance();
      end
      
      initial #10 foreach(list[i]) 
                  #20 list[i].set_data(1);
    endmodule