Q格式運(yùn)算講解學(xué)習(xí)
發(fā)布時(shí)間:2020-10-05 來源: 演講稿 點(diǎn)擊:
·37·
第3章 DSP 芯片的定點(diǎn)運(yùn)算
3.1 數(shù) 的 定 標(biāo) 在定點(diǎn) DSP芯片中,采用定點(diǎn)數(shù)進(jìn)行數(shù)值運(yùn)算,其操作數(shù)一般采用整型數(shù)來表示。一 個(gè)整型數(shù)的最大表示范圍取決于 DSP芯片所給定的字長,一般為 16位或 24位。顯然,字長越長,所能表示的數(shù)的范圍越大,精度也越高。如無特別說明,本書均以 16位字長為例。
DSP芯片的數(shù)以 2的補(bǔ)碼形式表示。每個(gè) 16位數(shù)用一個(gè)符號(hào)位來表示數(shù)的正負(fù), 0表示數(shù)值為正,
1則表示數(shù)值為負(fù)。其余 15位表示數(shù)值的大小。因此 二進(jìn)制數(shù) 0010000000000011b = 8195 二進(jìn)制數(shù) 1111111111111100b = - 4 對(duì) DSP 芯片而言,參與數(shù)值運(yùn)算的數(shù)就是 16 位的整型數(shù)。但在許多情況下,數(shù)學(xué)運(yùn)算 過程中的數(shù)不一定都是整數(shù)。那么, DSP芯片是如何處理小數(shù)的呢?應(yīng)該說, DSP芯片本身無能為力。那么是不是說 DSP芯片就不能處理各種小數(shù)呢?當(dāng)然不是。這其中的關(guān)鍵就 是由程序員來確定一個(gè)數(shù)的小數(shù)點(diǎn)處于 16位中的哪一位。這就是數(shù)的定標(biāo)。
通過設(shè)定小數(shù)點(diǎn)在 16位數(shù)中的不同位置,就可以表示不同大小和不同精度的小數(shù)了。
數(shù)的定標(biāo)有 Q表示法和
S表示法兩種。表 3.1列出了一個(gè) 16 位數(shù)的 16種Q表示、 S表示及它們所能表示的十進(jìn)制數(shù)值范圍。
從表 3.1可以看出,同樣一個(gè) 16位數(shù),若小數(shù)點(diǎn)設(shè)定的位置不同,它所表示的數(shù)也就不 同。例如:
16進(jìn)制數(shù) 2000H = 8192,用 Q0表示 16進(jìn)制數(shù) 2000H = 0.25,用 Q15表示 但對(duì)于 DSP芯片來說,處理方法是完全相同的。
從表 3.1還可以看出,不同的 Q所表示的數(shù)不僅范圍不同,而且精度也不相同。
Q越大,數(shù)值范圍越小,但精度越高;相反, Q越小,數(shù)值范圍越大,但精度就越低。例如, Q0的數(shù)值范圍是 - 32768到+32767 ,其精度為 1,而 Q15 的數(shù)值范圍為 - 1 到0.9999695,精度為 1/32768 = 0.00003051 。因此,對(duì)定點(diǎn)數(shù)而言,數(shù)值范圍與精度是一對(duì)矛盾,一個(gè)變量 要想能夠表示比較大的數(shù)值范圍,必須以犧牲精度為代價(jià);而想提高精度,則數(shù)的表示范圍就相應(yīng)地減小。在實(shí)際的定點(diǎn)算法中,為了達(dá)到最佳的性能,必須充分考慮到這一點(diǎn)。
· 38·
。 16384/32768=0.5 。
16384 ,式中 16384 × 2- 15 浮點(diǎn)數(shù)與定點(diǎn)數(shù)的轉(zhuǎn)換關(guān)系可表示為:
浮點(diǎn)數(shù) (x) 轉(zhuǎn)換為定點(diǎn)數(shù) ( x ):
x (int) x q q 2Q 定點(diǎn)數(shù) ( x q
)轉(zhuǎn)換為浮點(diǎn)數(shù) (x) :
x ( float )x q
2 Q 例如,浮 點(diǎn)數(shù) x=0.5 , 定 標(biāo) Q = 15 , 則定 點(diǎn)數(shù) Q= 15 表示的定點(diǎn)數(shù) x q
= 0.5 32768 表示下取整。反之,一個(gè)用 16384 ,其浮點(diǎn)數(shù)為
·39·
表3.1 Q表示、 S表示及數(shù)值范圍 Q表示 S表示 十進(jìn)制數(shù)表示范圍 Q15 S0.15 - 1≤ X≤ 0.9999695 Q14 S1.14 - 2≤ X≤ 1.9999390 Q13 S2.13 - 4≤ X≤ 3.9998779 Q12 S3.12 - 8≤ X≤ 7.9997559 Q11 S4.11 - 16≤ X≤ 15.9995117 Q10 S5.10 - 32≤ X≤ 31.9990234 Q9 S6.9 - 64≤ X≤ 63.9980469 Q8 S7.8 - 128≤ X≤ 127.9960938 Q7 S8.7 - 256≤ X≤ 255.9921875 Q6 S9.6 - 512≤ X≤ 511.9804375 Q5 S10.5 - 1024≤ X ≤ 1023.96875 Q4 S11.4 - 2048≤X ≤ 2047.9375 Q3 S12.3 - 4096≤ X≤ 4095.875 Q2 S13.2 - 8192≤ X≤ 8191.75 Q1 S14.1 - 16384≤ X ≤16383.5 Q0 S15.0 - 32768≤ X ≤ 32767
3.2 高級(jí)語言:從浮點(diǎn)到定點(diǎn) 在編寫
DSP模擬算法時(shí),為了方便,一般都是采用高級(jí)語言
(如 C語言 )來編寫模擬程序。程序中所用的變量一般既有整型數(shù),又有浮點(diǎn)數(shù)。如例 3.1程序中的變量 i是整型數(shù), 而pi是浮點(diǎn)數(shù), hamwindow 則是浮點(diǎn)數(shù)組。
例 3.1 256點(diǎn)漢明窗計(jì)算int
i; float pi=3.14159; float hamwindow[256]; for(i=0;i<256;i++) hamwindow[i]=0.54 - 0.46*cos(2.0*pi*i/255); 如果要將上述程序用某種定點(diǎn) DSP芯片來實(shí)現(xiàn),則需將上述程序改寫為 DSP芯片的匯編語言程序。為了 DSP 程序調(diào)試的方便及模擬定點(diǎn) DSP實(shí)現(xiàn)時(shí)的算法性能,在編寫 DSP匯編程序之前 一般需將高級(jí)語言浮點(diǎn)算法改寫為高級(jí)語言定點(diǎn)算法 。下面討論基本算術(shù)運(yùn)算
· 40·
的定點(diǎn)實(shí)現(xiàn)方法。
3.2.1 加法/減法運(yùn)算的 C語言定點(diǎn)模擬 設(shè)浮點(diǎn)加法運(yùn)算的表達(dá)式為:
float x,y,z;
·41·
q q z=x+y; 將浮點(diǎn)加法 /減法轉(zhuǎn)化為定點(diǎn)加法 /減法時(shí) 最重要的一點(diǎn)就是必須保證兩個(gè)操作數(shù)的定標(biāo)值一
樣。
若兩者不一樣,則在做加法
/減法運(yùn)算前先進(jìn)行小數(shù)點(diǎn)的調(diào)整。為保證運(yùn)算精 度, 需使 Q 值小的數(shù)調(diào)整為與另一個(gè)數(shù)的 Q 值一樣大
。此外,在做加法 /減法運(yùn)算時(shí),必須 注意結(jié)果可能會(huì)超過 16位表示。
如果加法
/減法的結(jié)果超出 16位的表示范圍,則必須保留 32 位結(jié)果,以保證運(yùn)算的精度 。
1. 結(jié)果不超過 16位表示范圍 設(shè) x的Q值為Qx, y的 Q值為 Qy,且Qx>Qy ,加法 / 減法結(jié)果 z的定標(biāo)值為 Qz,則 z= x+y z q
2
Q z
x q
2
Q x
Q y q
2 = x q
2 Q x
y 2(Q x
Q y ) 2 Q x
= [ x q
y q
2(Q x
Q y
) ]
2 Q x
z q [ xq
y 2(Q x
Q y ) ]
2( Qz
Q x )
所以定點(diǎn)加法可以描述為:
int x,y,z; long temp; /* 臨時(shí)變量 */ temp= y<<(Qx - Qy); temp= x+ temp; z= (int)(temp>>(Qx - Qz)), 若Qx≥ Qz z= (int)(temp<<(Qz - Qx)), 若QxQ ≤ z 例 3.2 定點(diǎn)加法 設(shè)x= 0.5, y=3.1,則浮點(diǎn)運(yùn)算結(jié)果為 z= x+y = 0.5+3.1 = 3.6; Qx= 15, Qy=13, Qz= 13,則定點(diǎn)加法為:
x= 16384; y=25395; temp= 25395<<2 = 101580; temp= x+temp = 16384+101580 = y
· 42·
117964; z= (int)(117964L>>2) = 29491; 因?yàn)?z的Q值為 13,所以定點(diǎn)值 z= 29491即為浮點(diǎn)值 z= 29491/8192 =3.6。
例 3.3 定點(diǎn)減法 設(shè)x= 3.0, y=3.1,則浮點(diǎn)運(yùn)算結(jié)果為 z= x- y= 3.0- 3.1= - 0.1; Qx= 13, Qy=13, Qz= 15,則定點(diǎn)減法為:
x= 24576; y=25295; temp= 25395; temp= x- temp= 24576- 25395= - 819; 因?yàn)?Qx<Qz ,故 z= (int)( - 819<<2) = - 3276 。由于 z的 Q值為 15,所以定點(diǎn)值 z= - 3276即為浮點(diǎn)值 z= - 3276/32768 - 0.1。
2. 結(jié)果超過 16位表示范圍
·43·
設(shè) x的Q值為Qx, y的 Q值為 Qy,且Qx>Qy ,加法結(jié)果 z的定標(biāo)值為 Qz,則定點(diǎn)加法為:
int x , y; long temp, z; temp= y<<(Qx - Qy) ; temp= x+ temp; z= temp>>(Qx - Qz),若Qx ≥ Qz z= temp<<(Qz - Qx) ,若Qx ≤ Qz 例 3.4 結(jié)果超過 16位的定點(diǎn)加法 設(shè)x= 15000, y= 20000,則浮點(diǎn)運(yùn)算值為 z= x+ y= 35000,顯然 z>32767 ,因此Qx= 1, Qy= 0, Qz= 0,則定點(diǎn)加法為:
x= 30000; y=20000; temp= 20000<<1 = 40000; temp= temp+x =40000+30000 = 70000; z= 70000L>>1 = 35000; 因?yàn)?z的Q值為 0,所以定點(diǎn)值 z=35000就是浮點(diǎn)值,這里 z是一個(gè)長整型數(shù)。
當(dāng)加法或加法的結(jié)果超過 16位表示范圍時(shí),如果程序員事先能夠了解到這種情況,并 且需要保證運(yùn)算精度時(shí),則必須保持 32位結(jié)果。如果程序中是按照 16位數(shù)進(jìn)行運(yùn)算的,則超過 16位實(shí)際上就是出現(xiàn)了溢出。如果不采取適當(dāng)?shù)拇胧,則數(shù)據(jù)溢出會(huì)導(dǎo)致運(yùn)算精度的 嚴(yán)重惡化。一般的定點(diǎn) DSP芯片都設(shè)有溢出保護(hù)功能,當(dāng)溢出保護(hù)功能有效時(shí),一旦出現(xiàn) 溢出,則累加器 ACC 的結(jié)果為最大的飽和值 (上溢為 7FFFH ,下溢為 8001H) ,從而達(dá)到防止溢出引起精度嚴(yán)重惡化的目的。
3.2.2 乘法運(yùn)算的 C語言定點(diǎn)模擬 設(shè)浮點(diǎn)乘法運(yùn)算的表達(dá)式為:
float x,y,z; z = xy; 假設(shè)經(jīng)過統(tǒng)計(jì)后 x的定標(biāo)值為 Qx, y的定標(biāo)值為 Qy ,乘積 z的定標(biāo)值為 Qz,則 z = xy z q
2 z = x q
y q
2 (Q x Q y ) Q z = ( x y )2 z ( Q x
Q y
) q q q
所以定點(diǎn)表示的乘法為:
int x,y,z; Q
· 44·
long temp; temp = (long)x; z = (temp× y) >> (Qx+Qy - Qz); 例 3.5 定點(diǎn)乘法 設(shè)x = 18.4 , y = 36.8 ,則浮點(diǎn)運(yùn)算值為 z =18.4× 36.8 = 677.12; 根據(jù)上節(jié),得 Qx = 10 , Qy = 9 , Qz = 5 ,所以
·45·
Q Q x = 18841 ; y = 18841 ; temp = 18841L; z = (18841L*18841)>>(10+9 - 5) = 354983281L>>14 = 21666; 因?yàn)?z的定標(biāo)值為
5,故定點(diǎn) z = 21666 即為浮點(diǎn)的 z = 21666/32 = 677.08 。
3.2.3 除法運(yùn)算的 C語言定點(diǎn)模擬 設(shè)浮點(diǎn)除法運(yùn)算的表達(dá)式為:
float x,y,z; z = x/y; 假設(shè)經(jīng)過統(tǒng)計(jì)后被除數(shù) x的定標(biāo)值為 Qx,除數(shù) y的定標(biāo)值為 Qy,商 z的定標(biāo)值為 Qz,則 z = x/y
z q
2 z = x q
2 x Q y
y q
2
x q
2 z q
(Q z
Q x
y q
Q y
)
所以定點(diǎn)表示的除法為:
int x,y,z; long temp; temp = (long)x; z = (temp<<(Qz - Qx+Qy))/y; 例 3.6 定點(diǎn)除法 設(shè)x = 18.4 , y = 36.8 ,浮點(diǎn)運(yùn)算值為 z = x/y = 18.4/36.8 = 0.5; 根據(jù)上節(jié),得 Qx = 10 , Qy = 9 , Qz = 15 ;所以有x = 18841, y = 18841; temp = (long)18841; z = (18841L<<(15 - 10+9))/18841 = 308690944L/18841 = 16384; 因?yàn)樯?z的定標(biāo)值為
15,所以定點(diǎn)
z = 16384即為浮點(diǎn) z = 16384/2 15 = 0.5。
3.2.4 程序變量的 Q值確定
· 46·
在前面幾節(jié)介紹的例子中,由于 x、y、z的值都是已知的,因此從浮點(diǎn)變?yōu)槎c(diǎn)時(shí) Q值很好確定。在實(shí)際的 DSP應(yīng)用中,程序中參與運(yùn)算的都是變量,那么如何確定浮點(diǎn)程序中 變量的 Q值呢? 從前面的分析可以知道,確定變量的 Q值實(shí)際上就是確定變量的動(dòng)態(tài)范圍,動(dòng)態(tài)范圍確定了,則 Q值也就確定了。
設(shè)變量的絕對(duì)值的最大值為 max , 注意 max 必須小于或等于 32767。取一個(gè)整數(shù) n, 使它滿足 2n 1 則有 max 2n
·47·
,則 2 Q 2 15 2 n 2 (15 n) Q = 15 - n 例如,某變量的值在 - 1至+ 1之間,即 max <1,因此 n = 0, Q= 15- n = 15。
確定了變量的 max 就可以確定其 Q值,那么變量的 max 又是如何確定的呢?一般來說,確定變量的 max 有兩種方法:一種是理論分析法,另一種是統(tǒng)計(jì)分析法。
1. 理論分析法 有些變量的動(dòng)態(tài)范圍通過理論分析是可以確定的。例如:
(1)
三角函數(shù),
y = sin(x)或y = cos( x),由三角函數(shù)知識(shí)可知, |y|≤ 1; (2)
漢明窗,
y( n)
= 0.54- 0.46cos [2 n/(N - 1)] , 0≤ n≤ N- 1。因?yàn)?- 1≤ cos [2 n/(N - 1)] ≤ 1,所以 0.08≤ y(n)≤ 1.0; N (3) FIR卷積。
y(n)= k 1 h( k) x( n 0 k ) ,設(shè) N 1 h( k) k 0 1.0 ,且 x( n)是模擬信號(hào) 12位量化值, 即有 x(n) 11 y( n) ≤2 11 ;
(4) 理論已經(jīng)證明,在自相關(guān)線性預(yù)測編碼 (LPC) 的程序設(shè)計(jì)中,反射系數(shù)不等式:
k i 滿足下列 k i
1.0 , i= 1,2, ,p, p為LPC 的階數(shù)。
2. 統(tǒng)計(jì)分析法 對(duì)于理論上無法確定范圍的變量,一般采用統(tǒng)計(jì)分析的方法來確定其動(dòng)態(tài)范圍。所謂統(tǒng)計(jì)分析,就是用足夠多的輸入信號(hào)樣值來確定程序中變量的動(dòng)態(tài)范圍,這里輸入信號(hào)一方面要有一定的數(shù)量,另一方面必須盡可能地涉及各種情況。例如,在語音信號(hào)分析中, 統(tǒng)計(jì)分析時(shí)就必須采集足夠多的語音信號(hào)樣值,并且在所采集的語音樣值中,應(yīng)盡可能地 包含各種情況,如音量的大小、聲音的種類
(男聲、女聲
)
等。只有這樣,統(tǒng)計(jì)出來的結(jié)果才能具有典型性。
當(dāng)然,統(tǒng)計(jì)分析畢竟不可能涉及所有可能發(fā)生的情況,因此,對(duì)統(tǒng)計(jì)得出的結(jié)果在程 序設(shè)計(jì)時(shí)可采取一些保護(hù)措施,如適當(dāng)犧牲一些精度, Q值取比統(tǒng)計(jì)值稍大些,使用 DSP 芯片提供的溢出保護(hù)功能等。
3.2.5 浮點(diǎn)至定點(diǎn)變換的 C程序舉例 本節(jié)通過一個(gè)例子來說明 C 程序從浮點(diǎn)變換至定點(diǎn)的方法。這是一個(gè)對(duì)語音信號(hào)(0.3kHz~3.4kHz) 進(jìn)行低通濾波的
C語言程序,低通濾波的截止頻率為 800Hz ,濾波器采用 19 點(diǎn)的有限沖擊響應(yīng) FIR濾波。語音信號(hào)的采樣頻率為 8kHz ,每個(gè)語音樣值按 16位整型數(shù)存≤ 2
· 48·
放在 insp.dat文件中。
例 3.7 語音信號(hào) 800Hz 19 點(diǎn)FIR低通濾波 C語言浮點(diǎn)程序#include <stdio.h> const int length = 180 /* 語音幀長為 180點(diǎn)= 22.5ms@8kHz 采樣 */ void filter(int xin[ ],int xout[ ],int n,float h[ ]); /* 濾波子程序說明 */ /*19 點(diǎn)濾波器系數(shù) */ static float h[19]=
·49·
{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}; static int x1[length+20]; /* 低通濾波浮點(diǎn)子程序 */ void filter(int xin[ ],int xout[ ],int n,float h[ ]) { int i,j; float sum; for(i=0;i<length;i++) x1[n+i-1]=xin[i]; for (i=0;i<length;i++) { sum=0.0; for(j=0;j<n;j++) sum+=h[j]*x1[i - j+n - 1]; xout[i]=(int)sum; } for(i=0;i<(n - 1);i++) x1[n - i - 2]=xin[length - 1- i]; }
/* 主 程 序 */ void main( ) { FILE *fp1,*fp2; int frame,indata[length],outdata[length]; fp1=fopen(insp.dat,"rb"); /* 輸入語音文件 */
· 50·
fp2=fopen(outsp.dat,"wb");
frame=0; /* 濾波后語音文件 */ while(feof(fp1)==0)
{
frame++;
printf("frame=%d\n",frame);
for(i=0;i<length;i++) indata[i]=getw(fp1); /* 取一幀語音數(shù)據(jù) */ filter(indata,outdata,19,h); /* 調(diào)用低通濾波子程序 */ for(i=0;i<length;i++) putw(outdata[i],fp2); /* 將濾波后的樣值寫入文件 */ }
fcloseall( );
/* 關(guān)閉文件 */ return(0);
·51·
} 例 3.8 語音信號(hào) 800Hz 19 點(diǎn)FIR低通濾波 C語言定點(diǎn)程序#include <stdio.h> const int length=180; void filter(int xin[ ],int xout[ ],int n,int h[ ]); static int h[19]={399, - 296,- 945,- 1555, - 1503,- 285,2112,5061,7503,8450, 7503,5061,2112, - 285,- 1503,- 1555, - 945,- 296,399}; /*Q15*/ static int x1[length+20]; /* 低通濾波定點(diǎn)子程序 */ void filter(int xin[ ],int xout[ ],int n,int h[ ]) { int i,j; long sum; for(i=0;i<length;i++) x1[n+i - 1]=xin[i]; for (i=0;i<length;i++) { sum=0; for(j=0;j<n;j++) sum+=(long)h[j]*x1[i - j+n - 1]; xout[i]=sum>>15; } for(i=0;i<(n - 1);i++) x1[n - i- 2]=xin[length - i- 1]; } 主程序與浮點(diǎn)的完全一樣。
3.3 DSP定點(diǎn)算術(shù)運(yùn)算 定點(diǎn) DSP芯片的數(shù)值表示是基于 2的補(bǔ)碼表示形式。每個(gè) 16位數(shù)用 1個(gè)符號(hào)位、 i個(gè)整數(shù) 位和 15- i 個(gè)小數(shù)位來表示。因此數(shù) 00000010.10100000 表示的值為 2 1 2 1
2 3
=2.625 , 這 個(gè)數(shù)可用
Q8格式 (8個(gè)小數(shù)位 )來表示,它表示的數(shù)值范圍為 - 128~+127.996 ,一個(gè) Q8 定點(diǎn)數(shù)的小數(shù)精度為 1/256=0.004 。
· 52·
雖然特殊情況 ( 如動(dòng)態(tài)范圍和精度要求 )必須使用混合表示法,但是,更通常的是全部以Q15格式表示的小數(shù)或以 Q0格式表示的整數(shù)來工作。這一點(diǎn)對(duì)于主要是乘法和累加的信號(hào)處理算法特別現(xiàn)實(shí),小數(shù)乘以小數(shù)得小數(shù),整數(shù)乘以整數(shù)得整數(shù)。當(dāng)然,乘積累加時(shí)可 能會(huì)出現(xiàn)溢出現(xiàn)象,在這種情況下,程序員應(yīng)當(dāng)了解數(shù)學(xué)里面的物理過程以注意可能的溢 出情況。下面討論乘法、加法和除法的 DSP定點(diǎn)運(yùn)算,匯編程序以 TMS320C25 為例。
3.3.1 定點(diǎn)乘法 2個(gè)定點(diǎn)數(shù)相乘時(shí)可以分為下列 3種情況:
1. 小數(shù)乘小數(shù)
·53·
Q15× Q15= Q30
例 3.9 0.5*0.5 = 0.25 0.100000000000000 ; Q15 × 0.100000000000000 ; Q15 00.010000000000000000000000000000=0.25 ; Q30 2個(gè)Q15的小數(shù)相乘后得到 1個(gè)Q30的小數(shù),即有 2個(gè)符號(hào)位。一般情況下相乘后得到的 滿精度數(shù)不必全部保留,而只需保留 16位單精度數(shù)。由于相乘后得到的高 16位不滿
15位的小數(shù)精度,為了達(dá)到 15位精度,可將乘積左移 1位,下面是上述乘法的 TMS320C25 程序 :
LT OP1 ; OP1=4000H(0.5/Q15) MPY PAC OP2 ; OP2=4000H(0.5/Q15) SACH ANS,1 ; ANS=2000H(0.25/Q15) 2. 整數(shù)乘整數(shù) Q0× Q0 = Q0
例 3.10 17× (- 5)= - 85
0000000000010001=17 × 1111111111111011= - 5 11111111111111111111111110101011= - 85 3. 混合表示法 許多情況下,運(yùn)算過程中為了既滿足數(shù)值的動(dòng)態(tài)范圍又保證一定的精度,就必須采用
Q0與 Q15之間的表示法。比如,數(shù)值 近的數(shù)是 1,精度無法保證。因此,數(shù) 1.2345,顯然 Q15無法表示,而若用 1.2345最佳的表示法是 Q14。
Q0表示,則最接 例 3.11 1.5× 0.75 = 1.125
×
01.10000000000000 = 1.5 00.11000000000000 = 0.75 ; Q14 ; Q14 0001.0010000000000000000000000000 = 1.125;Q28 Q14的最大值不大于 2,因此,
2個(gè)Q14數(shù)相乘得到的乘積不大于 4。
一般的,若一個(gè)數(shù)的整數(shù)位為 i位,小數(shù)位為 j
位,另一個(gè)數(shù)的整數(shù)位為 m 位,小數(shù)位為 n
位,則這兩個(gè)數(shù)的乘積為
( i + m )
位整數(shù)位和
(j + n) 位小數(shù)位。這個(gè)乘積的最高16位可能的精度為 ( i + m ) 整數(shù)位和
(15 - i - m) 小數(shù)位。
· 54·
但是,若事先了解數(shù)的動(dòng)態(tài)范圍,就可以增加數(shù)的精度。例如,程序員了解到上述乘 積不會(huì)大于 1.8 ,就可以用 Q14 數(shù)表示乘積,而不是理論上的最佳情況 Q13 。例 3.11的TMS320C25 程序如下:
LT OP1 ;OP1 = 6000H(1.5/Q14) MPY PAC OP2 ;OP2 = 3000H(0.75/Q14) SACH ANS,1 ;ANS = 2400H(1.125/Q13) 上述方法為了保證精度均對(duì)乘的結(jié)果舍位,結(jié)果所產(chǎn)生的誤差相當(dāng)于減去 1個(gè) LSB( 最低位 )。采用下面簡單的舍入方法,可使誤差減少二分之一。
·55·
LT OP1
MPY OP2 PAC ADD
ONE, 14
(上舍入 ) SACH ANS ,1
上述程序說明,不管 ANS 為正或負(fù),所產(chǎn)生的誤差是 1/2
LSB ,其中存儲(chǔ)單元 ONE 的值為 1。
3.3.2 定點(diǎn)加法 乘的過程中,程序員可不考慮溢出而只需調(diào)整運(yùn)算中的小數(shù)點(diǎn)。而加法則是一個(gè)更加 復(fù)雜的過程。首先,加法運(yùn)算必須用相同的 Q點(diǎn)表示;其次,程序員或者允許其結(jié)果有足
夠的高位以適應(yīng)位的增長,或者必須準(zhǔn)備解決溢出問題。如果操作數(shù)僅為 16位長,其結(jié)果可用雙精度數(shù)表示。下面舉例說明 16位數(shù)相加的兩種途徑。
1.保留 32位結(jié)果
LAC OP1 ;(Q15) ADD OP2 ;(Q15) SACH ANSHI ;(高16位結(jié)果 ) SACL 2.調(diào)整小數(shù)點(diǎn)保留 ANSLO 16位結(jié)果 ;(低16位結(jié)果 ) LAC OP1,15 ;(Q14 數(shù)用 ACCH 表示 ) ADD OP2,15 ;(Q14 數(shù)用 ACCH 表示 ) SACH ANS ;(Q14) 加法運(yùn)算最可能出現(xiàn)的問題是運(yùn)算結(jié)果溢出。
TMS320 提供了檢查溢出的專用指令 BV ,此外,使用溢出保護(hù)功能可使累加結(jié)果溢出時(shí)累加器飽和為最大的整數(shù)或負(fù)數(shù)。當(dāng)然,即使如此,運(yùn)算精度還是大大降低。因此,最好的方法是完全理解基本的物理過程并注意選擇數(shù)的表達(dá)方式。
3.3.3 定點(diǎn)除法 在通用 DSP芯片中,一般不提供單周期的除法指令,為此必須采用除法子程序來實(shí)現(xiàn)。二進(jìn)制除法是乘法的逆運(yùn)算。乘法包括一系列的移位和加法,而除法可分解為一系列的減法和移位。下面來說明除法的實(shí)現(xiàn)過程。
設(shè)累加器為 8位,且除法運(yùn)算為 10除以 3。除的過程就是除數(shù)逐步移位并與被除數(shù)比較 的過程,在每一步進(jìn)行減法運(yùn)算,如果能減則將位插入商中。
(1) 除數(shù)的最低有效位對(duì)齊被除數(shù)的最高有效位。
· 56·
00001010 - 00011000 11110010 (2) 由于減法結(jié)果為負(fù),放棄減法結(jié)果,將被除數(shù)左移一位再減。
·57·
00010100 - 00011000
11111000 (3) 結(jié)果仍為負(fù),放棄減法結(jié)果,被除數(shù)左移一位再減。
00101000 - 00011000
00010000 (4) 結(jié)果為正,將減法結(jié)果左移一位后加1,作最后一次減。
00100001 - 00011000
00001001
(5)
結(jié)果為正,將結(jié)果左移一位加 1得最后結(jié)果。高4位代表余數(shù),低 4位表示商。00010011 即商為 0011=3 ,余數(shù)為 0001=1。
TMS320 沒有專門的除法指令,但使用條件減指令 SUBC 可以完成有效靈活的除法功能。使用這一指令的唯一限制是兩個(gè)操作數(shù)必須為正。程序員必須事先了解其可能的運(yùn)算 數(shù)的特性,如其商是否可以用小數(shù)表示及商的精度是否可被計(jì)算出來。這里每一種考慮可
影響如何使用 SUBC 指令的問題。下面給出兩種不同情況下的 TMS320C25 除法程序。
(1) 分子小于分母 DIV_A:
LT NUMERA
MPY DENOM PAC SACH
TEMSGN
;取商的符號(hào) LAC DENOM
ABS
SACL DENOM ;使分母為正 ZALH ABS NUMERA ;使分子為正 RPTK 14
SUBC DENOM ;除循環(huán) 15次 SACL QUOT
LAC TEMSGN
· 58·
BGEZ ZAC A1 ;若符號(hào)為正 ,則完成 SUB QUOT
SACL QUOT ;若為負(fù) ,則商為負(fù) A1: RET
·59·
這個(gè)程序中,分子在 NUMERA 中,分母在 DENOM 中,商存在 QUOT 中 , TEMSGN 為暫存單元。
(2) 規(guī)定商的精度 DIV_B:
LT NUMERA
MPY DENOM
PAC
SACH TEMSGN ;取商的符號(hào) LAC DENOM
ABS
SACL DENOM ;使分母為正 LACK 15
ADD FRAC
SACL FRAC ;計(jì)算循環(huán)計(jì)數(shù)器 LAC NUMERA
ABS RPT
FRAC ;使分子為正 SUBC DENOM ;除循環(huán) 16+FRAC 次 SACL QUOT
LAC TEMSGN
BGEZ B1 ;若符號(hào)為正 ,則完成 ZAC
SUB QUOT
SACL QUOT ;若為負(fù) ,則商為負(fù) B1: RET 與 DIV_A 相同,這個(gè)程序中,分子在 NUMERA
中,分母在 DENOM 中,商存在 QUOT 中, TEMSGN 為暫存單元。
FRAC 中規(guī)定商的精度,如商的精度為 Q13
,則調(diào)用程序前FRAC 單元中的值應(yīng)為 13。
3.4 非線性運(yùn)算的定點(diǎn)快速實(shí)現(xiàn) 在數(shù)值運(yùn)算中,除基本的加減乘除運(yùn)算外,還有其他許多非線性運(yùn)算,如對(duì)數(shù)運(yùn)算、 開方運(yùn)算、指數(shù)運(yùn)算、三角函數(shù)運(yùn)算等,實(shí)現(xiàn)這些非線性運(yùn)算的方法一般有:
(1) 調(diào)用 DSP
· 60·
編譯系統(tǒng)的庫函數(shù); (2) 查表法; (3) 混合法。下面分別介紹這三種方法。1.調(diào)用 DSP編譯系統(tǒng)的庫函數(shù) TMS320C2X/C5X 的C編譯器提供了比較豐富的運(yùn)行支持庫函數(shù)。在這些庫函數(shù)中, 包含了諸如對(duì)數(shù)、開方、三角函數(shù)、指數(shù)等常用的非線性函數(shù)。在 C程序中 (也可在匯編程序中 )只要采用與庫函數(shù)相同的變量定義,就可以直接調(diào)用。例如,在庫函數(shù)中,定義了以 10為底的常用對(duì)數(shù) log10( ) :
·61·
。 include <math.h> double log10(double x); 在 C程序中按如下方式調(diào)用:
float x,y; x = 10.0; y = log10(x); 從上例可以看出,庫函數(shù)中的常用對(duì)數(shù)
log10(
)要求的輸入值為浮點(diǎn)數(shù),返回值也為浮點(diǎn)數(shù),運(yùn)算的精度完全可以保證。直接調(diào)用庫函數(shù)非常方便,但由于運(yùn)算量大,很難在實(shí) 時(shí)DSP中得到應(yīng)用。2.查表法 在實(shí)時(shí) DSP應(yīng)用中實(shí)現(xiàn)非線性運(yùn)算,一般都采取適當(dāng)降低運(yùn)算精度來提高程序的運(yùn)算 速度。查表法是快速實(shí)現(xiàn)非線性運(yùn)算最常用的方法。采用這種方法必須根據(jù)自變量的范圍和精度要求制作一張表格。顯然輸入的范圍越大,精度要求越高,則所需的表格就越大, 即存儲(chǔ)量也越大。查表法求值所需的計(jì)算就是根據(jù)輸入值確定表的地址,根據(jù)地址就可得到相應(yīng)的值,因而運(yùn)算量較小。查表法比較適合于非線性函數(shù)是周期函數(shù)或已知非線性函數(shù)輸入值范圍這兩種情況,例 3.12和例 3.13分別說明這兩種情況。
例 3.12
已知正弦函數(shù)
y=cos(x) ,制作一個(gè)
512點(diǎn)表格,并說明查表方法。由于正弦函數(shù)是周期函數(shù),函數(shù)值在- 1至+ 1之間,用查表法比較合適。
由于 Q15的表示范圍為-
1至32767/32768 之間,原則上講-
1至+ 1的范圍必須用
Q14表示。但一般從方便和總體精度考慮,類似情況仍用 Q15表示,此時(shí)+ 1用32767來表示。
(1) 產(chǎn)生 512點(diǎn)值的 C語言程序如下所示 :
#define N 512 #define pi 3.14159 int sin_tab[512]; void
main( ) { int i; for(i=0;i<N;i++) sin_tab[i]=(int)(32767*sin(2*pi*i/N)); } (2) 查表 查表實(shí)際上就是根據(jù)輸入值確定表的地址。設(shè)輸入 x在0~2 之間,則 x對(duì)應(yīng)于 512點(diǎn)表
· 62·
的地址為:
index = (int)(512*x/2 ),則 y = sin(x) = sin_tab[index] 。
如果 x用 Q12 定點(diǎn)數(shù)表示,將 512/2 用 Q8表示為 20861,則計(jì)算正弦表的地址的公式 為:
index = (x*20861L)>>20 。
例 3.13 用查表法求以 2為底的對(duì)數(shù),已知自變量取值范圍為 0.5~1,要求將自變量范圍均勻劃分為 10等分。試制作這個(gè)表格并說明查表方法。
(1) 做表:
y
=
log2(x) ,由于 x在0.5到1之間,因此
y在- 1到0之間, x和y均可用 Q15 表示。由于對(duì) x 均勻劃分為
10段,因此,
10段對(duì)應(yīng)于輸入 x的范圍如表
3.2所示。若每一段的對(duì)數(shù)值都取第 1
·63·
點(diǎn)的對(duì)數(shù)值,則表中第 1段的對(duì)數(shù)值為 y0(Q15) = (int)(log2(0.5) × 32768),第 2段的對(duì)數(shù)值為 y1(Q15) = (int)(log2(0.55)
×32768) ,依次類推。
表3.2 logtab0 10 點(diǎn)對(duì)數(shù)表 (輸入0.5~1) 地址
輸入值 對(duì)數(shù)值 (Q15) 0
0.50~0.55 - 32768 1
0.55~0.60 - 28262 2
0.60~0.65 - 24149 3
0.65~0.70 - 20365 4
0.70~0.75 - 16862 5
0.75~0.80 - 13600 6
0.80~0.85 - 10549 7
0.85~0.90 - 7683 8
0.90~0.95 - 4981 9
0.95~1.00 - 2425
(2) 查表 : 查表時(shí),先根據(jù)輸入值計(jì)算表的地址,計(jì)算方法為:
index=((x - 16384) × 20)>>15 。式中, index 就是查表用的地址。例如,已知輸入 x= 26869 ,則 index=6 ,因此 y=- 10549。
3.混合法 (1) 提高查表法的精度 上述方法查表所得結(jié)果的精度隨表的大小而變化,表越大,則精度越高,但存儲(chǔ)量也越大。當(dāng)系統(tǒng)的存儲(chǔ)量有限而精度要求也較高時(shí),查表法就不太適合。那么能否在適當(dāng)增加運(yùn)算量的情況下提高非線性運(yùn)算的精度呢?下面介紹一種查表結(jié)合少量運(yùn)算來計(jì)算非線性函數(shù)的混合法,這種方法適用于在輸入變量的范圍內(nèi)函數(shù)呈單調(diào)變化的情形。
混合法是在查表的基礎(chǔ)上采用計(jì)算的方法以提高當(dāng)輸入值處于表格兩點(diǎn)之間時(shí)的精度。提高精度的一個(gè)簡便方法是采用折線近似法,如圖 3.1所示。
仍以求以
2為底的對(duì)數(shù)為例 (例3.13) 。設(shè)輸入值為 x,則精確的對(duì)數(shù)值為 y,在表格值的兩點(diǎn)之間作一直線,用 y'作為 y的近似值,則有:
y'= y 0 + y
y
y " y 0
y
x y 0
x 0
x 0
x
圖3.1 提高精度的折線近似法
· 64·
其中 y 0 由查表求得,F(xiàn)在只需在查表求得 y 0 的基礎(chǔ)上增加 y即可。
y的計(jì)算方法如下:
y=( x/ x 0 ) y= x( y 0 / x 0 ) 式中 y 0 / x 0 對(duì)每一段來說是一個(gè)恒定值,可作一個(gè)表格直接查得。此外計(jì)算 x時(shí)需用到每段橫坐標(biāo)的起始值,這個(gè)值也可作一個(gè)表格。這樣共有 三個(gè)大小均為 10 的表格,分別為存儲(chǔ)每段起點(diǎn)對(duì) 數(shù) 值 的 表 logtab0 、 存 儲(chǔ) 每 段 y 0 / x 0
值 的 表 logtab1 和存儲(chǔ)每段輸入起始值 x 0 的表 logtab2 ,表 logtab1 和表 logtab2可用下列兩個(gè)數(shù)組表示:
·65·
int logtab1[10]={22529,20567,18920,17517,16308, 15255,14330,13511,12780,12124}; /* y 0 / x 0 : Q13*/ int logtab2[10]={16384,18022,19660,21299,22938, 24576,26214,27853,29491,31130}; /* x 0 : Q15*/ 綜上所述,采用混合法計(jì)算對(duì)數(shù)值的方法可歸納為:
①根據(jù)輸入值,計(jì)算查表地址:
index=((x - 16384)× 20)>>15; ②查表得 y 0 =logtab0[index]; ③計(jì)算 x=x - logtab2[index]; ④計(jì)算 y= ( x× logtab1[index])>>13;
⑤計(jì)算得結(jié)果 y=y 0 + y。
例 3.14 已知 x=0.54 ,求 log2(x) 。
0.54的精確對(duì)數(shù)值為y=log2(0.54)= - 0.889 ;旌戏ㄇ髮(duì)數(shù)值的過程為:
、俣(biāo) Q15,定標(biāo)值 x=0.54*32768=17694 ; ②表地址 index=((x - 16384)× 20)>>15=0; ③查表得 y 0 =logtab0[0]= - 32768; ④計(jì)算 x=x - logtab2[0]=17694 - 16384=1310; ⑤計(jì)算 y= ( xlogtab1[0])>>13=(1310*22529L)>>13=3602; ⑥計(jì)算結(jié)果
y=y 0 + y=- 32768+3602= - 29166。
結(jié)果 y為Q15定標(biāo),折算成浮點(diǎn)數(shù)為 - 29166/32768= - 0.89,可見精度較高。
(2) 擴(kuò)大自變量范圍 如上所述,查表法比較適用于周期函數(shù)或自變量的動(dòng)態(tài)范圍不是太大的情形。對(duì)于像對(duì)數(shù)這樣的非線性函數(shù),輸入值和函數(shù)值的變化范圍都很大。如果輸入值的變化范圍很
大,則作表就比較困難。那么能否比較好地解決這個(gè)問題,既不使表格太大,又能得到比較高的精度呢?下面討論一種切實(shí)可行的方法。
設(shè) x是一個(gè)大于 0.5的數(shù),則 x可以表示為下列形式:
x = m 2 e
式中, 0.5≤ m≤ 1.0,e為整數(shù)。則求 x 的對(duì)數(shù)可以表示為:
log2(x) = log2( m 2 e
) = log2(m) + log2( 2 e
) = e + log2(m)
· 66·
也就是說,求 x的對(duì)數(shù)實(shí)際上只要求 m的對(duì)數(shù)就可以了,而由于 m的數(shù)值在 0.5~1.0 之間, 用上面介紹的方法是完全可以實(shí)現(xiàn)的。例如:
log2(10000) = log2(0.61035 × 214 ) = log2(0.61035) + 14 = 13.2877
可見,如果一個(gè)數(shù)可以用比較簡便的方法表示為上面的形式,則求任意大小數(shù)的對(duì)數(shù) 也是比較方便的。
TMS320C2X/C5X 指令集提供了一條用于對(duì) ACC 中的數(shù)進(jìn)行規(guī)格化的指令 NORM ,該指令的作用就是使累加器中的數(shù)左移,直至數(shù)的最高位被移至累加器的第 30位。例如,對(duì)數(shù)值 10000進(jìn)行規(guī)格化的 TMS320C25 程序?yàn)椋?/p>
LAC #10000 SACL TEMP ZALH TEMP
·67·
Q LAR AR1,#0FH RPT 14 NORM * - 上述程序執(zhí)行后, AR1=#0eH , ACCH=2000(10 進(jìn)制 )。對(duì)一個(gè)
16位整數(shù) x 進(jìn)行上述程序處理實(shí)際上就是做這樣一個(gè)等效變換:
x = x 2 2 15 Q 32768 其中,寄存器 AR1 包含的值為 15- Q ,累加器 ACC 高 16 位包含的值為16384~32768之間。
例 3.15 實(shí)現(xiàn)以 2為底的對(duì)數(shù)的 C定點(diǎn)模擬程序 int logtab0[10] ={ - 32768,- 28262,- 24149,- 20365,- 16862, - 13600,- 10549,- 7683,- 4981,- 2425}; /*Q15*/ int logtab1[10] ={22529,20567,18920,17517,16308, 15255,14330,13511,12780,12124}; /*Q13*/ int logtab2[10] ={16384,18022,19660,21299,22938, 24576,26214,27853,29491,31130}; /*Q15*/ int log2_fast(int Am) {
x 2 Q
,其數(shù)值在 int point,point1; int index,x0,dx,dy,y; point =0; while(Am<16384) {point++ ; Am =Am<<1;} /* 對(duì) Am 進(jìn)行規(guī)格化 */ point1 = (15- point - 4)*512; /* 輸入為 Q4,輸出為 Q9*/ index = ((Am - 16384)*20L)>>15; /* 求查表地址 */ dx = Am- logtab2[index]; dy = ((long)dx*logtab1[index])>>13; y= (dy+logtab0[index])>>6;
· 68·
/*Q9*/ y= point1+y; return (y); } 上述程序中,輸入值 Am 采用 Q4表示,輸出采用 Q9表示,如果輸入輸出的 Q值與上面程序中的不同,則應(yīng)做相應(yīng)的修改。
3.5 小 結(jié) 本章討論了DSP 芯片進(jìn)行定點(diǎn)運(yùn)算所涉及的一些基本問題,這些問題包括:數(shù)的定標(biāo), DSP程序的定點(diǎn)模擬, DSP芯片的定點(diǎn)運(yùn)算以及定點(diǎn)實(shí)現(xiàn)非線性函數(shù)的快速實(shí)現(xiàn)方法等。充分理解這些問題對(duì)于用定點(diǎn)芯片實(shí)現(xiàn) DSP算法具有非常重要的作用。
熱點(diǎn)文章閱讀