Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using parameterized aggregate datatype in ANSI-style module port list

The following code

module test #(A = 1, B = 2) (output t_my sig);
   typedef struct {
      logic [A-1:0] fA;
      logic [B-1:0] fB;
   } t_my;
   initial $display("hello\n");
endmodule

returns the VCS error

Error-[SV-UIOT] Undefined interface or type
test.vs, 1
t_my, "sig"
  The definition for the forward-referenced interface 't_my' is missing or 
  't_my' is the name of an undefined user type.
  Check to see if the interface definition file/work library is missing or the
  definition of the user type is missing.

If I instead do

typedef struct {
   logic [A-1:0] fA;
   logic [B-1:0] fB;
}t_my;

module test #(A = 1, B = 2) (output t_my sig);
   initial $display("hello\n");
endmodule

then I get

Error-[IND] Identifier not declared
test.vs, 2
  Identifier 'A' has not been declared yet. If this error is not expected, 
  please check if you have set `default_nettype to none.


Error-[IND] Identifier not declared
test.vs, 3
  Identifier 'B' has not been declared yet. If this error is not expected, 
  please check if you have set `default_nettype to none.

Is there a way to do what I want using ANSI style module port lists? Note that I can accomplish this without ANSI style port lists as follows:

module test #(A = 1, B = 2) (sig); 
   typedef struct packed { 
       logic [A-1:0] fA; 
       logic [B-1:0] fB; } t_my; 

       output t_my sig; 
       initial $display("hello\n"); 
endmodule

module top; 
  logic topsig [2:0]; 
  test test1 (.sig ({>>{topsig}}) );
endmodule
like image 214
user2400361 Avatar asked Sep 16 '25 23:09

user2400361


1 Answers

When you have a user-defined aggregate type in a port list, you need to put that type in a place where it will be compatible to make a connection, i.e. the module test, and the module above it that will make a connection to that port. There are two ways to accomplish this:

Pass the data type down from from a higher level using a type parameter.

module test#(type T) (input T sig);
   parameter A = $bits(sig.fA);
   parameter B = $bits(sig.fB);

   initial #1 $display(A,, B);
endmodule
module top;
   typedef struct {
      logic [3:0] fA;
      logic [4:0] fB;
   } my_t;

   my_t s;

   test #(my_t) t2(s);

endmodule 

displays

#           3           4

or you can put the type in a common package. However to make the struct parameterized, you need to wrap the type in a class. See section 6.25 of the 1800-2012 LRM (This is supposed to be synthesiable)

package p;
class T#(int A,B);
   typedef struct {
      logic [A-1:0] fA;
      logic [B-1:0] fB;
   } my_t;
endclass
endpackage : p

module test#(int A=1, B=2) (input p::T#(A,B)::my_t sig);
   initial #1 $displayb(sig.fA,, sig.fB);
endmodule

module top;
   import p::T;

   T#(2,3)::my_t s = '{'1, '1}; 
   test #(2,3) t(s);

endmodule
like image 200
dave_59 Avatar answered Sep 19 '25 16:09

dave_59