SystemVerilog数组实例化行波进位加法器Verilator ASSIGNIN错误咨询
问题原因与修复方案
问题1 报错原因与修复方法
报错原因
Verilator的ASSIGNIN告警触发逻辑是所有对模块输入端口的连续赋值操作,不管该输入端口属于当前顶层模块还是子模块,都会触发。你当前的写法通过跨层次引用直接给子模块输入端口赋值,虽然符合IEEE Verilog标准,但不符合工业界常规编码规范:常规做法是所有子模块端口都在实例化阶段完成连接,不会后续通过跨层次赋值修改驱动。
推荐修复方案(无需关闭告警,符合编码规范)
声明中间进位总线,实例化全加器数组时直接把cin、cout端口和总线对应位连接,完全避免跨层次赋值:
module ripple_adder16 (a, b, cin, sum, cout); input [15:0] a, b; input cin; output [15:0] sum; output cout; wire [15:0] a, b; wire [15:0] sum; wire cout; /* verilator lint_off UNOPTFLAT */ wire [16:0] carries; /* verilator lint_on UNOPTFLAT */ // 实例数组的标量端口会依次匹配连接向量的每一位,符合Verilog-2001及以上标准 full_adder adders [15:0] ( .a(a), .b(b), .cin(carries[15:0]), .sum(sum), .cout(carries[16:1]) ); assign carries[0] = cin; assign cout = carries[16]; endmodule
问题2 单行赋值替代generate循环的实现
上述修复方案已经实现了你需要的逻辑:Verilog支持实例数组的端口聚合访问,adders[15:0].cout会自动把16个全加器的cout输出按顺序拼接为16位向量,直接通过实例化端口连接到carries[16:1],不需要额外写generate循环,也不需要内联full_adder的代码。
如果确实需要保留显式assign语句的写法,也可以直接写assign carries[16:1] = adders[15:0].cout,语法完全合法,不会触发报错。
内容的提问来源于stack exchange,提问作者GHJGHJJHG
相关产品推荐
相关产品推荐

