You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Verilog带符号数编写、测试bench输入及8位2补码加法器溢出问题排查

Verilog带符号数编写、测试bench输入及8位2补码加法器溢出问题排查

Hey Jason,我仔细看了你编写的8位2补码加法器代码和遇到的测试问题,咱们逐个击破:

一、测试Bench中负数显示为无符号数值的问题

你提到测试时负数(比如-23)被显示成无符号的233,这其实是仿真工具显示格式或者缺少带符号打印语句导致的——你已经用了reg signed [7:0]定义变量,变量本身是带符号的,只是没正确输出/显示而已。

解决方法很简单:在测试bench的initial块里添加带格式的$display语句,明确指定用带符号十进制格式打印,比如:

// 在每个#10之后添加打印逻辑
// Test 1
A = 5;
B = 10;
carry_in = 0;
#10;
$display("Test 1: A = %0d, B = %0d, Sum = %0d, Overflow E = %b", A, B, S, E);

// Test 2
A = 87;
B = -23;
carry_in = 0;
#10;
$display("Test 2: A = %0d, B = %0d, Sum = %0d, Overflow E = %b", A, B, S, E);

// 后续测试用例同理添加

这里的%0d是Verilog中带符号十进制的格式符,工具会正确解析signed变量的数值,不会把二进制按无符号数转换。另外,如果你用波形窗口观察,也可以手动设置变量的显示格式为「带符号十进制」或者「2补码」,不同仿真工具的操作略有差异,但都支持这个功能。

二、加法器核心代码的致命错误(进位链连接错误)

你的ripple_adder模块里,全加器的进位输入完全接错了!从FA1到FA6,你都把顶层的carry_in(初始进位)作为输入,而不是前一级全加器的carry_out,这导致整个加法器根本不是行波进位加法器,计算结果完全错误。

修正后的ripple_adder模块代码:

module ripple_adder (A, B, carry_in, sum, carry_out, E);
input signed [7:0] A;
input signed [7:0] B;
input carry_in;
output signed [7:0] sum;
output carry_out;
output E;

wire [6:0] carry;

// 正确的进位链连接:每一级的carry_in是前一级的carry_out
Full_Adder FA0(A[0], B[0], carry_in, sum[0], carry[0]);
Full_Adder FA1(A[1], B[1], carry[0], sum[1], carry[1]);  // 替换为前一级进位carry[0]
Full_Adder FA2(A[2], B[2], carry[1], sum[2], carry[2]);  // 替换为前一级进位carry[1]
Full_Adder FA3(A[3], B[3], carry[2], sum[3], carry[3]);  // 替换为前一级进位carry[2]
Full_Adder FA4(A[4], B[4], carry[3], sum[4], carry[4]);  // 替换为前一级进位carry[3]
Full_Adder FA5(A[5], B[5], carry[4], sum[5], carry[5]);  // 替换为前一级进位carry[4]
Full_Adder FA6(A[6], B[6], carry[5], sum[6], carry[6]);  // 替换为前一级进位carry[5]
Full_Adder FA7(A[7], B[7], carry[6], sum[7], carry_out); // 替换为前一级进位carry[6]

// 溢出判断逻辑是正确的:最高位进位和次高位进位异或
assign E = ((carry_out & ~carry[6]) | (~carry_out & carry[6]));
endmodule

三、全加器模块的小优化

你的Full_Adder模块里,把carry_incarry_out定义成signed是没必要的——单bit信号在Verilog里signedunsigned没有区别,改成普通input/output即可,不影响功能但更规范:

module Full_Adder (A, B, carry_in, sum, carry_out);
input signed A, B;
input carry_in;  // 去掉signed修饰
output signed sum;
output carry_out;  // 去掉signed修饰

assign sum = (A^B^carry_in);
assign carry_out = ((A&B) | (B&carry_in) | (carry_in&A));
endmodule

四、验证溢出功能的测试用例补充

你可以添加专门测试溢出/下溢的用例,确保E信号能正确触发:

  • 正数相加溢出:A = 127, B = 1(8位2补码最大正数是127,加1会溢出到-128)
  • 负数相加下溢:A = -128, B = -1(8位2补码最小负数是-128,减1会下溢到127)

备注:内容来源于stack exchange,提问作者Jason Nababan

火山引擎 最新活动