Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
1.0k views
Welcome To Ask or Share your Answers For Others

1 Answer

The current SystemVerilog BNF does not allow any dotted "." names in a parameter initialization. But you can get around this by using a typedef instead

interface MyInterface #(int DATA_W=0, ADDR_W=0) () ;
  typedef  logic [DATA_W-1:0]   data_t;
  ...
endinterface
 
module InnerTest 
  ( input wire Clock
  , input wire Reset
  , MyInterface.SNK Sink
  ) ;
 
  typedef Sink.data_t data_t;
  localparam BIT_WIDTH_SINK_DATA = $bits( data_t );
  ...
endmodule

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...