SystemVerilog array of interfaces with unique parameters

149 Views Asked by At

I have a module (lets call it "mem") that has array of interfaces as a port, parameter NB_ITFS that declares the number of interfaces and a data WIDTH parameter.

module mem
    #(NB_ITFS=2)
    (itf itfa [NB_ITFS-1:0]);
    logic [31:0] data [NB_ITFS-1:0];
    always_comb
    begin
        data[0] = {4{itfa[0].data}};
        data[1] = {2{itfa[1].data}};
        data[2] = itfa[2].data;
    end
endmodule

Interface looks like this:

interface itf #(WIDTH = 8)();
    logic [WIDTH-1:0] data;
endinterface

How can I create an array of interfaces where every interface has unique parameters? How can I pass them to "mem" module?

Example:

module MyModule #(NB_ITFS=2) ();
    for (genvar i = 0; i<NB_ITFS; i++) begin : ITFA_GEN
        case (i)
            0: itf #(8) itf_if();
            1: itf #(16) itf_if();
            default: itf #(32) itf_if();
        endcase
    end

    mem #(.NB_ITFS(NB_ITFS)) my_mem (.itfa(itf_if));
endmodule


I've tried to connect everything like in example, but it doesn't compile or synthesize.

3

There are 3 best solutions below

1
Parth Pandya On BEST ANSWER
// Code your testbench here
// or browse Examples
interface itf #(WIDTH = 8)();
    logic [WIDTH-1:0] data;
endinterface

module mem
    #(NB_ITFS=2)
    (itf itfa [NB_ITFS-1:0]);
    logic [31:0] data [NB_ITFS-1:0];
    always_comb
    begin
        data[0] = {4{itfa[0].data}};
        data[1] = {2{itfa[1].data}};
        data[2] = itfa[2].data;
    end
endmodule

module MyModule #(NB_ITFS=3) ();
    itf itf_p [NB_ITFS-1:0](); 
    defparam itf_p[0].WIDTH=8;
    defparam itf_p[1].WIDTH=16; 
    defparam itf_p[2].WIDTH=32;
      
     
   mem #(.NB_ITFS(NB_ITFS)) my_mem (.itfa(itf_p));
endmodule

Above code fix your issue. I tried on all simulator on edaplayground. it is only not supported for VCS.

1
Serge On

As a suggestion, use an array of parameters:

module MyModule #(NB_ITFS=2) ();
  localparam int iparam[] = '{8,16};
  
  for (genvar i = 0; i<NB_ITFS; i++) begin : ITFA_GEN
    itf #(iparam[i]) itf_if();        
  end
endmodule

You can declare it in the module or pass as a parameter to the module. Otherwise, you can continue using your case statement. However, it is more difficult to maintain.

0
Serge On

I'll try to create another answer here. Unfortunately, there is no way in verilog to do what you want. Every array element in interface array must have the same parameterization. It is a feature of arrays. The code you provided does not create any interface array whatsoever. Instead it creates multiple separate instances of interfaces.

So, there are only two ways to handle your situation:

  1. list all interfaces one by one on the port list: module mem(itf a, itf b, itf c) and deal with this non-flexible situation
  2. design your module mem in such a way that it can handle every interface separately. Here is an modified example of yours:
module mem
  #(WIDTH = 32)
  (itf itfa, output logic [31:0] data);
    always_comb
    begin
      if (WIDTH == 32)
        data = itfa.data;
      else
        data = {32/WIDTH{itfa.data}};
    end
endmodule

interface itf #(WIDTH = 8)();
    logic [WIDTH-1:0] data;
endinterface

module MyModule #(NB_ITFS=2) ();
  localparam int iparam[] = '{8,16,32};
  logic [31:0] data [NB_ITFS+1];
 
  
  for (genvar i = 0; i<=NB_ITFS; i++) begin : ITFA_GEN
    itf #(.WIDTH(iparam[i])) itf_if();
    mem #(.WIDTH(iparam[i])) mem(itf_if, data[i]);
  end
endmodule