2
\$\begingroup\$

I'm curious as to why an array of interfaces can't be indexed into unless the index is constant. Specifically I'm curious as to the case where a for loop is used, because a for loop elaborates into an expanded piece of code, i.e. the index is in fact constant.

I'm presuming it just the order in the compile/build process that things get elaborated that causes this.

Example:

module some_module(
  my_intf.modport intf,
  input logic clk
);

    integer index = 0;

    always@(posedge clk) begin

       .....

        for (index = 0; index < 4; index = index + 1) begin
               if(intf[index].net) begin
                   //logic
               end
        end

        .....

    end //always
endmodule //some_module

Should be equivalent to:

module some_module(
  my_intf.modport intf,
  input logic clk
);

    always@(posedge clk) begin

       .....
           if(intf[0].net) begin
                   //logic
           end
           if(intf[1].net) begin
                   //logic
           end
           if(intf[2].net) begin
                   //logic
           end
           if(intf[3].net) begin
                   //logic
           end

        .....

    end //always
endmodule //some_module

For context: I'm using Vivado as my toolchain and receive a Vivado simulator error of:

ERROR: [VRFC 10-2951] "index" is not constant

Manually unpacking the for loop works, as expected. (Which is what leads me to believe that the for loop is not unpacked until sometime later in the compile/build process). When the for loop is used, I get a Vivado simulator error,

\$\endgroup\$
1
  • \$\begingroup\$ I can't post full code for confidentiality reasons, but its effectively identical as to what is seen above. Manually unpacking the for loop works, as expected. (Which is what leads me to believe that the for loop is not unpacked until sometime later in the compile/build process). When the for loop is used I get a Vivado simulator error of "ERROR: [VRFC 10-2951] "index" is not a constant". \$\endgroup\$
    – avor
    Feb 13 at 20:05

2 Answers 2

2
\$\begingroup\$

The reason is because the LRM does not allow it; it's not a true array.

True arrays are groups of variables with identical data types. An individual index selection of an array is guaranteed to have the same data type regardless of which index value is being selected.

Module and interface instances are namespaces that get elaborated/flattened as part of the compilation process. The index intf[0] etc. becomes part of the hierarchical path name as if you had manually entered intf_0. Parameterization, bind. and port collapsing can have different effects on each instance so that they are no longer identical. Although there are a number of cases where it would not make a difference, the LRM has strict rules about indexing into instances using constants.

\$\endgroup\$
0
\$\begingroup\$

You can use a generate construct to access indexes of an array of interfaces. Here is a minimal example that compiles without errors with multiple simulators on EDA playground:

interface my_intf;
    logic net;
endinterface

module some_module(
  my_intf intf [4],
  input logic clk
);

    for (genvar index = 0; index < 4; index = index + 1) begin
        always @(posedge clk) begin
            if (intf[index].net) begin
                //logic
            end
        end
    end
endmodule

Refer to IEEE Std 1800-2017, section 27. Generate constructs

\$\endgroup\$
1
  • \$\begingroup\$ If generate works, then you could also unpack [part of] the interface into logic arrays using a for loop over assign statements, and then index the arrays normally \$\endgroup\$ yesterday

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.