(转帖)如何計算浮點數? (Verilog)
原创地址:http://www.cnblogs.com/oomusou/archive/2008/10/11/verilog_floating.html
Abstract
演算法常常會遇到浮點數運算,如何計算浮點數是Verilog初學者常問的問題。
Introduction
使用環境:Quartus II 8.0
在DE2的DE2_TV與DE2-70的DE2_70_TV範例中,有個YCbCr2RGB.v,負責將YCbCr轉成RGB,其公式如下:
G = 1.164(Y-16) - 0.391(Cb-128) - 0.813(Cr-128)
B = 1.164(Y-16) + 2.018(Cb-128)
將YCbCr轉成RGB牽涉到浮點數運算,這在Verilog是一項挑戰,並不像C那麼簡單,由於YCbCr2RGB.v比較複雜些,比較不適合當範例,而攝氏溫度轉華氏溫度可能是最簡單的浮點運算。
C為攝氏溫度,F為華氏溫度,我們來看看如何用Verilog實現。
CF2_bad.v / Verilog
2 input iCLK,
3 input iRST_N,
4 input [7:0] iC,
5 output [10:0] oF
6 );
7
8 reg [7:0] c;
9 reg [10:0] f;
10
11 assign oF = f;
12
13 always@(posedge iCLK, negedge iRST_N) begin
14 if (!iRST_N) begin
15 c <= 0;
16 f <= 0;
17 end
18 else begin
19 f <= c * 1.8 + 32;
20 end
21 end
22
23 endmodule
Quartus II編譯後,出現以下錯誤訊息:
看來Verilog果然不能直接使用浮點數做運算。
C2F_good.v / Verilog
2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : C2F_good.v
5 Compiler : Quartus II 8.0
6 Description : Demo how to calculate float;
7 Release : 10/11/2008 1.0
8 */
9
10 module C2F_good (
11 input iCLK,
12 input iRST_N,
13 input [7:0] iC,
14 output [10:0] oF
15 );
16
17 reg [7:0] c;
18 reg [10:0] f;
19 reg [10:0] sum;
20
21 assign oF = f;
22
23 always@(posedge iCLK, negedge iRST_N) begin
24 if (!iRST_N) begin
25 c <= 0;
26 f <= 0;
27 sum <= 0;
28 end
29 else begin
30 c <= iC;
31 sum <= c * 7 + 128;
32 f <= sum >> 2;
33 end
34 end
35
36 endmodule
模擬結果
除了第2個clock由於sum的值還沒來,所以32是錯的外,從第3個clock起的值都是對的。
合成結果
Fmax為237.19MHz
目前還沒用pipeline就已經237.19MHz,若加上pipeline還可更高。
31行
f <= sum >> 2;
關鍵程式碼只有這兩行,為什麼這樣就能計算浮點數呢?
原來的算式如下
現在將F向左移兩位,所以右邊每一項要乘以2 ^ 2 = 4 ,1.8 * 4 = 7.2,近似取7,32 * 4 = 128。
至於要放大幾位,並沒有一定的方式,由於shift的特性,只能放大2的n次方,讓浮點數放大後,能儘量接近整數即可。
32行
因為之前放大了4倍,所以在右移2位回來。
完整程式下載
C2F_good.7z
Conclusion
這種方式的優點是:速度快,且面積小,硬體容易實現,缺點是準確度較差,且受限於表示位數,必要時需搭配軟體模擬。
See Also
(原創) 如何使用Verilog將YCbCr轉RGB? (SOC) (Verilog) (DE2-70)