在 systemverilog 设计中覆盖包结构

overwrite package struct in systemverilog design

我尝试通过在模块外声明另一个 packad 结构来覆盖包结构 并将其覆盖为参数 这是 RTL 代码。

顶级模块

module test_top 
#()
();

//Module A
A#()
u0
();


//Module B
B#()
u1
(); 

endmodule

模块 A

module A 
#()
();

typedef struct packed
{
 logic [31:0]    addr    ;       
 logic [3:0]     tag     ;       
} a_cmd_t;

target
#(
  .CNT    (4),
  .CMD_T  (a_cmd_t   )   
)
u0
(
 .cmd() 
); 

endmodule

模块 B

module B 
#(
)
(
);

typedef struct packed
{
 logic [31:0]    addr    ;       
 logic [7:0]     tag     ;       
} b_cmd_t;

target
#(
   .CNT(5),         
   .CMD_T (b_cmd_t) 
)
u0
(
  .cmd() 
);

endmodule

模块目标

module target
import target_pkg::*;
 #(
 parameter CNT = 1,             
 parameter type CMD_T     = target_cmd_t      
)
(
 output CMD_T cmd
);

localparam WIDTH = $bits(cmd.tag);  
localparam ZERO_FILL_WIDTH = (WIDTH - CNT);

wire [ZERO_FILL_WIDTH-1:0] test;
assign test = {ZERO_FILL_WIDTH{1'b0}};

endmodule

套餐

package target_pkg;

typedef struct packed
{
 logic [31:0]   addr  ;       
 logic [7:0]    tag   ; 
} target_cmd_t;

endpackage

但是当我编译(w/VCS)时,似乎数字不能像我期望的那样被覆盖 因为我会得到如下编译错误:

Error-[ZMMCM] Zero multiconcat multiplier
~/target.sv, 15
"{ZERO_FILL_WIDTH {1'b0}}"
  Zero multiconcat multiplier cannot be used in this context. (Target as 
  above)
  A replication with a zero replication constant is considered to have a size 
  of zero and is ignored. Such a replication shall appear only within a 
  concatenation in which at least one of the operands of the concatenation has
  a positive size.
  Please use -error=noZMMCM to get around this error.
  Instance stack trace:
      target#(4, a_cmd_t, , )   
~/A.sv, 21
      A#()   
~/test_top.sv, 14
      test_top  
~/test_top.sv, 2
  

Error-[NMCM] Negative multiconcat multiplier
~/target.sv, 15
  Multiconcat multiplier cannot be negative value.
  Source info: {ZERO_FILL_WIDTH {1'b0}}
  Instance stack trace:
      target#(5, b_cmd_t, , )   
~/B.sv, 23
      B#()   
~/test_top.sv, 21
      test_top  
~/test_top.sv, 2
  Please refer LRM(1364-2005) section 5.1.14.

对于第一个错误信息“zero multiconcat multiplier”我认为是合理的,因为对于模块A (hierarchy:test_top.u0.u0) 参数 CNT 为 4,WIDTH = $bits(cmd.tag) = 4 所以参数 ZERO_FILL_WIDTH= (WIDTH - CNT) = 0.

但对于其他错误信息“Negative multiconcat multiplier” 来自模块 B(层次结构:test_top.u1.u0)对我来说是不合理的。 因为对于模块 B(层次结构:test_top.u1.u0) 参数CNT为5,WIDTH = $bits(cmd.tag) = 8 所以参数ZERO_FILL_WIDTH= (WIDTH - CNT) = 3 为正值。

我尝试这样修改模块 B:

module B 
#(
)
(
);

typedef struct packed
{
 logic [31:0]    addr    ;       
 logic [7:0]     tag     ;       
} b_cmd_t;

target
#(
   .CNT(3),         
   .CMD_T (b_cmd_t) 
)
u0
(
  .cmd() 
);

endmodule

让参数CNT=5,重新编译报错信息 “负多重连接乘数”消失了。 所以看起来值 WIDTH = $bits(cmd.tag) 是 4 而不是 8.
但我希望价值应该来自 b_cmd_t

所以我想知道这个 RTL 代码是否有什么问题导致我无法成功覆盖打包结构?

您看到的消息是正确的。从报错信息看实例:

 target#(4, a_cmd_t, , )  

上面的CNT == 4a_cmd_t中的标签宽度也是4:logic [3:0] tag

表达式 localparam ZERO_FILL_WIDTH = (WIDTH - CNT); 的计算结果为 0,这在以下复制器中是非法的:{ZERO_FILL_WIDTH{1'b0}};.

第二期(负数)问题不同。 vcs中显然有一个错误。无论出于何种原因,vcs 都没有在那里做正确的工作,也没有做正确的覆盖。它查看了一个正确的结构,但没有选择正确的字段并且无法识别它的宽度为 8。我建议你向 synopsys 报告它。

但是,如果您摆脱 localparams 并使用以下参数,它将起作用:

  wire [$bits(cmd.tag) - CNT -1:0] test;
  assign test = {$bits(cmd.tag) - CNT{1'b0}};