Parameterized struct in systemverilog design

Hello,
i have a module that is instantiated multiple times with different parameter.
parameter CNTR_TBL_ADDR_W = -1,
parameter CNTR_TBL_DATA_W = -1

instantiation with the same parameters can have mutual interface.
i would like to pass that interface with a struct that is defined in a common package:

typedef struct packed {

    logic [CNTR_TBL_ADDR_W-1:0] cntr_idx;
    logic [CNTR_TBL_DATA_W-1:0] cntr_val;

} stage_t;

what i would like to do is to have this struct parameterized, meaning on istantiation, set the parameters:
typedef struct packed #(parameter CNTR_TBL_ADDR_W, parameter CNTR_TBL_DATA_W) {

    logic [CNTR_TBL_ADDR_W-1:0] cntr_idx;
    logic [CNTR_TBL_DATA_W-1:0] cntr_val;

} stage_t;

module

stage_t #(CNTR_TBL_ADDR_W = 3,CNTR_TBL_DATA_W = 4) stage;

endmodule

is this possible?

thanks, Kobi.

The structures in SystemVerilog can not be defined like that way. One has to define the structure separately for each vale of the parameter.

You can keep a workaround by using the macros. One needs two macros: one for every structure that is to be created and other for macro for a unique structure name. Thereafter, invoke the macros from the parameterized module/interface. This will take the overridden values from the module and create different structures accordingly. Refer to the sample code below.


`define MY_STRUCT_STAGE(NAME) \
   my_struct_t_``NAME``

`define MY_STRUCT_STAGE_DEFINE(NAME, CNTR_TBL_ADDR_W, CNTR_TBL_DATA_W) \
 typedef struct { \
                 logic [CNTR_TBL_ADDR_W-1``:0] address; \
                 logic [CNTR_TBL_DATA_W-1:0] data; \
    } `MY_STRUCT_STAGE(NAME)

module my_module #(parameter int CNTR_TBL_ADDR_W=5, parameter int CNTR_TBL_DATA_W=6) ();
// interface my_interface #(parameter CNTR_TBL_ADDR_W=5, parameter CNTR_TBL_DATAR_W=6) ();

  `MY_STRUCT_STAGE_DEFINE(stage_t, CNTR_TBL_ADDR_W, CNTR_TBL_DATA_W); // Structure with parameters CNTR_TBL_ADDR_W=7 and CNTR_TBL_DATA_W=31
  
  `MY_STRUCT_STAGE_DEFINE(stage_t_2, CNTR_TBL_ADDR_W, CNTR_TBL_DATA_W); // Structure with different parameter values
  

`MY_STRUCT_STAGE(stage_t)  s_0, s_1; // Structure handles
  `MY_STRUCT_STAGE(stage_t_2) s_2, s_3; // Structure handles

  initial begin
    $display("In %m hierarchy, Width of s_0.address = %0d",$size(s_0.address));
    $display("In %m hierarchy, Width of s_2.address = %0d",$size(s_2.address));
  end
  
endmodule
//endinterface

// Top module
module top();
  my_module #(9,3) m1(); // Instantiating with different width of struct variables
  my_module #(1,2) m2();
endmodule


Refer to this link for some more discussion on a similar topic.

In reply to sharvil111:

Do not declare typedefs inside modules if they are to be shared across other modules.

What you should be doing is declaring a parameterized interface with the typedef inside the interface.

interface common_intf #(int  ADDR_W, DATA_W);
typedef struct packed {

logic [ADDR_W-1:0] cntr_idx;
logic [DATA_W-1:0] cntr_val;

} stage_t;

  stage_t bus;
  
endinterface

module mod1(common_intf p1);
  initial $display("%m idx bits %0d, val bits %0d", $bits(p1.bus.cntr_idx), $bits(p1.bus.cntr_val));
  typedef p1.stage_t stage_t; // "imports" type into module
  stage_t local_bus;
endmodule

module mod2(common_intf p1, p2);
  initial $display("%m-1 idx bits %0d, val bits %0d", 
                   $bits(p1.bus.cntr_idx),
                   $bits(p1.bus.cntr_val));
  typedef p1.stage_t stage1_t; // "imports" type into module
  stage1_t local_bus1;
  initial $display("%m-2 idx bits %0d, val bits %0d", 
                   $bits(p2.bus.cntr_idx), 
                   $bits(p2.bus.cntr_val));
  typedef p2.stage_t stage2_t; // "imports" type into module
  stage2_t local_bus2;
  initial $display("%m params p1 ADDR_W %0d DATA_W %0d", p1.ADDR_W, p1.DATA_W);
  initial $display("%m params p2 ADDR_W %0d DATA_W %0d", p2.ADDR_W, p2.DATA_W);

  
endmodule

module top;
  common_intf #(8,16) i1_2(); // connects m1 to m2
  common_intf #(4,32) i2_3(); // connects m2 to m3
  mod1 m1(i1_2);
  mod2 m2(i1_2,i2_3);
  mod1 m3(i2_3);
endmodule

In reply to dave_59:

I agree with you. There can be workarounds better methods that can be applied.

In reply to dave_59:

Shouldn’t the second typedef in mod2 be

typedef p2.stage_t stage2_t

?

In reply to abregnsbo:

I believe you are correct. Fixed above. Thanks.