SystemVerilog全加器输出始终为X,SW定义是否存在问题?
问题分析与解决
你的LED输出始终为X的核心原因是TestBench中的检查逻辑错误导致仿真提前终止,并非SW的定义问题。以下是具体问题和修复方案:
问题1:位宽不匹配的比较错误
你定义的sum是3位信号(logic [2:0] sum),而LED[0]是1位信号,直接使用sum !== LED[0]进行比较时,SystemVerilog会自动进行位宽扩展,导致比较逻辑异常。仿真一开始就触发错误提示和$stop,后续的激励循环根本没机会执行,所以LED一直保持初始的X状态。
问题2:检查逻辑的逻辑错误
全加器的输出中,LED[0]对应三个输入和的最低位(sum[0]),LED[1]对应和的第二位(sum[1]),你只检查了LED[0],遗漏了进位输出的检查,且比较对象错误。
修复后的TestBench代码
`timescale 1ns/100ps module tb; logic [2:0] SW; logic [1:0] LED; challenge u_challenge (.*); // Stimulus initial begin $printtimescale(tb); SW = '0; for (int i = 0; i < 8; i++) begin $display("Setting switches to %3b", i[2:0]); SW = i[2:0]; #100; end $display("PASS: logic_ex test PASSED!"); $stop; end logic [2:0] sum; assign sum = SW[0] + SW[1] + SW[2]; // Checking - 修复后的检查逻辑 always @* begin // 同时检查和输出与进位输出 if (sum[0] !== LED[0] || sum[1] !== LED[1]) begin $display("FAIL: Addition mismatch at SW=%3b, expected sum=%2b, got LED=%2b", SW, sum[1:0], LED); $stop; end end endmodule // tb
额外优化建议
- 模块中的
SW定义为wire,TestBench中用logic是合法的,SystemVerilog允许这种信号类型的跨模块连接,无需修改。 - 敏感列表使用
always @*代替always @(SW, LED),可以自动包含所有相关输入信号,避免手动维护敏感列表时出现遗漏。 - 全加器的进位逻辑可以简化为
LED[1] = (SW[1] & SW[0]) | (SW[1] & SW[2]) | (SW[0] & SW[2]);,逻辑更直观,运算结果与原代码一致。
内容的提问来源于stack exchange,提问作者Pclaverie
相关产品推荐
相关产品推荐

