8位CLA加法器仿真输出显示'X'?问题排查需求
8位CLA加法器仿真异常排查与解决
编写了8位CLA加法器Verilog模块及测试平台后,仿真出现两处异常:
- 第一条
$display语句所有信号显示'X' - 第二条语句输入参数与预期不符,结果和预设正确输出存在差异
8位CLA加法器代码
module cla8(a, b, cin, sum, cout); input [7:0] a; input [7:0] b; input cin; output [7:0] sum; output cout; wire p0, g0, p1, g1, p2, g2, p3, g3, p4, g4, p5, g5, p6, g6, p7, g7; wire c8, c7, c6, c5, c4, c3, c2, c1; assign p0 = a[0] ^ b[0]; assign p1 = a[1] ^ b[1]; assign p2 = a[2] ^ b[2]; assign p3 = a[3] ^ b[3]; assign p4 = a[4] ^ b[4]; assign p5 = a[5] ^ b[5]; assign p6 = a[6] ^ b[6]; assign p7 = a[7] ^ b[7]; assign g0 = a[0] & b[0]; assign g1 = a[1] & b[1]; assign g2 = a[2] & b[2]; assign g3 = a[3] & b[3]; assign g4 = a[4] & b[4]; assign g5 = a[5] & b[5]; assign g6 = a[6] & b[6]; assign g7 = a[7] & b[7]; assign c0 = cin; assign c1 = g0|(p0 & c0); assign c2 = g1|(p1 & g0)|(p1 & p0 & c0); assign c3 = g2|(p2 & g1)|(p2 & p1 & g0)|(p2 & p1 & p0 & c0); assign c4 = g3|(p3 & g2)|(p3 & p2 & g1)|(p3 & p2 & p1 & g0)|(p3 & p2 & p1 & p0 & c0); assign c5 = g4|(p4 & g3)|(p4 & p3 & g2)|(p4 & p3 & p2 & g1)|(p4 & p3 & p2 & p1 & g0)| (p4 & p3 & p2 & p1 & p0 & c0); assign c6 = g5|(p5 & g4)|(p5 & p4 & g3)|(p5 & p4 & p3 & g2)|(p5 & p4 & p3 & p2 & g1)| (p5 & p4 & p3 & p2 & p1 & g0)|(p5 & p4 & p3 & p2 & p1 & p0 & c0); assign c7 = g6|(p6 & g5)|(p6 & p5 & g4)|(p6 & p5 & p4 & g3)|(p6 & p5 & p4 & p3 & g2)| (p6 & p5 & p4 & p3 & p2 & g1)|(p6 & p5 & p4 & p3 & p2 & p1 & g0)| (p6 & p5 & p4 & p3 & p2 & p1 & p0 & c0); assign c8 = g7|(p7 & g6)|(p7 & p6 & g5)|(p7 & p6 & p5 & g4)|(p7 & p6 & p5 & p4 & g3)| (p7 & p6 & p5 & p4 & p3 & p2 & g1)|(p7 & p6 & p5 & p4 & p3 & p2 & p1 & g0)| (p7 & p6 & p5 & p4 & p3 & p2 & p1 & p0 & c0); assign sum[0] = p0 ^ c0; assign sum[1] = p1 ^ c1; assign sum[2] = p2 ^ c2; assign sum[3] = p3 ^ c3; assign sum[4] = p4 ^ c4; assign sum[5] = p5 ^ c5; assign sum[6] = p6 ^ c6; assign sum[7] = p7 ^ c7; assign cout = c8; endmodule
测试平台代码(原版本)
module cla8bit_testbench; reg[7:0] a; reg[7:0] b; reg cin; wire [7:0] sum; wire cout; cla8 uut(.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout)); initial begin $dumpfile("dump.vcd"); $dumpvars(1); //带进位情况 a = 8'b11110000; b = 8'b11001100; cin = 0; $display("In the case involving carry, For A = %8b, B = %8b, and Cin = %1d: the Sum will be %8b and Cout will be %1d.", a, b, cin, sum, cout); #20 $display("In the case without involving carry, For A = %8b, B = %8b, and Cin = %1d: the Sum will be %8b and Cout will be %1d.", a, b, cin, sum, cout); //无进位情况 a = 8'b11110000; b = 8'b00001101; cin = 0; #100; end endmodule
实际输出
# KERNEL: In the case involving carry, For A = xxxxxxxx, B = xxxxxxxx, and Cin = x: the Sum will be xxxxxxxx and Cout will be x. # KERNEL: In the case without involving carry, For A = 11110000, B = 11001100, and Cin = 0: the Sum will be 10111100 and Cout will be 1.
预期输出
# KERNEL: In the case involving carry, For A = 11110000, B = 11001100, and Cin = 0: the Sum will be 10111100 and Cout will be 1. # KERNEL: In the case without involving carry, For A = 11110000, B = 00001101, and Cin = 0: the Sum will be 11111101 and Cout will be 0.
问题分析与解决
1. 第一条$display显示'X'的原因
Verilog中initial块语句顺序执行,但组合逻辑的输出不会在信号赋值后立即更新——仿真器需要等到当前时间步结束,才会计算组合逻辑结果。第一条$display紧跟在信号赋值后,此时输入信号的更新还未传递到加法器输出,甚至部分reg类型变量在0时刻初始值为'X',导致输出全为'X'。
解决方法:在信号赋值后添加#1等待最小时间单位,确保组合逻辑完成计算、信号稳定后再执行打印。
2. 第二条$display输入参数不符的原因
原测试平台中,无进位测试的输入赋值语句写在$display之后,导致打印的仍是之前的带进位测试输入,而非预期的无进位输入。
解决方法:调整代码顺序,先更新无进位测试的输入信号,再执行$display,同样添加延迟等待信号稳定。
修改后的测试平台代码
module cla8bit_testbench; reg[7:0] a; reg[7:0] b; reg cin; wire [7:0] sum; wire cout; cla8 uut(.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout)); initial begin $dumpfile("dump.vcd"); $dumpvars(1); //带进位情况 a = 8'b11110000; b = 8'b11001100; cin = 0; #1; // 等待信号稳定 $display("In the case involving carry, For A = %8b, B = %8b, and Cin = %1d: the Sum will be %8b and Cout will be %1d.", a, b, cin, sum, cout); #20; //无进位情况:先更新输入,再打印 a = 8'b11110000; b = 8'b00001101; cin = 0; #1; // 等待信号稳定 $display("In the case without involving carry, For A = %8b, B = %8b, and Cin = %1d: the Sum will be %8b and Cout will be %1d.", a, b, cin, sum, cout); #100; $finish; // 添加结束语句,避免仿真无限运行 end endmodule
修改后的输出
运行修改后的测试平台,将得到与预期一致的输出:
# KERNEL: In the case involving carry, For A = 11110000, B = 11001100, and Cin = 0: the Sum will be 10111100 and Cout will be 1. # KERNEL: In the case without involving carry, For A = 11110000, B = 00001101, and Cin = 0: the Sum will be 11111101 and Cout will be 0.
内容的提问来源于stack exchange,提问作者HDY
相关产品推荐
相关产品推荐

