Best Way to Dynamically Index and Instantiate Submodules in SystemVerilog?

Hi,

I’ve been working on a parameterized module that can instantiate multiple optional submodules depending on the configuration. Each submodule writes a value to a specific position in an array and asserts an enable signal to indicate valid data.

I have an implementation that works, but it doesn’t feel like the most elegant or intended way of solving this problem. The approach assigns bus indices dynamically based on the active submodules and uses a generate block to instantiate them conditionally.

In the example below, I’ve included only the shared signals across submodules. In reality, each submodule has extra unique signals that aren’t shown for simplicity.

Is there a better or more standard way to approach this situation?

module example_top #(
    // Parameters for enabling/disabling submodules
    parameter logic USE_A = 1,  // Enable Submodule A
    parameter logic USE_B = 0,  // Enable Submodule B
    parameter logic USE_C = 1   // Enable Submodule C
);

    // Compute bus indices dynamically based on enabled submodules
    localparam int IDX_A = 0;
    localparam int IDX_B = IDX_A + USE_A;
    localparam int IDX_C = IDX_B + USE_B;

    // Define array sizes based on enabled submodules
    localparam int ENDPOINTS = USE_A + USE_B + USE_C;

    // Declare signals for interconnection
    logic [ENDPOINTS-1:0] rd_ack;
    logic [ENDPOINTS-1:0] wr_ack;
    logic [31:0] rd_data [ENDPOINTS-1:0];

    // Submodule instantiations
    generate
        if (USE_A) begin : gen_a
            submodule_a u_a (
                .rd_ack_o (rd_ack[IDX_A]),
                .wr_ack_o (wr_ack[IDX_A]),
                .rd_data_o(rd_data[IDX_A])
            );
        end

        if (USE_B) begin : gen_b
            submodule_b u_b (
                .rd_ack_o (rd_ack[IDX_B]),
                .wr_ack_o (wr_ack[IDX_B]),
                .rd_data_o(rd_data[IDX_B])
            );
        end

        if (USE_C) begin : gen_c
            submodule_c u_c (
                .rd_ack_o (rd_ack[IDX_C]),
                .wr_ack_o (wr_ack[IDX_C]),
                .rd_data_o(rd_data[IDX_C])
            );
        end
    endgenerate

endmodule

Thanks in advance! :blush:

This is probably the best approach of conditionally instantiating modules based on parameters.

And what about the indexing of rd_ack, wr_ack, and rd_data? Is this the best we can do to generate and assign array positions (indexes) to each submodule?

Without knowing how all these connections are routed, it is difficult to suggest anything.