I have a highly hierarchical design in SystemVerilog (synthesized using Xilinx Vivado). I use parametrized interfaces and modules. Some data types inside the interfaces are calculated using (interface internal) functions, based on their parameters. I want to be able to access information(specifically, bit width) of those types inside the modules that are using those interfaces. It seems that I can instantiate the type from the interfaces inside a module, but can not use the bit width as a constant.
That is, given the following:
interface iface #(PARAM=1);
const int i = PARAM; //Gives a warning about simultaneous procedural and continuous assignment
typedef logic [PARAM-1:0] t;
t s;
endinterface
module test(iface i);
i.t s; //Works
const int size1 = $bits(i.s); //Works
const int size2 = $bits(s); //Works
localparam int p = $bits(i.s); //Fails: Heirarchial name access not allowed
wire [size1-1:0] s1; //Fails: "size1" is not constant
wire [size2-1:0] s2; //Fails: "size2" is not constant
wire [i.i-1:0] s3; //Fails: "i" is not constant
wire [p-1:0] s3; //Would have worked, is "p" was defined
localparam int p2 = i.i; //Fails: "i" is not constant
localparam int p3 = i.PARAM; //Fails: Heirarchial name access not allowed
//Any of the above two lines would solve all my problems
endmodule
I tried several solutions, including using packages. But in that case there seems to be no way to initialize the package parameters from the top-level parameters.
I read the SystemVerilog LRM regarding both interfaces and packages and could not find any solution in there.
Any solution (short of calculating the derived parameters outside the interface and passing them down the heirarchy) or a pointer in the right direction would be highly appreciated.