verilog数的舍入溢出和截位

发布时间 2023-10-17 12:02:57作者: luckylan

四舍五入(round)

前面讲的都是对数据进行扩位,这一节说的是对数据截位时如何进行四舍五入以提高截位后数据的精度。

假设一个9Q6格式的数据为:9’b011.101101,现在只想保留3位小数位,显然必须把最后三位小数位截掉,但是不能直接把数据截成6’b011.101,这样是不精确的,工程上一般也不允许这么做.

首先举例整理思路:

image可以这么理解:正数向下取整,负数向上取整。对于0.5这个地方处理不同。
特殊说明:取round(-2.5)为-2,实际上matlab运行的结果是round(-2.5)为-3。
通过整理真值表,发现round截位时的小数进位与三个变量均相关:数据符号位、小数位的最高bit,以及小数位除最高bit外的所有bit是否均为0(按位或)
image

小数进位可以表示=A ? B &(|C): B;
设输入数据din位宽为DW位,其中小数部分位宽为RD位,且需要四舍五入截掉小数部分,结果为dout。
input [DW-1:0]din; output [DW-RD:0]dout;
即carry_bit=din[DW-1]?( din[RD-1] & (|din[RD-2:0]) ):din[RD-1]
再考虑溢出保护:
image

dout={din[DW-1],din[DW-1:RD]}+{ {(DW-RD){1'B0}}, carry_bit};
假设溢出不保护:
image
这种处理和floor几乎一摸一样,会导致频域上出现不必要的直流分量,相当于所有分量向下做了减法。

正确的做法是先看这个数据是正数还是负数,因为9’b011.101101的最高位为0,所以它是一个正数,然后再看截掉部分(此例中截掉部分是最末尾的101)的最高位是0还是1,在数据是正数的情况下,如果截掉部分的最高位为1,那么是需要产生进位的,所以,最终9’b011.101101应该被截成6’b011.110.

 如果是负数则正好相反。假设一个9Q6格式的数据为:9’b100.101101,由于最高位是1,所以这个数是一个负数,然后再看截断部分的最高位以及除最高位的其他位是否有1,此例中截断部分(截断部分为末尾的101)的最高位为1,而且除最高位以外的其他位也有为1的情况,由于负数最高位的权重是(- ),所以对于这种情况是不需要进位的,与正数不同的是,负数不进位是需要加1的。因此最终9’b100.101101应该被截成6’b100.110。

  假设a是一个9Q6格式的数据,要求把小数位截成3位。下面是Verilog代码:

    assign carry_bit = a[8] ? ( a[2] & ( |a[1:0] ) ) : a[2] ; //正数和负数四舍五入截断

    assign a_round = {a[8], a[8:3]} + carry_bit ;

  上面的代码第一行是通过判断符号位a[8]和截断部分数据特征来确定是否需要进位,如果a[8]是0,计算得到的carry_bit为1,则表示是a是正数,且截断是需要进位;如果a[8]是1,计算得到的carry_bit为1,则表示是a是负数,且截断是不需要进位的,负数不进位需要加1。代码第二行为了保证进位后数据不溢出,所以扩展了一位符号位。

饱和(saturation)截位

 所谓饱和处理就是如果计算结果超出了要求的数据格式能存储的数据的最大值,那么就用最大值去表示这个数据,如果计算结果超出了要求的数据格式能存储的数据的最最小值,那么就用最小值去表示这个数据。

例1:有一个6Q3的数据为6’b011.111,现在要求用4Q2格式的数据去存储它,显然6’b011.111转化为10进制如下:

  $6′b011.111=1∗2^1+1∗2^0+1∗2^{−1}+1∗2^{−2}+1∗2^{−3}=3.875$

  而4Q2格式的数据能表示的数据的最大值为4’b01.11,转化为10进制为1.75,因此4Q2格式的数据根本无法准确的存放3.875这个数据,这样就是所谓的饱和情况。在这种情况下,饱和处理就是把超过了1.75的所有数据全部用1.75来表示,也就是说,6Q3的数据为6’b011.111如果非要用4Q2格式的数据来存储的话,在进行饱和处理的情况下最终的存储结果为:4’b01.11。

  例2:有一个6Q3的数据为6’b100.111,现在要求用4Q2格式的数据去存储它,显然6’b100.111转化为10进制如下:

     $6′b100.111=−1∗2^2+0∗2^1+0∗2^0+1∗2^{−1}+1∗2^{−2}+1∗2^{−3}=−4+0.5+0.25+0.125=−3.125$

  而4Q2格式的数据能表示的数据的最小值为4’b10.00,转化为10进制为-2,因此4Q2格式的数据根本无法准确的存放-3.125这个数据,这是另一种饱和情况。在这种情况下,饱和处理就是把小于-2的所有数据全部用-2来表示,也就是说,6Q3的数据为6’b100.111如果非要用4Q2格式的数据来存储的话,在进行饱和处理的情况下最终的存储结果为:4’b10.00。

1.8 数据溢出

这样两个有/无符号数进行加减运算时,如果运算结果超出可表示的数值范围,会发生出错,产生溢出现象。有溢出不一定有进位、有进位不一定有溢出

有符号加法和无符号加法在运算时硬件电路是一样的,只是对结果的解读不同.

 4-bit运算时

溢出的检查方法

“最高位的进位输入”不等于“最高位的进位输出”,说明产生了溢出。

经过一个异或门,如果C31和Cout 不相等,overflow被设为1,表示溢出。

溢出只能出现在两个同号数相加和两个异号数相减的情况下。通常判别溢出的方法用双高位法:

所谓双高位判别,即规定符号位(用CS表示)有进位时,CS=1,否则 CS=0。数值部分最高位(CP表示)有进位时CP=1,否则 CS=0。若CS⊕CP=1("异或"运算),则有溢出产生。