DSP晶片的定點運算
在定點
DSP晶片中,採用
定點數進行數值運算,其運算元一般採用整型數來表示。一個整型數的最大表示範圍取決於DSP晶片所給定的字長,一般為16位或24位。顯然,字長越長,所能表示的數的範圍越大,
精度也越高。如無特別說明,本書均以16位字長為例。 DSP晶片的數以2的
補碼形式表示。每個16位數用一個符號位來表示數的正負,0表示數值為正,1則表示數值為負。其餘15位表示數值的大小。因此
二進制數0010000000000011b=8195 二進制數1111111111111100b=-4 對DSP晶片而言,參與數值運算的數就是16位的整型數。但在許多情況下,數學運算過程中的數不一定都是整數。那么,DSP晶片是如何處理
小數的呢?應該說,DSP晶片本身無能為力。那么是不是說DSP晶片就不能處理各種
小數呢?當然不是。這其中的關鍵就是由程式設計師來確定一個數的
小數點處於16位中的哪一位。這就是數的定標。 通過設定小數點在16位數中的不同位置,就可以表示不同大小和不同
精度的小數了。數的定標有Q表示法和S表示法兩種。表3.1列出了一個16位數的16種Q表示、S表示及它們所能表示的
十進制數值範圍。 從表3.1可以看出,同樣一個16位數,若小數點設定的位置不同,它所表示的數也就不同。例如: 16
進制數2000H=8192,用Q0表示 16進制數2000H=0.25,用Q15表示 但對於DSP晶片來說,處理方法是完全相同的。 從表3.1還可以看出,不同的Q所表示的數不僅範圍不同,而且
精度也不相同。Q越大,數值範圍越小,但
精度越高;相反,Q越小,數值範圍越大,但精度就越低。例如,Q0的數值範圍是-32768到+32767,其
精度為1,而Q15的數值範圍為-1到0.9999695,精度為 1/32768 = 0.00003051。因此,對
定點數而言,數值範圍與
精度是一對矛盾,一個變數要想能夠表示比較大的數值範圍,必須以犧牲精度為代價;而想提高精度,則數的表示範圍就相應地減小。在實際的定點
算法中,為了達到最佳的性能,必須充分考慮到這一點。
浮點數與
定點數的轉換關係可表示為:
浮點數(x)轉換為
定點數( ): 定點數( )轉換為浮點數(x): 例如,浮點數 x=0.5,定標 Q=15,則定點數 = ,式中 表示下取整。反之,一個用 Q=15 表示的
定點數16384,其
浮點數為16384×2-15 =16384/32768=0.5。
從浮點到定點
在編寫DSP模擬算法時,為了方便,一般都是採用
高級語言(如C語言)來編寫模擬程式。程式中所用的變數一般既有整型數,又有
浮點數。如例3.1程式中的變數i是整型數,而pi是
浮點數,hamwindow則是浮點數組。
例3.1256點漢明窗計算
inti;
floatpi=3.14159;
floathamwindow[256];
for(i=0;iQy,
加法/
減法結果z的定標值為Qz,則
z=x+yÞ
=
=Þ
intx,y,z;
longtemp;
temp=y>(Qx-Qz)),若Qx≥Qz
z=(int)(temp>2)=29491;
因為z的Q值為13,所以定點值z=29491即為
浮點值z=29491/8192=3.6。
例3.3定點減法
設x=3.0,y=3.1,則浮點運算結果為z=x-y=3.0-3.1=-0.1;
Qx=13,Qy=13,Qz=15,則定點減法為:
x=24576;y=25295;
temp=25395;
temp=x-temp=24576-25395=-819;
因為QxQy,
加法結果z的定標值為Qz,則定點加法為:
intx,y;
longtemp,z;
temp=y>(Qx-Qz),若Qx≥Qz
z=temp32767,因此
x=30000;y=20000;
temp=20000>1=35000;
因為z的Q值為0,所以定點值z=35000就是浮點值,這裡z是一個長整型數。
當加法或加法的結果超過16位表示範圍時,如果程式設計師事先能夠了解到這種情況,並且需要保證運算
精度時,則必須保持32位結果。如果程式中是按照16
位數進行運算的,則超過16位實際上就是出現了溢出。如果不採取適當的措施,則數據溢出會導致運算精度的嚴重惡化。一般的定點DSP晶片都設有溢出保護功能,當溢出保護功能有效時,一旦出現溢出,則累加器ACC的結果為最大的飽和值(
上溢為7FFFH,
下溢為8001H),從而達到防止溢出引起
精度嚴重惡化的目的。
3.2.2乘法運算的C語言定點模擬
floatx,y,z;
z=xy;
假設經過統計後x的定標值為Qx,y的定標值為Qy,乘積z的定標值為Qz,則
z=xyÞ
=Þ
=
所以定點表示的乘法為:
intx,y,z;
longtemp;
temp=(long)x;
z=(temp×y)>>(Qx+Qy-Qz);
例3.5定點乘法
設x=18.4,y=36.8,則
浮點運算值為z=18.4×36.8=677.12;
根據上節,得Qx=10,Qy=9,Qz=5,所以
x=18841;y=18841;
temp=18841L;
z=(18841L*18841)>>(10+9-5)=354983281L>>14=21666;
因為z的定標值為5,故定點z=21666即為浮點的z=21666/32=677.08。
floatx,y,z;
z=x/y;
假設經過統計後
被除數x的定標值為Qx,除數y的定標值為Qy,商z的定標值為Qz,則
z=x/yÞ
=Þ
所以定點表示的除法為:
intx,y,z;
longtemp;
temp=(long)x;
z=(temp
constintlength=180
voidfilter(intxin[],intxout[],intn,floath[]);
staticfloath[19]=
{0.01218354,-0.009012882,-0.02881839,-0.04743239,-0.04584568,
-0.008692503,0.06446265,0.1544655,0.2289794,0.257883,
0.2289794,0.1544655,0.06446265,-0.008692503,-0.04584568,
-0.04743239,-0.02881839,-0.009012882,0.01218354};
staticintx1[length+20];
voidfilter(intxin[],intxout[],intn,floath[])
{
inti,j;
floatsum;
for(i=0;i
constintlength=180;
voidfilter(intxin[],intxout[],intn,inth[]);
staticinth[19]={399,-296,-945,-1555,-1503,-285,2112,5061,7503,8450,
7503,5061,2112,-285,-1503,-1555,-945,-296,399};
staticintx1[length+20];
voidfilter(intxin[],intxout[],intn,inth[])
{
inti,j;
longsum;
for(i=0;i>15;
}
for(i=0;i<(n-1);i++)x1[n-i-2]=xin[length-i-1];
}
主程式與浮點的完全一樣。