Reputation: 549
My struct contains parameters that vary per module. I'd like to use this struct to pass input/outputs to these modules. I'm using this for design so it has to be synthesizable and my toolchain doesn't support Interfaces unfortunately.
For example:
`ifdef MY_STRUCTS
`define MY_STRUCTS
typedef struct packed {
logic [PARAMETER_VAL-1:0] field1;
logic [PARAMETER1_VAL-1:0] field2;
} myStruct_t;
`endif
module top #(
parameter PARAMETER_VAL = 8;
parameter PARAMETER1_VAL = 16;
) (
input myStruct_t in_packet,
output myStruct_t out_packet,
);
Unfortunately, this seems to be a chicken-or-egg problem. The struct definition can't be compiled because it relies on the module parameters to define it. However, the input/output declarations can't be declared because it relies on the struct to know what to declare.
Does anyone have a solution to this? Would definitely appreciate suggestions.
Upvotes: 0
Views: 9373
Reputation: 42673
Two options:
Instead of passing a list of parameter values, pass a single struct typedef with the field widths you need. You would likely want to use the struct in the upper level anyway.
module upper;
typedef struct packed {
logic [7:0] field1;
logic [16:0] field2;
} myStruct_t;
my_Struct in, out;
lower #(.T(my_Struct_t) ins1 (in, out);
...
endmodule
module lower #(type T) (
input T in_packet,
output T out_packet,
);
...
endmodule
Create the struct type inside the lower level module, but keep the ports as packed arrays. This works because the struct is packed as well.
module top #(
parameter PARAMETER_VAL = 8;
parameter PARAMETER1_VAL = 16;
) (
input logic [PARAMETER_VAL+PARAMETER_VAL1-1:0] in,
output logic [PARAMETER_VAL+PARAMETER_VAL1-1:0] out,
);
typedef struct packed {
logic [PARAMETER_VAL-1:0] field1;
logic [PARAMETER1_VAL-1:0] field2;
} myStruct_t;
myStruct_t in_packet, out_packet;
assign in_packet = in;
assign out = out_packet;
Upvotes: 0
Reputation: 12354
Potentially you can also use a parameterized interface.
Disclaimer: the following code works with synopsys but fails with cadence in eda playground. I think that Cadence is in violation of the standard here (They might have fixed it in the latest version).
Anyway, here is the example
interface top_if #(int PARAMETER_VAL = 8, PARAMETER1_VAL = 16) ();
typedef struct packed {
logic [PARAMETER_VAL-1:0] field1;
logic [PARAMETER1_VAL-1:0] field2;
} myStruct_t;
myStruct_t in_packet, out_packet;
modport in (input in_packet);
modport out (output out_packet);
endinterface
module caller();
top_if #(8,16) top_if();
always_comb top_if.in_packet = '{11, 22};
top top(top_if.in, top_if.out);
logic [top_if.PARAMETER1_VAL-1:0] field2;
always_comb field2 = top_if.out_packet.field2;
always @* begin
$display("out.field2=%0d", field2);
end
endmodule
module top(
top_if in,
top_if out
);
logic [in.PARAMETER_VAL-1:0] field1;
always_comb field1 = in.in_packet.field1;
always_comb out.out_packet = '{field1, field1+55};
always @* begin
$display("input.field1=%d", field1);
end
endmodule
Upvotes: 2