【问题标题】:why is there no overflow flag set for binary subtraction?为什么没有为二进制减法设置溢出标志?
【发布时间】:2018-05-02 01:23:06
【问题描述】:

我有基本的二进制数学问题。例如;

reg [31:0] a = 32'hFFFF_FFFF; 
reg [31:0] b = 32'hFFFF_FFFF; 
reg [31:0] c = 0;

我知道 c = a - b 将导致零并且不会设置溢出标志。

我的理解是 ALU 使用 2 的减数补码(运算符右侧)并将其添加到被减数(运算符左侧)。

所以存储在 reg b 中的值的 2s 补码是 32'h1。现在,如果我将它添加到 reg a,我将得到 32 个零和一个 1,这是溢出。那为什么不设置溢出标志呢?

即使我将 reg c 的宽度更改为 33,c[32] 也不会设置为 1。我知道当两个相等的数字相减时,没有溢出,但是当我做 2s 补码数学时会溢出。

让我帮助我消除脑海中的困惑。 感谢您的时间。

【问题讨论】:

  • 从 5 岁开始,你被教导减去两个相同的数字会得到零。如果您得到不同的结果,使用假设、计算和结论,您就知道自己做错了!

标签: binary verilog cpu alu


【解决方案1】:

abc 都是 32 位无符号变量,而您正在执行 32 位算术运算。 LRM 表示算术运算的结果宽度是其最大操作数的宽度。所以 overflow 或第 33 位被截断。即使将c 扩展到 33 位,这一事实仍然成立。

【讨论】:

    【解决方案2】:

    你必须看看二进制补码是什么。因此,在您的示例中,ab 是 32 位向量,所有位都设置为“1”:

     a[31:0] = 32'hFFFF_FFFF;
    

    这个的补码是 32'h0000_0001;因此,将其添加到 b 将导致所有设置为 0 和溢出位 33 被截断,因为操作的宽度是 32 位。

    现在,假设你有一个 33 位向量

    a[32:0] = 33'hFFFF_FFFF;
    

    二进制补码是33'h1_OOOO_OOO1。因此,如果将其添加到 33 位向量 33'hFFFF_FFFF,您仍将拥有所有 33 位等于“0”。如果您向a 添加更多位,则将更多1 添加到msb 端:34'h3_0000_0001,...

    而且,如果c 比操作上下文更宽,对于无符号变量,它将始终为 0 扩展,否则为符号扩展。

    因此,您总是会遇到溢出位超出操作宽度并被截断的情况。这是由操作宽度的 LRM 要求保证的。

    【讨论】:

    • 感谢您的回复。如果我将测试用例更改为 a 中的所有 1,设置 b[0] = 1 并将 c 的宽度增加到 33 位并进行加法而不是减法,则 c 有 33'h100000000。结果的宽度不应该限制为 32 并且符号在 c[33] 中扩展为 0?我所有的注册表都没有签名。感谢您花时间向我解释这一点。
    • 您还需要将宽度设置为 a 和/或 b 到 33 位。这样,加法的结果将是 33 位宽,高位将设置为“1”。但它相当于减法,并且“0000_0001”是 FFFF_FFFF 的二进制补码。
    • 抱歉不清楚。 a[31:0] = '1, b[31:0] = 1 并且结果存储在 c[32:0] 中,根据您的解释,即使 c 是 33 位,大于 32 位的结果值也会被截断,所以我应该在 c 中看到全零。但我看到 33'h100000000。我在这个测试用例中做加法。
    • 我猜表达式的左侧设置了整个表达式的宽度。因此,评估 rhs 的上下文的宽度是所有操作数的最大宽度,包括 lhs,在您的情况下为 33。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 2014-05-31
    • 2017-07-30
    • 2021-03-19
    • 2016-07-29
    相关资源
    最近更新 更多