前言
FPGA定點數計算在高效資源利用、運算速度優勢、硬件可預測性和成本效益等方面發揮著重要作用。它能節省邏輯和存儲資源,實現更快速的運算和更高的時鐘頻率,保證行為可預測且易于硬件實現和驗證,同時降低硬件和開發成本,廣泛應用于數字信號處理、工業控制、通信系統等領域。
基本定義
定義有符號寫法和無符號數寫法,其中定義和說明如下所示
| 符號類型 | 有符號定點數 | 無符號定點數 |
|---|---|---|
| 簡寫 | F/Q10.6 | UF/UQ10.6 |
| 數據位寬 | 10+6=16bit | 1+9+6=16bit |
| 符號位 | 無 | 最高位 |
| 說明 | 其中前10位表示整數位寬,后6位為小數位寬。其中整數的取值范圍0?450-4^50?45,小數位的精度為(1/(26))(1/(2^6))(1/(26))。 |
其中最高位為符號位,之后的9位表示整數位寬,最后后6位為小數位寬。 其中整數的取值范圍0?290-2^90?29,小數位的精度為(1/(26))(1/(2^6))(1/(26))。 |
計算方式
計算流程
將兩個相乘實數RA RB數據轉化成對應=>UFa.b/Fa.b 格式數據: 先乘小數2b2^b2b
將轉化后的兩個定點數進行相乘
將相乘的結果進行位移操作,換算QA QB格式數據
在將QA QB定點數據格式進行移位得到實數RA RB,這個實數會損失精度
任意無符號定點數與任意無符號定點數相乘(無符號)
| 無符號定點數 | 無符號定點數 |
|---|---|
| QA=UFa.b | QB=UFn.m |
| QA=UF9.7 | QB=UF1.15 |
| RA=5.3 | RB=0.2 |
| 下面是計算過程 |
| 流程 | 定點數計算過程 | 實數計算數值 |
|---|---|---|
| 開始 | — | RA=5.3 RB=0.2 |
| 1 | QA=RA×2b=QAQA={RA×2^b=QA}QA=RA×2b=QA |QB=RB×2m=QBQB= {RB×2^m = QB}QB=RB×2m=QB | QA=678 QB=6553 |
| 2 | (UQ(a+n).(b+m))=QA?QB(UQ(a+n).(b+m))=QA*QB(UQ(a+n).(b+m))=QA?QB | QA×QB=8×6553.6=52428 |
| 3 | QA=QA?QB>>mQA=QA*QB>>mQA=QA?QB>>m |QB=QA?QB>>bQB=QA*QB>>bQB=QA?QB>>b | QA=QAQB>>15=135 QB=QAQB>>7=34734 |
| 4 | RA=(UQa.b)>>bRA=(UQa.b)>>bRA=(UQa.b)>>b |RB=(UQn.m)>>mRB=(UQn.m)>>mRB=(UQn.m)>>m | RA=(QA=UQ9.7)>>7=1 |RB=(QB=UQ1.15)>>15=1 |
任意有符號定點數與任意有符號定點數相乘
| 有符號定點數 | 有符號定點數 |
|---|---|
| QA=Fa.b | QB=Fn.m |
| QA=F3.4 | QB=F2.3 |
| RA=1.5 | RB=-2.25 |
| 下面是計算過程 | |
| 實數計算中,若數據為負數,數據左移后將最高位補1, |
| 流程 | 定點數計算過程 | 實數計算數值 |
|---|---|---|
| 開始 | — | RA=1.5 RB=-2.25 |
| 1 | QA=RA×2b=QAQA={RA×2^b=QA}QA=RA×2b=QA |QB=RB×2m=QBQB= {RB×2^m = QB}QB=RB×2m=QB | QA=24 QB=46 |
| 2 | (Q(a+n).(b+m))=QA?QB(Q(a+n).(b+m))=QA*QB(Q(a+n).(b+m))=QA?QB | QA×QB=15952 |
| 3 | QA=QA?QB>>mQA=QA*QB>>mQA=QA?QB>>m |QB=QA?QB>>bQB=QA*QB>>bQB=QA?QB>>b | QA=QAQB>3=202 QB=QAQB>>4=37 |
| 4 | RA=(Qa.b)>>bRA=(Qa.b)>>bRA=(Qa.b)>>b |RB=(Qn.m)>>mRB=(Qn.m)>>mRB=(Qn.m)>>m | RA=QA>>4=-3.375| RB=QB>>3=-3.375 |
小技巧
注意整數損失和小數精度損失
在進行定點數據計算前,需要人為考慮定點數計算后數據損失情況,若F(16.0)與F(1,15)相乘,如果使用F(17.15)數據不會損失太多信息
如果將F(17.15)=>F(16.0)則會損失小數精度。
如果將F(17.15)=>F(1.15)則會損失整數16位信息。
小數符號位的計算方法
在整個有符號數據計算時,所有的數據按照補碼來計算,其中含負數和符號位乘法如下圖所示。
FPGA中截斷定點數位寬
在進行定點數據計算時,有可能會出現輸出不同精度數據情況,例如若F(8.8)與F(5,11)相乘,產生F(13,19),但是我需要輸出F(6,10)這種精度。一般操作過程如下所示
如果將F(13,19)左移9位,變成F(13.9),在截斷整數位,變成F(6,10)。
有符號定點數進行截位后注意符號位
FPGA中擴展定點數位寬
在進行定點數據計算時,有可能會出現將低精度數據擴展到高精度數據情況操作,例如若F(8.8)不通過乘法轉換成F(9,13)。
整數部分:如果為負數,最高位補1,如果為正數,最高位補0。
小數部分:小數只需要補0即可。
有符號定點數進行截位后注意符號位
無符號與有符號數據實現
1在信號輸入端,人為將無符號數通過assign或者always將無符號數據轉換成有符號數,在進行運算。
無符號定點數乘法模塊
//無符號數據乘法模塊
module unsigned_fixed_point_multiplication#(
parameter P_A_DATA_DW = 16,
P_A_POINT_DW = 8,
P_B_DATA_DW = 16,
P_B_POINT_DW = 8 ,
P_Q_DW =P_A_DATA_DW +P_B_DATA_DW
)
(
input i_clk , // 時鐘
input i_rst , // 復位
input wire [P_A_DATA_DW - 1:0] i_unsgined_a , // 第一個無符號定點數
input wire [P_B_DATA_DW - 1:0] i_unsgined_b , // 第二個無符號定點數
input wire i_unsgined_ab_vld , // 數據有效位
output wire [P_A_DATA_DW - 1:0] o_unsgined_cov_a , // 第一個無符號定點數類型結果
output wire [P_B_DATA_DW - 1:0] o_unsgined_cov_b , // 第二個無符號定點數類型結果
output wire o_unsgined_ab_vld , // 數據輸出有效位
output wire [P_Q_DW - 1 :0] o_unsgined_c , // 不做刪減的數據輸出
output wire o_unsgined_c_vld // 數據輸出有效位
);
localparam P_POINT_DW = P_A_POINT_DW + P_B_POINT_DW ;
reg [P_A_DATA_DW - 1:0] ri_unsgined_a ;
reg [P_B_DATA_DW - 1:0] ri_unsgined_b ;
reg ri_unsgined_ab_vld ;
reg [P_A_DATA_DW - 1:0] ro_unsgined_cov_a ;
reg [P_B_DATA_DW - 1:0] ro_unsgined_cov_b ;
reg ro_unsgined_ab_vld ;
reg [P_Q_DW - 1 :0] ro_unsgined_c ;
reg ro_unsgined_c_vld ;
assign o_unsgined_cov_a = ro_unsgined_cov_a ;
assign o_unsgined_cov_b = ro_unsgined_cov_b ;
assign o_unsgined_ab_vld = ro_unsgined_ab_vld ;
assign o_unsgined_c = ro_unsgined_c ;
assign o_unsgined_c_vld = ro_unsgined_c_vld ;
//數據暫存
always @(posedge i_clk or posedge i_rst) begin
if (i_rst) begin
ri_unsgined_a <= 'd0;
ri_unsgined_b <= 'd0;
ri_unsgined_ab_vld <= 'd0;
end else begin
ri_unsgined_a <= i_unsgined_a ? ? ? ;
ri_unsgined_b <= i_unsgined_b ? ? ? ;
ri_unsgined_ab_vld <= i_unsgined_ab_vld ?;
end
end
// 執行乘法運算
always @(posedge i_clk or posedge i_rst) begin
if (i_rst) begin
ro_unsgined_c <= 'd0;
ro_unsgined_c_vld <= 'd0;
end else if(ri_unsgined_ab_vld)begin
ro_unsgined_c <= ri_unsgined_a * ri_unsgined_b;
ro_unsgined_c_vld <= ri_unsgined_ab_vld;
end else begin
ro_unsgined_c <= ro_unsgined_c;?
ro_unsgined_c_vld <= ?1'd0;
end
end
// 調整小數點位置
// 注意:這里沒有進行舍入處理,根據需要可能需要添加
// 執行乘法運算
always @(posedge i_clk or posedge i_rst) begin
if (i_rst) begin
ro_unsgined_cov_a <= 'd0;
ro_unsgined_cov_b <= 'd0;
ro_unsgined_ab_vld <= 'd0;
end else if(ro_unsgined_c_vld)begin
ro_unsgined_cov_a <= ro_unsgined_c>>P_B_POINT_DW;
ro_unsgined_cov_b <= ro_unsgined_c>>P_A_POINT_DW;
ro_unsgined_ab_vld <= ro_unsgined_c_vld;
end else begin
ro_unsgined_cov_a <= ro_unsgined_cov_a;?
ro_unsgined_cov_b <=ro_unsgined_cov_b;
ro_unsgined_ab_vld <= ?1'd0;
end
end
endmodule
有符號定點數乘法模塊
//有符號數據乘法模塊
module signed_fixed_point_multiplication#(
parameter P_A_DATA_DW = 8,
P_A_POINT_DW = 4,
P_B_DATA_DW = 6,
P_B_POINT_DW = 3 ,
P_Q_DW =P_A_DATA_DW +P_B_DATA_DW
)
(
input i_clk ,
input i_rst ,
input wire signed [P_A_DATA_DW - 1:0] i_sgined_a ,
input wire signed [P_B_DATA_DW - 1:0] i_sgined_b ,
input wire i_sgined_ab_vld ,
output wire signed [P_A_DATA_DW - 1:0] o_sgined_cov_a ,
output wire signed [P_B_DATA_DW - 1:0] o_sgined_cov_b ,
output wire o_sgined_ab_vld ,
output wire signed [P_Q_DW - 1 :0] o_sgined_c ,
output wire o_sgined_c_vld
);
reg signed [P_A_DATA_DW - 1:0] ri_sgined_a ;
reg signed [P_B_DATA_DW - 1:0] ri_sgined_b ;
reg ri_sgined_ab_vld ;
reg signed [P_A_DATA_DW - 1:0] ro_sgined_cov_a ;
reg signed [P_B_DATA_DW - 1:0] ro_sgined_cov_b ;
reg ro_sgined_ab_vld ;
reg signed [P_Q_DW - 1 :0] ro_sgined_c ;
reg ro_sgined_c_vld ;
assign o_sgined_cov_a = ro_sgined_cov_a ;
assign o_sgined_cov_b = ro_sgined_cov_b ;
assign o_sgined_ab_vld = ro_sgined_ab_vld ;
assign o_sgined_c = ro_sgined_c ;
assign o_sgined_c_vld = ro_sgined_c_vld ;
//數據暫存
always @(posedge i_clk or posedge i_rst) begin
if (i_rst) begin
ri_sgined_a <= 'd0;
ri_sgined_b <= 'd0;
ri_sgined_ab_vld <= 'd0;
end else begin
ri_sgined_a <= i_sgined_a ? ? ? ;
ri_sgined_b <= i_sgined_b ? ? ? ;
ri_sgined_ab_vld <= i_sgined_ab_vld ?;
end
end
// 執行乘法運算
always @(posedge i_clk or posedge i_rst) begin
if (i_rst) begin
ro_sgined_c <= 'd0;
ro_sgined_c_vld <= 'd0;
end else if(ri_sgined_ab_vld)begin
ro_sgined_c <= ri_sgined_a * ri_sgined_b;
ro_sgined_c_vld <= ri_sgined_ab_vld;
end else begin
ro_sgined_c <= ro_sgined_c;?
ro_sgined_c_vld <= ?1'd0;
end
end
// 調整小數點位置
// 注意:這里沒有進行舍入處理,根據需要可能需要添加
// 執行乘法運算
always @(posedge i_clk or posedge i_rst) begin
if (i_rst) begin
ro_sgined_cov_a <= 'd0;
ro_sgined_cov_b <= 'd0;
ro_sgined_ab_vld <= 'd0;
end else if(ro_sgined_c_vld)begin
ro_sgined_cov_a <= ro_sgined_c>>P_B_POINT_DW;
ro_sgined_cov_b <= ro_sgined_c>>P_A_POINT_DW;
ro_sgined_ab_vld <= ro_sgined_c_vld;
end else begin
ro_sgined_cov_a <= ro_sgined_cov_a;?
ro_sgined_cov_b <=ro_sgined_cov_b;
ro_sgined_ab_vld <= ?1'd0;
end
end
endmodule
-
FPGA
+關注
關注
1656文章
22317瀏覽量
631097 -
數字信號
+關注
關注
2文章
1055瀏覽量
48996 -
符號
+關注
關注
0文章
56瀏覽量
4724
原文標題:FPGA定點數計算
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
固定點數運算案例的程序
【安富萊——DSP教程】第7章 DSP定點數和浮點數(重要)
第7章 DSP定點數和浮點數
請問28335浮點數使用IQmath轉換后當定點數計算快還是用浮點數進行計算快?28335可以定點浮點混合編程嗎?
6618虛擬定點數學庫IQmath
verilog程序定點數的資料
DSP功能函數-定點數互轉
在定點數運算中產生溢出的原因是什么
定點數和浮點數的區別是什么
LabVIEW中定點數有什么用途?LabVIEW中定點數應用解析
FPGA定點數截位的基本準則

詳解FPGA定點數計算方法
評論