Also discussed at:
https://verificationacademy.com/forums/systemverilog/parameterizing-bit-widths-fields-packed-struct-so-modules-can-infer-bit-width-if-used-port-map-virtual-interface-interface-compile-time-configured-struct-bit-width
https://forums.xilinx.com/t5/Synthesis/Parameterizing-the-Bit-Widths-of-fields-in-a-packed-struct-so/td-p/1191678
I am having trouble accomplishing my intent in SystemVerilog trying to use the latest language features to make my code more elegant and less verbose. For synthesis**
I would like to accomplish the following:
- be able to parameterize the bit widths of fields in a packed struct that I want to define ... I have attempted to accomplish this using a parameterized interface construct
- I would like for modules with that parameterized interface as an INPUT to the module to be able to infer the bit width of a field inside that packed struct defined inside the interface
I have been mostly successful in past experiments but I have run into an issue.
Please see the following simple interface definition:
interface MyInterface #(int DATA_W, ADDR_W) () ;
typedef struct packed
{ logic valid
; logic [ADDR_W-1:0] addr
; logic [DATA_W-1:0] data
; } SimpleStruct;
SimpleStruct bus;
logic ready;
modport SNK (input bus, output ready);
modport SRC (output bus, input ready);
endinterface
It is easy enough to instantiate an interface and use it at the input of a simple module in my Top module for this example:
module TopTest
( input wire Clock
, input wire Reset
, input wire [31:0] In
, output wire dummyOut
) ;
MyInterface # ( 32, 3 ) my_interface ();
assign my_interface.bus.data = In ;
assign my_interface.bus.addr = 3'h3 ;
InnerTest inst_mod_inner_test
( .Clock( Clock )
, .Reset( Reset )
, .Sink( my_interface )
) ;
assign dummyOut = my_interface.ready ;
endmodule
The problem that I am running into is that I do not want to parameterize the actual module with field bit widths, because I believe that at compile time the bit widths of the fields should be already established and accessible. This seems to not be the case, and I am wondering if there is anything I can do to accomplish inferring the bit width of the packed struct in the interface (remember that is the case because I want it parameterized, I know it is easy to get $bits of a field of a struct that is not defined in an interface but instead defined in a package or module)
module InnerTest
( input wire Clock
, input wire Reset
, MyInterface.SNK Sink
) ;
localparam BIT_WIDTH_SINK_DATA = $bits( Sink.bus.data ) // this line errors out b/c sink is 'virtual'
RAM # ( .DATA_WIDTH( BIT_WIDTH_SINK_DATA ) ) ram ( ... // etc
... other code to drive output ready of interface ...
endmodule
There are many reasons why a designer would want to make a module "parameterizable" and I have taken that approach in the past, but I am very interested in not duplicating information. If I were to take the easy approach, I would simply parameterize my inner test module so that I provided it DATA_WIDTH, but I would then have two numbers to update and a lot of parameters that I feel I do not need. I think it would be most elegant if I could simply infer characteristics of the parameterized struct somehow. The information I am looking for is truly known at compile time in my opinion. I just can't seem to access it, or this is another shortfall of SystemVerilog.