在定点DSP芯片中,采用定点数进行数值运算,其操作数一般采用整型数来表示。一个整型数的最大表示范围取决于DSP芯片所给定的字长,Blackfin DSP的字长为16位。显然,字长越长,所能表示的数的范围越大,精度也越高。本章将以 16 位字长为例进行介绍。
定点DSP芯片的操作数以2的补码形式表示。每个16位数用一个符号位来表示数的正负(0表示数值为正,1则表示数值为负),其余15位表示数值的大小。因此,有
二进制数0010000000000011b=8195
二进制数1111111111111100b=– 4
对于定点DSP芯片而言,参与数值运算的数就是16位的整型数。但在许多情况下,数学运算过程中的数不一定都是整数。那么,如何让定点DSP芯片处理小数呢?这其中的关键就是由程序员来确定一个数的“小数点”处于16位中的哪一位,这就是数的定标。
通过设定“小数点”在16位数中的不同位置,就可以表示不同大小和不同精度的小数了。数的定标通常采用的是Q表示法。表3-1列出了一个16位有符号数的16种Q表示、精度及它们所能表示的十进制数值范围。必须指出的是,这里所说的“小数点”是一个隐式的小数点,对定点 DSP 芯片而言,参与运算的就是 16 位的整型数,并不存在真正意义上的小数点。
表3-1 Q表示、精度及十进制数值范围
一个16位有符号数,最左边的一位是符号位,其余15位包括整数位和小数位。对于Q表示法而言,Q后面的数表示该数的小数点右边有几位,如Q15表示该数的小数点右边有15位,即有15位小数,没有整数位;Q10表示该数的小数点右边有10位,即有10位小数和5位整数位。
从表3-1可以看出,同样一个16位数,若小数点设定的位置不同,它所表示的数也就不同。
例如:
十六进制数2000H=8192,用Q0表示;
十六进制数2000H=0.25,用Q15表示。
但对于定点DSP芯片来说,处理方法是完全相同的。
从表3-1还可以看出,不同的Q所表示的数不仅范围不同,而且精度也不相同。Q越大,表示的数值范围越小,但精度越高(量化步长越小);相反,Q 越小,表示的数值范围越大,但精度就越低(量化步长越大)。不同Q值所对应的正最大值、负最大值和量化步长表示如下。
正最大值:
负最大值:
精度:
例如,Q0的数值范围是– 32768~+32767,其精度为1;而Q15的数值范围为–1~0.9999695,精度为 1/32768 = 0.00003051。显然,对定点数而言,数值表示范围与精度是一对矛盾,一个变量要想能够表示比较大的数值范围,必须以牺牲精度为代价;而要想精度提高,则数的表示范围就相应地减小。在实际的定点算法中,为了达到最佳的性能,必须充分考虑到这一点。
除了上述的Q 表示法外,也可以直接用小数点左右的位数来表示,如1.15 表示该数的小数点左边有1位,而小数点右边有15位。
1.浮点数与定点数之间的转换
浮点数与定点数的转换关系简介如下:
浮点数(x)转换为定点数( x q )
定点数( x q )转换为浮点数(x):
例如,浮点数x=0.6,定标Q=15,则定点数 ,式中的 表示下取整。反之,一个用 Q=15 表示的定点数 19660,转换为浮点数是 19660×2 - 15 =19660/32768=0.599975585,显然,用定点数来表示0.6这个数存在一定的误差。
为了最大限度地保持数的精度,在将浮点数转换为定点数时,可以采取“四舍五入”的方法,即在取整运算前,先加上0.5。
浮点数(x)转换为定点数( x q ):
同样,对于0.6这个数,采用上述方法转换得到的定点数将为 , 其浮点数为 ,显然其精度得到了提高。
2.定点二进制数转换为十进制数
对于一个给定Q值的二进制数,确定该数的等值十进制数大小有以下两种方法。
1)先求整型数,然后利用式(3-2)进行计算
首先将该数视为一个整型数,计算该整型数的等值十进制数值,然后利用式(3-2)求该数。例如,设一个Q=15的二进制有符号数为0100110011001100,由于左边第一位是符号位且为0,所以它是一个正数,则其对应的十进制整型数值为
因此,该数的等值十进制数为
2)根据Q值,确定小数点位置,然后进行计算
根据Q值确定小数点的位置,然后以小数点为中心,依次向左向右得到每一位的权值大小,具体如下:
依次向左,各位的权值大小分别为2 0 ,2 1 ,2 2 ,2 3 ,…符号位除外;
依次向右,各位的权值大小分别为2 -1 ,2 -2 ,2 -3 ,2 -4 ,…。
仍以二进制有符号数0100110011001100为例,若Q=15,则该数相当于0.100110011001100,即隐含的小数点在符号位之后。由于该数的符号位为0,所以它是一个正数,其等值十进制数大小为
同样的二进制有符号数,若Q=14,则该数相当于01.00110011001100,其等值十进制数大小为
需要注意的是,如果一个二进制数是负数,则首先应将它转换为无符号的二进制格式,然后利用上述方法进行计算。
由于定点数的表示范围是一定的,所以在进行定点数的加法、减法、移位等操作时,其结果就有可能出现超过数值表示范围的情况,这种现象称为溢出。在进行定点运算时,必须考虑溢出的处理方法。因为如果忽视溢出情况,就有可能导致灾难性的后果。
例如,设有两个16位有符号数x和y相加,结果也用16位有符号数表示,则
显然,x与y相加的结果应该是32769,但由于已经超过了表示范围,所以在不采取溢出保护措施的情况下,其结果变成了–32767。
为了避免这种情况的发生,一般在DSP芯片中可以设置溢出保护功能。设置溢出保护功能后,当发生溢出时,DSP芯片自动将结果饱和设置为正最大值或负最大值。如果设置了溢出保护功能,则上述加法的结果为+32767,从而避免发生从+32769 变到–32767 的灾难性后果。
对于Blackfin DSP,根据寄存器字长的不同,其溢出保护值也不同。对于16位寄存器,其正最大值为 0X7FFF,负最大值为0X8000;对于32位寄存器,其正最大值为 0X7FFF FFFF,负最大值为0X8000 0000;对于40位寄存器,其正最大值为 0X7F FFFF FFFF,负最大值为0X80 0000 0000。
例如,对于一个包含 0X1000(+4096)的 16 位寄存器,如果不设置溢出保护,则左移3位后得到的值是0X8000(- 32768);如果设置了溢出保护,则左移3位后得到的是16位的最大正值0X7FFF(+32767)。
在BlackfinDSP中,可通过指令来设置是否进行溢出保护。例如:
当一个字长小的数放到一个字长大的累加器中进行运算时,必须注意数的符号问题。先来看下面的一个例子。
一个用4位表示的数x,设x为1011,即为十进制数-5,如果将它直接放到一个已经清0的8位字长累加器的低4位(符号不扩展),则得到00001011,显然它表示+11,不是- 5。如果在装载时进行符号扩展,即将累加器的高四位根据所存放数据的符号进行填充,则得到11111011,该数表示的数值为正确数- 5。
在DSP芯片中进行二进制补码的运算时,通常参与运算的数为16位,而DSP累加器为 32 位,因此,为了使运算能够得到正确的结果,需要把数的符号位扩展到累加器左边的高位。这就是DSP芯片中的符号扩展模式。
在Blackfin DSP中,可通过指令来设置是否进行符号扩展。例如:
下面以取整运算来说明舍入(rounding)及截尾(truncating)的概念。
对一个数x进行取整处理,一般有以下两种处理方法:
(1)直接将小数部分去除,这就是截尾处理方法,也称下取整;
(2)将该数加 0.5,之后再将小数部分去除,这就是舍入处理方法,即通常所说的四舍五入。这种处理方法也称上取整;
【例3.1】 已知x=123.3,y=123.7,试分别对x、y进行舍入和截尾处理。
对x进行舍入:round(x)=round(123.3)=trunc(123.3+0.5)=123;
对x进行截尾:trunc(x)=trunc(123.3)=123;
对y进行舍入:round(y)=round(123.7)=trunc(123.7+0.5)=124;
对y进行截尾:trunc(y)=trunc(123.7)=123。
从上述的例子可以看出,由于数 x 的小数部分为 0.3,所以采用舍入运算后得到的结果与截尾运算结果相同。而数 y 的小数部分为 0.7,则采用舍入运算后得到的结果与截尾运算结果不同,数值精度要高一些。
对于DSP芯片的乘法运算,常需要用到舍入处理方法。下面举例予以说明。
设两个Q值均为15的16位有符号数x和y进行乘法运算,结果也采用Q15表示的16位数。这里将一般的运算过程描述如下。
(1)x与y相乘,结果放在32位累加器中。由于x与y的Q值均为15,所以,此时累加器中的结果为32位,Q值为30。
(2)将累加器的数左移一位,此时累加器中数的Q值变为31。
(3)为了将结果表示为16位,一种方法是直接将低16位截尾,保留高16位,作为乘法结果;另一种方法就是在截尾之前进行舍入处理,即在低16位数的最高位加1(相当于加32768),然后将低16位去除,将高16位作为乘法结果。
显然,进行舍入运算后,能够最大程度地保持16位结果的精度。