2

I'm trying to pass an interface to a module which is an array of interfaces.

interface front_port #(parameter DATA_WIDTH = 4);
        logic   [DATA_WIDTH - 1 : 0]   data;
        logic                          acknowledge;

        modport f_interface(input data, output acknowledge);
endinterface

interface front_interface #(parameter NO_OF_IN_PORTS = 3);
        front_port    front_ports[NO_OF_IN_PORTS]();
endinterface

module A #(parameter NO_OF_IN_PORTS = 3)
(
    interface front_port;
);

module testbench;
    font_interface #(.NO_OF_IN_PORTS(3))  my_front_interface();

    A #(.NO_OF_IN_PORTS(3)) (.front_port(my_front_interface));
endmodule

So, my question is, can the array elements of my_front_interface have different values of DATA_WIDTH. If so, how? In the code defined above all the array elements of my_front_interface have the default DATA_WIDTH of 4.

Thanks

R. Kukreja
  • 21
  • 1
  • 6
  • You are sure about using nested modules? While instantiating module `A`, the input argument is `my_front_interface` of type `front_interface`, but the instance `my_front_interface` is of type `front_interface`. The module declaration might be like `module A...(front_interface fr_if)`. – sharvil111 Apr 06 '16 at 07:28
  • Regarding variable `DATA_WIDTH`, rather than simply creating array of instances, you need a `generate` block for making multiple instances with varying data width parameter. Refer [this link](http://www.asic-world.com/verilog/verilog2k2.html) and [this question](http://stackoverflow.com/questions/17734329/system-verilog-parameters-in-generate-block) for `generate` block example. – sharvil111 Apr 06 '16 at 07:43
  • Ok. Thank you. If that's the case how do I assign the generated instances with varying data width parameter to front_interface? – R. Kukreja Apr 06 '16 at 08:32

2 Answers2

3

Following from my comments, there seems many compilation errors in the given code. Yet, I have tried to resolve them as per my understanding.

In order to create varying DATA_WIDTH instances, the interface front_interface must get information about DATA_WIDTH in various instances. So, adding an array of parameters to front_interface entity. The size of that array is determined by NO_OF_IN_PORTS parameter.

Further, you must use generate block for creating multiple instances of front_port. Each instance picks up an element from parameter array of front_interface entity.

I have created following code which overrides the default values of DATA_WIDTH and creates instances with unique data widths.

interface front_port #(parameter DATA_WIDTH = 4);
    logic   [DATA_WIDTH - 1 : 0]   data;
    logic                          acknowledge;

    modport f_interface(input data, output acknowledge);

  initial
    begin : DEBUG_DISPLAY
      $display("DATA_WIDTH for %m is %0d",DATA_WIDTH);
    end
endinterface

// Use array DATA_WIDTH here, for varying data widths.
interface front_interface #(parameter NO_OF_IN_PORTS = 3, int DATA_WIDTH[NO_OF_IN_PORTS] = '{1,2,3});
  genvar i;
  generate // generate block for multiple instances
    begin : MULTIPLE_INSTANCES
      for(i=0;i<NO_OF_IN_PORTS;i++)
        begin : UNIQUE_DATA_WIDTH
          // Pick up each element from array to create varying DATA_WIDTH instances
          front_port #(.DATA_WIDTH(DATA_WIDTH[i])) front_ports();
        end
     end
  endgenerate
endinterface

module A #(parameter NO_OF_IN_PORTS = 3)
          (front_interface fi_if);
endmodule

module testbench;

  // Override DATA_WIDTH here for different instances
  front_interface #(.NO_OF_IN_PORTS(3), .DATA_WIDTH('{4,5,6}))  my_front_interface();

  A #(.NO_OF_IN_PORTS(3)) a1(my_front_interface);

endmodule

Output:

DATA_WIDTH for testbench.my_front_interface.MULTIPLE_INSTANCES.UNIQUE_DATA_WIDTH[0].front_ports.DEBUG_DISPLAY is 4
DATA_WIDTH for testbench.my_front_interface.MULTIPLE_INSTANCES.UNIQUE_DATA_WIDTH[1].front_ports.DEBUG_DISPLAY is 5
DATA_WIDTH for testbench.my_front_interface.MULTIPLE_INSTANCES.UNIQUE_DATA_WIDTH[2].front_ports.DEBUG_DISPLAY is 6

Refer this page for passing array of parameters in an entity. Also, SystemVerilog IEEE 1800-2012 Section 27 is helpful for generate blocks.

Greg
  • 18,111
  • 5
  • 46
  • 68
sharvil111
  • 4,301
  • 1
  • 14
  • 29
  • I'm struggling to access the front_interface (fi_if) in module A. What is the syntax? Shouldn't it be **fi_if.MULTIPLE_INSTANCES.UNIQUE_DATA_WIDTH[0].front_ports.data**? – R. Kukreja Apr 07 '16 at 03:36
  • Oh yes. There seems to be a **gotcha for unnamed generate block scope** discussed in [Section 2.5 Sutherland Paper](http://www.sutherland-hdl.com/papers/2006-SNUG-Boston_standard_gotchas_paper.pdf). Remove `begin : MULTIPLE_INSTANCES ..end`, and use `my_front_interface.UNIQUE_DATA_WIDTH[i].front_ports.DATA_WIDTH` from `testbench`. For accessing from module A, `fi_if.UNIQUE_DATA_WIDTH[i].front_ports.DATA_WIDTH` should work, but I am confused as to why it is **not working**. – sharvil111 Apr 07 '16 at 04:35
  • So, for module A, **use** `$root.testbench.my_front_interface.UNIQUE_DATA_WIDTH[i].front_ports.DATA_WIDTH`. When I get a solution for module A, `fi_if` hierarchy, I'll post it as soon as possible. – sharvil111 Apr 07 '16 at 04:36
  • Alright. Thank you. I'll post if I find a solution too. – R. Kukreja Apr 07 '16 at 07:58
0

Yes, it will create data as per DATA_WIDTH only, by default 4 bit.

Check the below code, with it's output. (In the code, 2 Interface Arrays with different parameter values, f & f5 are instantiated in the front_interface, to make things more clear.

interface front_port #(parameter DATA_WIDTH = 4);
  logic [DATA_WIDTH - 1 : 0] data;
  logic acknowledge;

  modport f_interface(input data, output acknowledge);
endinterface

interface front_interface #(parameter NO_OF_IN_PORTS = 3);
  // To create array of front_port
  front_port f[NO_OF_IN_PORTS - 1 : 0](); // data should be 4 bits wide
  front_port #(5) f5[NO_OF_IN_PORTS - 1 : 0](); // data should be 5 bits wide
endinterface

module A #(parameter NO_OF_IN_PORTS = 3) (front_interface x); 
  initial
    begin
      $display ("Size of x.f[%0d].data = %0d", 0, $size(x.f[0].data));
      $display ("Size of x.f[%0d].data = %0d", 1, $size(x.f[1].data));
      $display ("Size of x.f[%0d].data = %0d", 2, $size(x.f[2].data));

      $display ("Size of x.f5[%0d].data = %0d", 0, $size(x.f5[0].data));
      $display ("Size of x.f5[%0d].data = %0d", 1, $size(x.f5[1].data));
      $display ("Size of x.f5[%0d].data = %0d", 2, $size(x.f5[2].data));
    end
endmodule


module testbench ();
  front_interface #(3)  my_front_interface();

  A #(3) (my_front_interface);
endmodule

And Output of the Code :

Size of x.f[0].data = 4
Size of x.f[1].data = 4
Size of x.f[2].data = 4
Size of x.f5[0].data = 5
Size of x.f5[1].data = 5
Size of x.f5[2].data = 5
Karan Shah
  • 1,912
  • 1
  • 29
  • 42
  • The number of instances of `front_port` is to be controlled by parameter, NUM_OF_IN_PORTS. – rahulcodesinverilog Apr 16 '16 at 01:59
  • Yes, exactly that is what I have done. `front_port #(5) f5[NO_OF_IN_PORTS - 1 : 0]()` will create instances of front_port, depending upon parameter `NO_OF_IN_PORTS` – Karan Shah Apr 17 '16 at 03:45
  • Will the array **elements** of my_front_interface have different values of DATA_WIDTH?? As per OPs question? I think this willwill create an array of instances with same value of DAAT_WIDTH (4). Then you have created again a different array of instances with DATA_WIDTH (5). The intent of OP is to have a single array of instances with different data width. – rahulcodesinverilog Apr 17 '16 at 08:07
  • I have explained, how to generate array if DATA_WIDTH is same. Now, if you want to change DATA_WIDTH in each instance, then it can't be called an array, as each elements are not same. To make different insatnces with different DATA_WIDTH values, you can use generate ... endgenerate block. – Karan Shah Apr 17 '16 at 17:55