Using parameterized aggregate datatype in ANSI-style module port list
system-verilog
Solution
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
Problem
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 ```