原创
定点
2009-1-7 16:33
2343
6
6
分类:
处理器与DSP
DSP广义上指数字信号处理理论(Digital Signal Processing),狭义上指数字
信号处理器(Digital Signal Processor)。数字信号处理理论广泛应用于语音、图象、
遥测数据、电机控制等各个方面。现代个人通信、互联网、多媒体应用的飞速发展又推
动着数字信号处理理论的进一步发展。现代信号处理(ASP)算法越来越复杂,处理的数
据量越来越庞大。由于体系结构的限制,通用微处理器并不适合作这种高运算量的信号
处理,由此诞生了一种专门用于信号处理的芯片和系统,这就是数字信号处理器,通常
简称DSP。作为数字信号处理理论和当代大规模集成电路VLSI技术融合的结晶,数字信号
处理器(DSP)正日益广泛地应用于通信、消费类电子产品、仪器仪表、航天航空等各个
领域。在数字化浪潮的推动下,基于DSP的软硬件开发需求越来越大。国际上各大DSP芯
片制造厂商也不断推出运算速度更快、功耗更低的产品。
1. 定点DSP和浮点DSP
国际上生产DSP芯片的厂商很多,典型的有TI、AD、Motorola、DSP Group以及
AT&T、NEC等等,这些公司都有自己的由低档到高档的DSP产品系列。其中TI--德州仪器
公司占有主导地位,其产品占了45%的市场份额。 AD--模拟器件公司紧随其后,其产品
约占11%的市场份额。TI公司的TMS320系列和AD公司的ADSP系列在中国使用的也最为广泛
。表1列出了常见的两家公司的主要产品。
表1
公司 DSP芯片 定点/浮点 时钟频率(MHz)
TI TMS320C2xxx 定点 20-40
TMS320C3x 浮点 33-75
TMS320C54xx 定点 40-160
TMS320C55xx 定点 160-200
TMS320C62xx 定点 150-300
TMS320C67xx 浮点 100-167
AD ADSP-21xx 定点 10-80
ADSP-21xxx(SHARC) 浮点 33-100
TigerSHARC 浮点 250
从表1可以看出,两家公司都有各自的定点产品和浮点产品。数据以定点格式工
作的DSP芯片称为定点DSP,数据以浮点格式工作的DSP称为浮点DSP。浮点DSP表示数据的
精度高,编程也比较容易,从高级语言转化为适合浮点DSP的汇编语言要方便。但是,由
于DSP大量用于嵌入式系统,很多应用场合如手机、PDA、便携式音频播放器等等,
都要求价格低廉,功耗尽量低。而浮点DSP由于内部结构较复杂,价格、功耗都不易降下
来,因此其应用反而不如定点DSP普遍。DSP芯片厂商推出的定点DSP种类也比浮点DSP种
类多,这在表1中也有体现。
定点DSP的字宽一般为16位,也有24位和20位的DSP,如摩 托罗拉的DSP563XX系
列和Zoran公司的 ZR3800X系列。显然数据字长越大单字表示的范围越大,精度越高,但
TI和AD目前的产品都是16位字长。
2. C语言在DSP开发中的应用[1][3]
为缩短软件开发周期,使用C语言开发DSP产品越来越普遍。使用汇编语言可以
充分利用DSP片内资源编出精简高效的代码。但是DSP汇编语言编程较繁杂,可读性差。
而且,一般来说,不同公司的芯片汇编语言是不同的,即使是同一家公司的芯片,由于
芯片类型不同(如定点和浮点),产品的升级换代,其汇编语言也不相同,这使得汇编
语言的可移植性也较差。所以用汇编语言开发基于DSP芯片的产品周期长,软件的修改和
升级都较困难。C语言既有高级语言的易学易懂、功能丰富、表达能力强、可移植性好的
优势,又具有低级语言的特点(比如能方便地进行位运算、地址操作)。正因为如此,
各DSP芯片厂商也都提供了相应的C优化编译器,并不断提高其编译效率,鼓励DSP开发者
选用C语言作为开发DSP应用程序的首选工具。事实上,对于有些多内核、并行化程度非
常高的DSP处理器,如TI的TMS320C62xx,完全由人手编写汇编代码反而很难有效地分配
运行资源、发挥处理器并行处理的优势。当然,现在的C编译器效率仍然不是很高,DSP
片内片外资源也有限,很多地方仍然要作人工优化。
通常DSP的开发流程如图1所示,详细过程如下:
(1) 用C语言编写程序,在PC机上仿真测设,确保算法正确。尽管现在DSP厂商推出的
调试工具越来越方便,用户界面越来越友善,但比起PC编程仍然要麻烦得多。确保算法
在PC机上仿真通过,以后调试DSP汇编程序时就有一个参考,这样会方便很多。一般采用
文件的形式来仿真DSP程序的输入输出。
(2) 按照DSP的C程序编写规则改写C程序,使之适合DSP硬件。将文件读写改为真正的
I/O操作。加入中断功能。必要时在C程序中嵌入汇编语句。
(3)使用C编译器编译改写的C程序,生成DSP汇编源代码。C编译器具有优化选项,根据
需要选择不同的优化等级和优化范围。
(4)手动进行程序优化,降低程序代码大小,使流程更合理,进一步加快程序的执行速
度。评估程序能否在实际的DSP处理器上实时运行。如果不行,人工编写指令周期密集的
那些模块的汇编代码,直到满足实时要求。
(5)使用汇编器将各模块汇编成目标文件。
(6)最后将各目标文件链接成可载入DSP中联机运行调试的可执行代码。
3. DSP定点算法的C语言仿真[2]
DSP开发过程的第一步是在PC机上编写C仿真程序,确保算法正确,这样可以大
大节省以后在DSP上调试的时间。对于浮点算法,使用C语言加以实现是十分方便的,编
程者只需具备C编程的知识,甚至可以完全不懂DSP。常见的数字信号处理算法也都是以
浮点形式出现。但是由于定点DSP受数值表示范围的限制,用C语言仿真定点算法或将浮
点算法定点化则要复杂的多,需要了解一些定点DSP芯片硬件操作的知识,掌握一些规则
和技巧。下面就从定点DSP数值表达、常用运算来讲述如何用C语言实现DSP定点算法的仿
真。这里假定处理器是16位的定点DSP,乘法器、累加器为32位。仿真C程序使用TURBO
C编译器,那么在C程序中可用的变量只有单精度整型int (16位)和 双精度长整型lon
g(32位)两种形式。
3.1浮点数的定点化
3.1.1 Q格式--固定小数点的表达方式[1]
定点DSP芯片中的基本单元是16位(比特)字。当表示纯整数时其范围为-3276
8到+32767,分别对应的二进制表示为1000 0000 0000 0000和0111 1111 1111 1111。处
理器中都是采用补码形式,最左面的一位即第15位是最高有效位(MSB),最右面的一位即
第0位是最低有效位(LSB)。MSB作符号位,如果一个数是正数,MSB为0,若为负数,MSB
为1。
当要表示小数时,必须假定一个小数点位于相邻两比特之间。比如,要表示一
个-1.0到+1.0之间的小数,我们可以假定小数点位于第14位和第15位之间。这种表达方
式称为Q15格式,因为小数点右边有15位。如果小数点右边有n位就称为Qn格式。纯整数
是一种特殊的Q0格式的小数。
将浮点算法转化为定点算法,首先就要把所有的小数经定标转化为整数。比如
浮点算法中有一个浮点数组为[ 0.25 0.5 1.125 5.75 7.0 ],用二进制表示为[
0.01 0.1 1.001 101.11 111.0 ]。将数组各分量左移三位,得[ 10 100 1001
101110 111000 ],十进制表示为[ 2 4 9 46 56 ]。小数点位置在第3位,此数组
中的各分量都是Q3格式,这就是定标的过程。
浮点数和定点数的转换公式如下:
浮点数(x)转换为定点数(xq):xq=(int)x * 2Q
定点数( xq)转换为浮点数(x):x=(float) xq * 2-Q
不同的Q格式所表示的数的范围不同,精度也不同。Q越大,数值范围越小,但精
度越高。例如,Q0的数值范围是-32768到+32768,其精度是1,而Q15的数值范围为-1到
0.9999695,精度为1/32768=0.00003051。对于定点数而言,数据范围和精度是一对矛盾
。
3.1.2 定标浮点数--动态小数点的表达方式
固定小数点的方式只适用于表达动态范围较小的浮点数变量,对于那些动态变
化比较大的浮点数变量采取固定小数点的表达方式,往往可能造成溢出或者精度太低。
浮点数定点化的关键是要保证精度,而与精度有直接关系的是有效数字的位数
,与小数点的位置无关。可见,只要保证了浮点数表达的有效位数为16比特定点可以表达
的最大位数,就等于保证了浮点数定点化的最大精度。因此,可以将一个浮点数用两个
16比特字来表达。第一个字表示尾数(M), 采用补码形式,其幅度值在16384~32767之
间, MSB位是符号位。尾数是对浮点数进行归一化后的有效数字,对于16比特定点数来
说,这是最大的表示精度。第二个字是指数NLS,表示为归一化而对浮点数进行的左移位
数,NLS可正可负,同样采用补码形式。这种32位单精度的浮点数表示方法一般称为定标
浮点数( scaler floating point )。定标浮点数的大小等于M*2NLS,大大扩展了定点数
的精度和范围,特别适合于动态范围比较大或者动态范围不太好预测的变量。如何将一
个浮点数用定标浮点数来表示,主要是一个归一化的过程,后面3.2.5中有详细介绍。
3.1.3 块浮点数--块表达方式
动态小数点位置的表达方式的缺点是需要多一倍的存储空间来表示浮点数。特
别是对于数组来说,这是很大的开销。而块表达方式正好解决了这一问题,同时又具有
动态小数点表达方式的优点。
块表达方式使用n+1个字来表示一个n维数组。数组中幅度最大的一个元素采用
动态小数点表达方式,即由归一化值表示有效数字,另外用一个NLS变量表示小数点位置
。数组中其他分量则共享此NLS值。可见,块浮点数( block floating point )的表达方
式效率是很高的,特别是对于那些比较长的数组变量。
以上介绍的三种浮点数表达方式各有自己的优缺点,到底采用何种方式视浮点
数的动态范围和其对算法精度的影响程度而定。固定小数点的表达方式简单,使用的也
最多。当对算法的精度要求比较高,动态范围又比较大的时候,可以采用定标浮点数。
如果是数组,且各分量之间相关性较强、大小接近,则可以使用块浮点数。定标浮点数
和块浮点数的缺点是需要占用额外的存储空间,并且每经过一次变化后就要进行一次归
一化,势必造成运算量成倍的增加和耗费更多的存储空间。
在保证精度的同时,还要考虑这些表达方式可能在运算中带来的溢出问题。数
字信号处理算法中常用到乘加的累积,比如求卷积和FIR滤波,如果采用最大精度表示,
往往带来累加器溢出造成的麻烦。因此,与卷积和FIR滤波相关的变量,一般不用16bit
精度表示,而是根据乘加运算的次数使用15bit或者14bit精度表示。
3.2 基本定点算法
3.2.1 移位运算
在定点DSP芯片中经常用到移位操作。C语言提供了移位操作符,左移为<<,右
移为>>。左移运算符用来将一个数的各二进位左移若干位,操作如下
a<<=n;将a的二进制数左移n位,右补0。高位左移后溢出,舍弃不起作用
。
在没有溢出的前提下,左移n位相当于该数乘以2n。同理,a>>n表示将a的各二
进位右移n位。移到右端的低位被舍弃。TURBO C编译器采用算术右移,最左边移入符号
位,当a为正数,左边移入的是0,若为负数,左边移入的是1。当a为正数,a>>n相当于
a/2n,若为负数则未必。例如:
a=7>>2; 结果a=1
a=7/4; 结果a=1
但是,
a=-7>>2 ; 结果a=-2
a=-7/4; 结果a=-1
作移位操作时,如果移位次数n是个变量,必须保证n>=0,否则会产生预料不到
的错误。如果n正负难以预测,可先作正负判断再右移或左移。例如要将a右移n位,可作
如下处理:
if ( n>=0)
a>>=n;
else
a<<=-n;
如果一个数左移后超出了int的表示范围[-32768,32767],可以用一个long类型
的数据来保存结果。例如32000<<1的正确结果应该是64000,大于32767,移位结果不能
用int类型来表达。可作如下处理:
long a;
a=(long)32000<<1; 结果a等于64000
注意下面的语句将产生错误的结果:
long a;
a=32000<<1; 结果a等于-1536。
3.2.2 加减运算
将浮点加减法转化为定点加减法最重要的一点是必须保证两个操作数的小数点的
位置要相同。如果不同,在作加减法运算前必须先进行小数点的调整。为保证运算精度
,一般是将Q值小的数的Q格式调整为与另一个数的Q值一样大。如果是定标浮点数,则N
LS大的数必须先向右移位,达到与另一个数相同的NLS值后才能相加。DSP芯片一般在累
加器中作加减法,累加器至少为32位。在C语言程序中,如果加减的结果可能超出int的
表示范围,注意要用双精度long类型表示结果。
例1 求x+y的值z。x、y、z是变量,对应的Q格式分别为Qm、Qn、Qk,Qm<Qn。
算法描述如下:
int x,y;
long z;
…………..
z=(long)x<<(n-m)
z+=y; z为32位长整型数,Q格式为Qn
例2 求x+y的值z。x、y、z都是定标浮点数,对应的NLS值分别是NLSx、NLSy、NL
Sz。NLSx>NLSy。
算法描述如下:
int x,NLSx,y,NLSy,z,NLSz; long temp;
……………………………
temp=x>>(NLSx-NLSy);
temp+=y;
这里,如果x和y符号相同,temp可能需要17bit来表达,那么将它右移1位恢复
成16bit再赋给z,NLSz等于NLSy-1。反之,如果x和y符号不同,temp的绝对值可能小于
16384,则要将它左移重新进行归一化,直到绝对值大于或等于16384,而NLSz为NLSy加
上移位的次数。
3.2.3 乘法运算
两个16位整数相乘其结果是32位的数,所以要用双精度数即long类型的长整型
数来保存乘法结果。
例1 求xy的值z。x、y、z是变量,x、y对应的Q格式分别为Qm、Qn。算法描述如下:
int x,y; long z;
…………..
z=(long)x*y;
乘积结果z为双精度Q(m+n)形式。这里注意要先将x强制转换为long类型,否则
得到的仍然是一个单精度int类型的乘积,很容易因为溢出产生错误的结果,就像下面的
例子。
例2
int x; long z;
x=32000;
z=x*2; 结果z并不等于64000,而是等于-1536。
大多情况下,我们要将乘积z保存在一个16位的内存单元中,比如将它置回一个
Qk格式的单精度变量result中,必须首先将双精度乘积左移16+k-(m+n)位,然后进行舍
入,将双精度的高位字存 入16bit的整型变量中。舍入操作是考察双精度数低位字的MS
B是否为1,如果为1,则向高位字进位1。整个过程如下:
int x,y,result; long z;
……………………….
z=(long)x*y; 乘法
z=z<<16+k-(m+n); 左移16+k-(m+n)位
result=(z+0x8000)>>16; 舍入后高位字存到result
3.2.4 除法运算[4]
DSP芯片不善于作除法运算。一般DSP处理器中没有专门的除法硬件电路,它是
靠一系列的移位减来完成除法运算,需耗费很多指令周期。因此,在定点DSP算法中应该
尽量避免作除法。很多时候除法可以用乘法来代替,即乘以除数的倒数。
在DSP上作除法通常由一段程序来完成,每个DSP厂商都会在应用指南中给出除法
的例程,包括有符号数相除、无符号数相除以及16位与16位相除、32位与16位相除的例
程。在C仿真程序中可以用"/"运算符来作除法,没必要编写一个专门的除法函数。
例 求x/y的值z,x是Qm格式,y是Qn格式。C语言描述如下:
int x,y,z;
………..
z=x/y; z的Q格式是Q(m-n)。
3.2.5归一化与矢量定标
通常对定标浮点数每做一次变化都要重新进行归一化,归一化是为了使其尾数的
绝对值在16384~32767之间,从而保证最大的精度。有的DSP处理器提供归一化的指令,
能在单指令周期内完成累加器中数值的归一化。在C语言中需要编写一小段程序来模拟,
算法如下:
x的Q格式为Qn,x为long类型或int类型。现在要将x归一化转换为定标浮点数,
用两个整型数X和NLSX来表达。
#define MAX 32767
#define MIN 16384
int shift=0;计算移位次数
long temp; 临时变量
………………………….
temp=x;
if ( temp<0 ) temp=-temp; 取绝对值
while ( temp>MAX )
{
temp>>=1; 右移一位
shift--;
}
while ( temp<MIN )
{
temp<<=1; 左移一位
shift++;
}
if ( shift<=0 ) X=x>>-shift;
else X=x<<shift;
NLSX=n+shift;
定标浮点数的尾数采用16bit的最大精度。前面已经提到,为了防止运算溢出造成
麻烦,也可以降低一些精度,比如可以采用15bit或14bit来表示。这种修正的定标浮点
数的归一化过程仍然可以采用上面的算法,只是MIN和MAX值要作变动。假定采用MLS位精
度,则MIN=2(MLS-2) ,MAX=2(MLS-1) -1。
块浮点数每做一次变化通常也要重新进行归一化即矢量定标。过程如下:
1) 找出尾数数组中幅度最大的分量。
2) 对该分量归一化,求出移位次数shift。
3) 对所有分量均作同样的移位。
4) 原来NLS值加上shift得到新的NLS值。
3.2.6 溢出与饱和模式
相对浮点DSP处理器,经常出现溢出可能是定点DSP的一大特征。溢出是数字信号
处理算法定点化过程中要特别注意的一个问题。
两个16bit的乘积是32bit的数,DSP算法常用的卷积和FIR滤波都要用到乘加运算
,经过多次乘加后其结果可能超出32bit能表示的最大范围,这就是溢出的现象。溢出会
使一个很大的正数变成一个很小的负数,或者将一个很小的负数变成一个很大的正数,
使结果产生非常大的误差。因此,判断溢出并且采取适当的保护措施很有必要。
一种有效的办法是采用饱和模式,当运算结果要溢出时就限定在临界值。对于32bit
数,表示的范围是-231~231-1。-2147483648是下临界,2147483647是上临界。一般的
DSP处理器都可以工作在饱和模式下,减小溢出造成的不利影响。在C语言中模拟饱和模
式则要麻烦一些。
例 求x*y<<2的值z。
Int x,y; long z;
Float temp;
…………………
temp=1.0*x*y*4; 1.0起的作用是为了将乘积强制转换为浮点格式。
;左移2位相当于乘以4。
if ( temp> 2147483647) z=2147483647;上溢出
else
if ( temp<-2147483648 ) z=-2147483648; 下溢出
else z=(long)x*y;
这里引入float单精度浮点数是为了扩大数值的表示大小。在IBM PC机上,C语言中单
精度实数的数值范围约为10-38~1038。
文章评论(0条评论)
登录后参与讨论