2 / 24 · 概念
位宽、符号扩展与溢出
用数值示例区分数值解释、扩展与位宽缩窄。
课时内容可免费阅读,选课后可保存学习进度。
区分位模式与其含义
八位模式 1111_1101 可以表示无符号数 253,也可以表示二进制补码有符号数 -3。存储的位完全相同,但比较与扩展方式不同。八位有符号数的范围是 -128 到 127,无符号数的范围是 0 到 255。位宽决定可表示的位模式数量,符号属性决定这些模式对应的数值含义。
把无符号数 253 扩展到十六位时,应使用零扩展。对 -3 进行符号扩展时,重复原来的最高位,得到 1111_1111_1111_1101。零扩展会把 -3 变成 253。在 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+1 | 256 | 0,带进位 |
| 有符号 127+1 | 128 | -128,发生溢出 |
| 有符号 -3+2 | -1 | -1,没有溢出 |
使用 Verilator 的 WIDTH 警告检查意外的位宽变化。本课程的 Node 检查运行的是数值模型,而不是这些 HDL 代码片段。在把常见正数示例视为正确性证据之前,应先测试零、极值和正负混合的情况。
自己试试
把八位 -3 和 2 符号扩展为九位,再相加,结果是多少?四个值均为 255 的无符号数,其精确和至少需要多少位?
阅读解释
九位操作数分别是 111111101 和 000000010。它们的和是 111111111,即 -1。四个 255 相加为 1020;九位无符号数最大为 511,因此需要十位。