FPGA量化/小數計算
定點數的量化
在FPGA開發時,對於浮點數,可以采用IEEE規定的浮點數格式,但那種浮點數運算的開銷太大,對於小數位數比較少的浮點數,資源浪費又太多,可以采用定點數的形式來進行運算。
所謂定點數就是將小數點的位置固定,也就是說,整數部分和小數部分的位數固定,我們用整數來表示這個定點小數。
舉個例子我們可以用(8,3)來表示8位二進制數據,其中最后的三位表示小數部分。
比如1.125,我們可以寫成8'b00001001
因為小數部分是三位,相當於對於0~1
的小數,我們有\(2^3=8\)個刻度來表示,一個刻度的精度是\(1/8=0.125\),那么對於0.125我們可以寫成001
,對於整數部分1就可以寫成二進制數00001
合起來就寫成00001001
,從另一方面,因為(8,3)的一個刻度的精度是0.125,1.125有9個0.125的刻度,所以寫成\(9(d)=00001001(b)\)
對於1.125用(8,3)定點數可以表示為\(-2^4\times 0 + 2^3 \times 0 + 2^2 \times 0 + 2^1 \times 0 + 2^0 \times 1 + 2^{-1} \times 0 + 2^{-2} \times 0 + 2^{-3} \times 1\)對於最開始的負號,表示符號位
對於負數-0.125來說,可以先求0.125的定點數形式,即00000001
,再求補碼即11111111
,如果展開來即為
\(-2^4\times 1 + 2^3 \times 1 + 2^2 \times 1 + 2^1 \times 1 + 2^0 \times 1 + 2^{-1} \times 1 + 2^{-2} \times 1 + 2^{-3} \times 1\)
那么對於隨機一個數,比如1.128來說,因為(8,3)定點數的精度為0.125,所以會丟失一些精度,所以我們需要先對其進行量化,我們可以先將1.128乘上\(2^3\),按照上面定點數的展開形式可以看出,這時數字中已經沒有小數部分(最后一位\(2^{-3}\)已經被消去),\(1.128 \times 8 = 9.024\),這時結果中的小數部分即為1.128中不能被量化的部分,我們對9.024取整即為我們對小數進行量化后的結果9,然后我們可以再對9處於\(2^{3}\),轉換為小數形式\(9 / {2^3}=1.125\),再對其進行定點數的換算,當然可以直接用量化后的9乘上定點數的精度來進行換算。
定點數實際上就是精度數,而十進制小數可以寫成
\(精度數 \times 定點數的精度\)
\(9 \times 0.125 = 1.125\)
定點數的運算
先以10進制為例。
如果我們能夠計算12+34=46的話,當然也就能夠計算1.2+3.4 或者 0.12+0.34了。所以定點小數的加減法和整數的相同,並且和小數點的位置無關。乘法就不同了。
12*34=408,而1.2*3.4=4.08。這里1.2的小數點在第1位之前,而4.08的小數點在第2位之前,小數點發生了移動。所以在做乘法的時候,需要對小數點的位置進行調整?!
可是既然我們是做定點小數運算,那就說小數點的位置不能動!!怎么解決這個矛盾呢,那就是舍棄最低位。
也就說1.2*3.4=4.1,這樣我們就得到正確的定點運算的結果了。所以在做定點小數運算的時候不僅需要牢記小數點的位置,還需要記住表達定點小數的有效位數。上面這個例子中,有效位數為2,小數點之后有一位。
對於定點小數的乘法運算,需要舍棄最低位,相應的就是向右進行移位,移位到我們規定的小數位數上(對於上面的例子要保證小數的位數為1位),向右移位等同於直接對數進行相除,我們也可以直接對乘法結果進行相除。
一個例子比較直觀
對於2.1和2.2進行(13,12)的量化
\(2.1 *2^{12}=8601.6=8602\)
\(2.2 * 2^{12} = 9011.2 = 9011\)
兩個定點數直接相乘
\(2.1 * 2^{12} * 2.2 * 2^{12}\)
與我們想要的結果\(2.1 * 2.2 * 2^{12}\)多乘上了一個\(2^{12}\),
所以需要將定點數直接相乘的結果除於\(2^{12}\)
參考引用
(21條消息) 針對FPGA的數據量化_nice_2808的博客-CSDN博客_fpga 量化
FPGA內部計算小數 - 天馬行空W - 博客園 (cnblogs.com)