Altifigence Academy

2 / 24 · 概念

位宽、符号扩展与溢出

用数值示例区分数值解释、扩展与位宽缩窄。

区分位模式与其含义

八位模式 1111_1101 可以表示无符号数 253,也可以表示二进制补码有符号数 -3。存储的位完全相同,但比较与扩展方式不同。八位有符号数的范围是 -128 到 127,无符号数的范围是 0 到 255。位宽决定可表示的位模式数量,符号属性决定这些模式对应的数值含义。

把无符号数 253 扩展到十六位时,应使用零扩展。对 -3 进行符号扩展时,重复原来的最高位,得到 1111_1111_1111_1101。零扩展会把 -3 变成 253。在 SystemVerilog 中,计算前应明确操作数的类型和位宽;不要假定拼接或部分位选择会保留你期望的有符号含义。

SystemVerilog
logic [7:0] ua, ub;
logic [8:0] usum;
logic signed [7:0] sa, sb;
logic signed [8:0] sax, sbx, ssum;
assign usum = {1'b0, ua} + {1'b0, ub};
assign sax = {sa[7], sa};
assign sbx = {sb[7], sb};
assign ssum = sax + sbx;

这里两个输入都先扩展为九位,再相加。无符号 255+1 得到 256,低八位随后变成零。有符号 127+1 的数学结果也是 128,但缩窄为八位有符号数后会得到 -128。进位说明越过了无符号数边界,有符号溢出说明越过了有符号数边界。两个同号操作数相加后,结果符号发生变化,便说明出现了有符号溢出。-1 与 1 相加可能产生进位,却不会产生有符号溢出。

中间结果的位宽也要提前规划。最大的八位无符号乘积是 65025,需要十六位。四个八位无符号数的和可达 1020,需要十位。若把每个部分和都截断为八位,就会丢失信息,之后再加宽最终寄存器也无法恢复。

运算宽位结果缩窄后的解释
无符号 255+12560,带进位
有符号 127+1128-128,发生溢出
有符号 -3+2-1-1,没有溢出

使用 Verilator 的 WIDTH 警告检查意外的位宽变化。本课程的 Node 检查运行的是数值模型,而不是这些 HDL 代码片段。在把常见正数示例视为正确性证据之前,应先测试零、极值和正负混合的情况。

自己试试

把八位 -3 和 2 符号扩展为九位,再相加,结果是多少?四个值均为 255 的无符号数,其精确和至少需要多少位?

阅读解释

九位操作数分别是 111111101 和 000000010。它们的和是 111111111,即 -1。四个 255 相加为 1020;九位无符号数最大为 511,因此需要十位。

你的选择适用于此浏览器,可随时在页脚更改。