【发布时间】:2019-05-15 07:52:08
【问题描述】:
我正在 SystemVerilog 中设计一个浮点单元,它接受两个 IEEE754 格式的 32 位输入,将它们相加,然后以相同的 32 位 IEEE754 格式输出结果。
我的问题是,我如何判断我的结果是否需要标准化?
我意识到这是当您需要将“最左边”的 1 移动到正确的位时,应该是位 23。(从位 0 开始)
我很难理解如何确定正确的“最左边”1 位是什么,以便我可以移动尾数并适当地增加/减少指数位。
如果我的理解是正确的,加法应该有以下过程。
- 将位分为符号、指数和尾数
- 在尾数前添加“1”
- 比较指数并将差值添加到较小的指数
- 将较小指数的尾数向右移动所述差异以正确“排列”小数/数字
- 执行二进制加法
- 必要时标准化结果
我相信除了规范化部分之外,我的每一步都是正确的。我的问题是,如果我只有比特,我怎么能确定结果没有标准化?
我知道如果结果不是 1.(分数),它就没有被规范化。
IE。 10.10101 * 2^1 应归一化为 1.010101 *2^2, .1001 * 2^2 应归一化为 1.001 * 2^1。
具体来说,我想我想问我如何在添加两个数字后跟踪“小数”位的位置。
例如:添加输入 a: 0x3fc00000 (1.5) 和 b: 0x40500000 (3.25)
a = 0 | 0111 1111 | (1) 100 0000 0000 0000 0000 0000
b = 0 | 1000 0000 | (1)101 0000 0000 0000 0000 0000
a 的指数比 b 小 1,所以:
a = 0 | 1000 0000 | 0(1)10 0000 0000 0000 0000 0000
b = 0 | 1000 0000 | (1)101 0000 0000 0000 0000 0000
添加尾数会给我们一个结果
1 0011 0000 0000 0000 0000 0000
这里我们看到“最左边”的 1 是第 24 位而不是第 23 位,因此我们将尾数向右移动 1 并增加指数以标准化结果。然后我们删除“最左边”的 1,因为它在 IEEE754 格式中是隐含的,我们得到:
0 | 1000 0001 | 001 1000 0000 0000 0000 0000 (4.75) 作为我们的最终输出,这是正确的。
鉴于这个例子,我认为我只需要检查以下情况:
- 如果尾数的第 24 位等于 1,则尾数右移并递增指数
- 否则检查位 23 为 1,如果为真,则不需要规范化
- 否则校验位22为1,则尾数左移,指数递减
但是,我发现这仅在某些情况下是正确的。我错过了什么?
在我的实现中,我创建了一个 26 位的值来保存两个尾数之和,我不确定这是否正确。第 25 位是尾数的符号,我认为我不需要,第 24 位和第 23 位是隐藏位,或者不会包含在最终输出中的位。
例如:0x449ebbc8 (1269.868163) + 0xc60eb709 (-9133.758561) 给我以下尾数:
11 0111 1010 1101 1111 1001 0000 注意这是 26 位 (25:0)
如果我遵循前一种情况,这意味着不包括符号位的“最左边的 1”位将是 24 位,这意味着我会将尾数向右移动并增加指数。然而正确的答案是相反的! “'true' 最左边的 1”位实际上是位 22!这意味着我应该向左移动并减少!给我最终输出:
1 | 10001011 | 111 0101 1011 1111 0010 0000 (-7863.8906) 这是正确的。
类似地,将 0x45c59cbd 和 0xc473d9dc 相加得到尾数为
01 1010 0111 0010 0001 1000 0010 但“最左边的 1”位不是第 24 位,而是第 23 位,因此不需要归一化。
为什么在第一种情况下我需要担心第 24 位而不是其他两种情况?是因为我为其他情况添加了相反的符号吗?溢出问题?还是我从根本上缺少其他东西?
感谢您的帮助,如果格式不好,请见谅!
【问题讨论】:
标签: floating-point verilog system-verilog ieee-754 twos-complement