1. 概述
基于FPGA實(shí)現(xiàn)各種設(shè)計(jì)的首要前提是理解并掌握數(shù)字的表示方法,計(jì)算機(jī)中的數(shù)字表示方法有兩種:定點(diǎn)數(shù)表示法和浮點(diǎn)數(shù)表示方法。其中,對(duì)于浮點(diǎn)數(shù)盡管當(dāng)前應(yīng)用最為廣泛的是基于IEEE 754所設(shè)計(jì)的浮點(diǎn)數(shù)表示方法,Xilinx(忘記Altera中是否有對(duì)應(yīng)的IP核)的IP核中也提供了相應(yīng)的設(shè)計(jì)方法,但其表示方法缺乏FPGA設(shè)計(jì)應(yīng)有的靈活性,而且資源消耗相對(duì)嚴(yán)重,因此可以根據(jù)應(yīng)用的需要,設(shè)計(jì)好基于FPGA實(shí)現(xiàn)的自定義浮點(diǎn)數(shù)。
2. 定點(diǎn)數(shù)表示
定點(diǎn)數(shù)大類上可分為有符號(hào)數(shù)和無符號(hào)數(shù),需要清楚的是,無論是計(jì)算機(jī)還是FPGA,其底層并沒有無符號(hào)數(shù)、有符號(hào)數(shù)的概念,底層只是一大串二進(jìn)制數(shù)據(jù)在進(jìn)行運(yùn)算(在底層就是一大堆寄存器處于開關(guān)的工作狀態(tài)中)。定點(diǎn)數(shù)的第一印象容易給人產(chǎn)生是用來表示整數(shù)的印象,然而無論是整數(shù)還是小數(shù)都可以采用定點(diǎn)數(shù)來表示,同理整數(shù)和小數(shù)的概念也是人為規(guī)定上去的,F(xiàn)PGA本身不會(huì)理解那一大串二進(jìn)制數(shù)是表示整數(shù)還是小數(shù),具體的運(yùn)算法則由編程人員規(guī)定好。
1.1 Qm.n的表示方法
本文采用最廣泛使用的補(bǔ)碼表示形式(默認(rèn)都懂其他的原碼表示和反碼表示形式),對(duì)應(yīng)的用來表示有符號(hào)數(shù)。人為定義小數(shù)點(diǎn)的位置。
采用Qm.n量化表示定點(diǎn)數(shù),其中m用來表示小數(shù)點(diǎn)前的位寬,包括一位符號(hào)位和m-1位整數(shù)位,n表示小數(shù)位寬。如16位有符號(hào)整數(shù)可以表示成Q16.0,用來表示小于1的小數(shù)則可以表示成Q1.15。對(duì)于Qm.n的表示格式,其范圍表示如下:
例如,1110整數(shù)則表示為Q4.0:(-2^4 + 2^3 + 2^2 +0)/2^0= -2,1110有兩位小數(shù)則表示為Q2.2:(-2^4+2^3+2^1+0)/2^2 = -0.5。下表對(duì)應(yīng)表示16位二進(jìn)制補(bǔ)碼表示的數(shù)的范圍。
1.1 浮點(diǎn)數(shù)的定點(diǎn)化
浮點(diǎn)數(shù)的定點(diǎn)化涉及到量化方法。量化的過程可以表示為:
量化方法主要有兩種:尾部截?cái)嗌釛壏ê臀膊克纳嵛迦敕ā?/p>
對(duì)于尾部截?cái)嗌釛壏?,顧名思義則是丟棄掉尾部不能表示的部分。假設(shè)將浮點(diǎn)數(shù)表示成8位Q3.5的定點(diǎn)數(shù),則表示過程如下(對(duì)3.2和-3.2進(jìn)行定點(diǎn)化):
[3.2] = floor(3.2*2^5) = floor(102.4) = 102 = 01100110
[-3.2] = floor(-3.2*2^5) = floor(-102.4) = -103 = 10011001
采用MATLAB可以做如下實(shí)現(xiàn):
dec2bin(floor(3.2*2^5), 8) = 01100110
dec2bin(2^8+floor(-3.2*2^5), 8) = 10011001
對(duì)于四舍五入法,則對(duì)應(yīng)的過程表示如下:
[3.2] = round(3.2*2^5) = round(102.4) =102 = 01100110
[-3.2]=round(-3.2*2^5) = round(-102.4)= -102 = 10011010
采用MATLAB可以做如下實(shí)現(xiàn):
dec2bin(round(3.2*2^5), 8) = 01100110
dec2bin(2^8+round(-3.2*2^5), 8) = 10011010
由于采用四舍五入方法還需要進(jìn)行尾部數(shù)據(jù)的判斷,因此通常使用中,如無特別需求,多采用尾部截?cái)嗌釛壏ā?/p>
3. 浮點(diǎn)數(shù)表示
在FPGA運(yùn)算中,浮點(diǎn)數(shù)無論是表示方法、資源占用還是運(yùn)算法則都比定點(diǎn)數(shù)復(fù)雜得多。但另一方面,基于FGPA 的實(shí)現(xiàn)的算法性能嚴(yán)重依賴于算法的數(shù)值精度表示,很多時(shí)候在信號(hào)處理中,數(shù)值的動(dòng)態(tài)范圍過大,采用一般的定點(diǎn)算法往往無法滿足這樣大的動(dòng)態(tài)范圍,而且定點(diǎn)算法經(jīng)過精打細(xì)算之后,算法的小數(shù)位和整數(shù)位是固定的,表示的范圍同樣是固定的,無法在作調(diào)節(jié),后續(xù)一旦有所修改,整個(gè)算法實(shí)現(xiàn)過程需要重新進(jìn)行計(jì)算仿真設(shè)計(jì),這樣的后期維護(hù)成本太高,簡(jiǎn)直是牽一發(fā)而動(dòng)全身。對(duì)于cpu處理器來說,浮點(diǎn)格式基本上會(huì)采用IEEE 754制定的標(biāo)準(zhǔn)單精度或雙精度格式。而對(duì)于FPGA來說,由于其強(qiáng)大的靈活性,雖然也是按照IEEE 754標(biāo)準(zhǔn)實(shí)現(xiàn)浮點(diǎn)數(shù)表示,但是卻可以對(duì)尾數(shù)和指數(shù)的位寬作修改。
IEEE 754定制的浮點(diǎn)格式在存儲(chǔ)方面有著很完美的形式,可以最大限度表示數(shù)的動(dòng)態(tài)范圍的同時(shí),減少存儲(chǔ)資源,但是實(shí)際參與運(yùn)算時(shí)并沒那么直接,需要經(jīng)過相應(yīng)的換算。因此可利用FPGA的靈活性,自定義浮點(diǎn)數(shù)格式。
3.1 自定義浮點(diǎn)格式表示
不像根據(jù)IEEE 754[45] 標(biāo)準(zhǔn)所設(shè)計(jì)的32-bit和64-bit標(biāo)準(zhǔn)浮點(diǎn)格式,本論文的自定義浮點(diǎn)由位寬可配置的指數(shù)(Exponent)和尾數(shù)(Mantissa)兩部分組成。指數(shù)和尾數(shù)部分都是有符號(hào)定點(diǎn)數(shù)。作為一個(gè)例子,我們采用標(biāo)準(zhǔn)雙精度浮點(diǎn)格式和自定義浮點(diǎn)格式之間進(jìn)行對(duì)比。標(biāo)準(zhǔn)雙精度浮點(diǎn)數(shù)可以表示如下等式:
其中1.f表示52-bit尾數(shù);Exp?表示存儲(chǔ)起來的指數(shù)值;bias?表示偏置,對(duì)于標(biāo)準(zhǔn)雙精度浮點(diǎn),改值為1023;Exp-bias?表示實(shí)際的指數(shù)值。標(biāo)準(zhǔn)格式表示如圖(a) 所示。然而,對(duì)于自定義浮點(diǎn)格式表示的數(shù)的實(shí)際值如下:
其中,Man?表示的尾數(shù)是52-bit有符號(hào)定點(diǎn)數(shù),表示的實(shí)際值為0.1b49b48...b2b1b0 或者1.0b49b48...b2b1b0。而Exp?表示實(shí)際指數(shù)值。具體格式表示如圖(b)所示。
自定義浮點(diǎn)算法的其中一個(gè)優(yōu)點(diǎn)是指數(shù)部分和尾數(shù)部分的位寬都是可配置的,設(shè)計(jì)者可以在算法精度要求和資源消耗方面進(jìn)行權(quán)衡。而現(xiàn)存的由XILINX 提供的浮點(diǎn)運(yùn)算IP 核是基于IEEE 754標(biāo)準(zhǔn)的,在每一次四則運(yùn)算之后(如加法或乘法之后)都會(huì)進(jìn)行一個(gè)格式化運(yùn)算。而格式化運(yùn)算占比的硬件資源消耗很大。無疑,如果存在多次連續(xù)加法運(yùn)算或者乘加運(yùn)算,這樣的運(yùn)算方式是資源消耗嚴(yán)重的。而本文所提出的自定義浮點(diǎn)算法則是整合的乘加運(yùn)算和連續(xù)加法運(yùn)算,盡量減少格式化操作,從而減少資源消耗。
1.1 定點(diǎn)數(shù)轉(zhuǎn)自定義浮點(diǎn)格式
相比較于標(biāo)準(zhǔn)浮點(diǎn)格式的轉(zhuǎn)換,定點(diǎn)數(shù)轉(zhuǎn)成上文描述的自定義浮點(diǎn)格式相對(duì)來說簡(jiǎn)單許多,只需要經(jīng)過簡(jiǎn)單的規(guī)格化,假設(shè)定點(diǎn)數(shù)為Qm.n,將其轉(zhuǎn)換為指數(shù)位寬為E,尾數(shù)位寬為M,其過程可以描述如下:
輸入:定點(diǎn)數(shù)Qm.n,則初始指數(shù)值為m,尾數(shù)Q1.(m+n-1);
規(guī)格化:計(jì)算符號(hào)位個(gè)數(shù),假設(shè)計(jì)算得符號(hào)位個(gè)數(shù)為k;
輸出:指數(shù)輸出值為m-k,尾數(shù)從m+n-k作為最高位開始截位,截取M位,如果不夠長(zhǎng),則從最低位開始補(bǔ)零,補(bǔ)足到M位長(zhǎng)度輸出。
這里唯一需要再次說明的是,如何計(jì)算符號(hào)位的個(gè)數(shù),最簡(jiǎn)單的方法就是采用一個(gè)for循環(huán),for循環(huán)里邊使用一個(gè)計(jì)數(shù)器(初始值為1)和比較判斷器,從次高位開始與最高位做比較,如果相同(同為1或者同為0),則計(jì)數(shù)器加1,以此類推下去。這里使用MATLAB,按照比特級(jí)別仿真,打包成一個(gè)函數(shù),如下:
?
function k = dupSign_cal(u)% ?u: 定點(diǎn)數(shù)輸入 % k:計(jì)算符號(hào)位個(gè)數(shù) bit_len = get(u, 'WordLenght'); SignBit = bitget(u, bit_len); count = 1; for i = bit_len-1:-1:1 if bitget(u, i) == SignBit ? count = count+1; else ? break; end end
?
當(dāng)然,無論是verilog里邊的for循環(huán)還是vhdl里邊的for循環(huán),并非軟件中for的概念意義,實(shí)際上FPGA綜合時(shí)會(huì)將for循環(huán)全部展開,因此這里如果定點(diǎn)數(shù)太長(zhǎng),則for循環(huán)不但消耗的資源多,而且非常容易造成時(shí)序不過關(guān)(想想在規(guī)定的一個(gè)或兩個(gè)時(shí)鐘里邊完成幾十比特一比特一比特的比對(duì))。因此如果定點(diǎn)位寬太長(zhǎng),則應(yīng)該想更多的辦法來完成該過程,F(xiàn)PGA節(jié)省時(shí)間的方法無外乎增加資源,一個(gè)for循環(huán)不行,并行多個(gè)for循環(huán)嘛?! ?/p>
評(píng)論
查看更多