Search code examples
verilogsystem-verilog

How to call function of module instances made from generate block?


I have module instances made in a generate block and would like to call a function defined in the module similar to the code below:

module parent (...);
    ...
    genvar i;
    generate
      for (i = 0; i < N; ++i) begin : module_inst
          MyModule my_module(...);
      end
    endgenerate
    
    always@(...) begin
        for(int i = 0; i < N; ++i)
            module_inst[i].function();
        ...
    end

endmodule

However, I get this error:

function not declared under prefix module_inst/my_module

Is my syntax incorrect, or is this not possible to do?

I am able to call the function if I only create one instance:

module parent (...);
    ...
    MyModule my_module(...);
    
    always@(...) begin
        my_module.function();
        ...
    end
endmodule

The problem can be solved by manually creating each module instance and manually calling their respective functions, instead of using the generate and for loop statements. However, this would scale poorly and be hard to maintain. How can I go about doing this? I have found similar problems using tasks instead of functions where the suggested solution used classes; however, I'm unsure of its applicability to my problem as I need synthesizable code.


Solution

  • You need to use the module instance name (my_module) as well. This code compiles without errors with multiple simulators:

    module MyModule;
        function func1;
        endfunction
    endmodule
    
    module parent;
        parameter N=3;
        genvar i;
        generate
          for (i = 0; i < N; ++i) begin : module_inst
              MyModule my_module ();
          end
        endgenerate
        
        for (i = 0; i < N; ++i) begin
            always @* begin
                module_inst[i].my_module.func1();
            end
        end
    endmodule
    

    Note that the 2nd for loop is also a generate block. The generate/endgenerate keywords are optional.


    As a helpful debugging tip for generate constructs, I like to add this line inside the generated module (MyModule) to show the full hierarchical path:

    initial $display("%m");