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.