日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

FPGA除法实现

發布時間:2023/12/20 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 FPGA除法实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文主要通過兩種方法實現乘法器,一種是調用IP核方式,另一種是使用移位和減法的方式。

一、調用divider generator IP核

賽靈思pg151介紹了除法器IP的使用,簡單介紹:

除法器的實現主要有三種方式:LUTMult、Radix-2、High Radix。

1、LUTMult:使用除數的有限精度倒數組成的簡單查找表進行查找,然后乘以被除數。

A.使用DSP、塊RAM和少量FPGA邏輯實現。

B.僅支持輸出余數,不支持輸出分數。

C.推薦處理位寬低于12bits的數據

2、Radix-2:小學迭代除法計算方式,計算商和余數

A.使用FPGA邏輯實現。

B.支持輸出余數和分數兩種。

C.一般使用此種。

3、High Radix:在進行迭代除法之前,進行預縮放處理,可同時生成商多個bits數據

A.使用DPS、塊RAM實現。

B.支持輸出余數和分數兩種。

C.推薦處理位寬高于16bits的數據。

調用該IP核實,AXIS4_stream options—flow control中,Non blocking與blocking區別

Non blocking:非阻塞,此時IP核的S_AXIS_DIVISOR與S_AXIS_DIVIDEND不往外輸出axis_ready信號,流水線輸出,不判斷外部模塊是否接收數據

Blocking:阻塞,此時IP核S_AXIS_DIVISOR與S_AXIS_DIVIDEND輸出axis_ready信號,控制外部是否可以輸入除數與被除數。

二、IP核的仿真驗證

IP核參數配置:

module testbench(

????);

reg clk=1'b0;

reg [7:0]clk_cnt = 8'd0;

wire [23:0]m_axis_dout_tdata;

reg [15:0] dividend = 16'd0;//被除數

wire [7:0]divisor;

wire [15:0] quotient;//商

wire [7:0] remainder;//余數

always

begin

????#5 clk <= ~clk;

end

always@(posedge clk)

begin

????clk_cnt <= clk_cnt + 1'b1;

end

always@(posedge clk)

begin

????if(clk_cnt == 8'hFF) ???//間隔256個時鐘,被除數加1

????????dividend <= dividend + 1'b1;

end

assign divisor = 8'd11;

divid_ip divid_ip (

??.aclk(clk), ?????????????????????????????????????// input wire aclk

??.s_axis_divisor_tvalid(1'b1), ???// input wire s_axis_divisor_tvalid

??.s_axis_divisor_tdata(divisor), ?????// input wire [7 : 0] s_axis_divisor_tdata

??.s_axis_dividend_tvalid(1'b1), ?// input wire s_axis_dividend_tvalid

??.s_axis_dividend_tdata(dividend), ???// input wire [15 : 0] s_axis_dividend_tdata

??.m_axis_dout_tvalid(), ?????????// output wire m_axis_dout_tvalid

??.m_axis_dout_tdata(m_axis_dout_tdata) ???????????// output wire [23 : 0] m_axis_dout_tdata

);

assign ???quotient = ?m_axis_dout_tdata[23:8];

assign ???remainder = ?m_axis_dout_tdata[7:0];

endmodule

仿真結果如下:?

三、FPGA邏輯實現除法器

定義:

????????被除數:dividend[M-1:0]

????????除數:divisor[N-1:0]

計算可得:

????????商:quotient[M-1:0] ??位寬為M,與被除數相同

????????余數:remainder[N-1:0] ?位寬為N,與除數相同

????????????????

先行舉例說明:

????????被除數:dividend[7:0] ?= 8’d255 = 8’b1111_1111

????????除數: divisor[3:0] ? ?= 4’d11 = 4’b1011

表達如圖:

????????????????????????????????

?第一次運算:? ? ? 被除數最高位為1’b1,小于4’b1011,因此商最高位置為0;

????????????????????????????????????????

第二次運算:被除數高2位為2’b11,小于4’b1011,因此商次高位置為0;?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

????????????????????????????????????????????????????????????????????

第三次運算:被除數高3位為3’b111,小于4’b1011,因此商的高第3位為0

????????????????????????????????????????????????????????????????????

第四次運算:被除數高4位為4’b1111,大于4’b1011,因此將商的高第4位,為1,將4’b1111減去4’b1011,結果3’b100用于接下來的運算;

?

?第五次運算:將上一次運算的結果3’b100拼接商被除數高第5位數,組合成4’b1001。其小于4’b1011,因此商的高第5位為0;

?

?第六次運算:將上一次運算的結果4’b1001拼接被除數高第6位數,組合成4’b10011。其大于4’b1011,相減后結果為4’b1000,將商第6位置為1;

?

第七次運算:將上一次運算的結果4’b1000拼接被除數高第7位數,組合成4’b10001。其大于4’b1011,相減后結果為3’b110,將商第7位置為1;

?

第八次運算:將上一次運算的結果3’b110拼接被除數高第8位數,組合成4’b1101。其大于4’b1011,相減后結果為2’b10,將商第8位置為1;

?

最終得出,255÷11=23余2。

分析可知,商的位寬與被除數位寬一致,余數的位寬與除數的位寬一致。

四、FPGA邏輯實現除法器,并仿真驗證

module divid_gen(
? ? input clk,
? ? input calculate_en,
? ? input [7:0] dividend,
? ? input [3:0] divisor,
? ? output reg [7:0] quotient,
? ? output reg [3:0] remainder
? ? );

reg [3:0] shift_cnt;//被除數移位計算計數器

reg [7:0] dividend_reg; //鎖存dividend寄存器
reg [3:0] divisor_reg;//鎖存divisor寄存器

reg [7:0] quotient_reg;//商寄存器,用于緩存每次結算的商結果
reg [7:0] remainder_reg;//余數寄存器,用于緩存每次計算的余數結果

reg [1:0] state,next_state;
parameter IDLE_STATE = 2'b00;//空閑態
parameter CALC_STATE = 2'b01;//計算態
parameter END_STATE = 2'b10;//結束態

always@(posedge clk)
begin
? ? state <= next_state;
end

always@( * )
begin
? ? case(state)
? ? ? ? IDLE_STATE : begin
? ? ? ? ? ? if(calculate_en)
? ? ? ? ? ? ? ? next_state <= CALC_STATE;
? ? ? ? ? ? else
? ? ? ? ? ? ? ? next_state <= IDLE_STATE;
? ? ? ? end
? ? ? ? CALC_STATE : begin
? ? ? ? ? ? if(shift_cnt >= 8'd8) //移位8次,移位結束,8為被除數的數據寬度
? ? ? ? ? ? ? ? next_state <= END_STATE;
? ? ? ? ? ? else
? ? ? ? ? ? ? ? next_state <= CALC_STATE;
? ? ? ? end
? ? ? ? END_STATE : begin
? ? ? ? ? ? ? ? next_state <= IDLE_STATE;
? ? ? ? end
? ? ? ? default : begin
? ? ? ? ? ? ? ? next_state <= IDLE_STATE;
? ? ? ? end
? ? endcase
end

always@(posedge clk)
begin
? ? if((state == IDLE_STATE) & (calculate_en == 1'b1)) begin
? ? ? ? dividend_reg <= dividend;
? ? ? ? divisor_reg <= divisor;
? ? end
end

always@(posedge clk)
begin
? ? if(state == IDLE_STATE)
? ? ? ? shift_cnt <= 4'b0;
? ? else if(state == CALC_STATE)
? ? ? ? shift_cnt <= shift_cnt + 1'b1;
end

always@(posedge clk)
begin
? ? case(shift_cnt)
? ? ? ? 4'd0: begin //第一次運算
? ? ? ? ? ? if(dividend_reg[7] >= divisor) begin
? ? ? ? ? ? ? ? quotient_reg[7] <= 1'b1;
? ? ? ? ? ? ? ? remainder_reg[7:6] <= {(dividend_reg[7] - divisor),dividend_reg[6]};
? ? ? ? ? ? end ??
? ? ? ? ? ? else begin
? ? ? ? ? ? ? ? quotient_reg[7] <= 1'b0;
? ? ? ? ? ? ? ? remainder_reg[7:6] <= dividend_reg[7:6];
? ? ? ? ? ? end
? ? ? ? end
? ? ? ? 4'd1: begin //第二次運算
? ? ? ? ? ? if(remainder_reg[7:6] >= divisor) begin
? ? ? ? ? ? ? ? quotient_reg[6] <= 1'b1;
? ? ? ? ? ? ? ? remainder_reg[7:5] <= {(remainder_reg[7:6] - divisor),dividend_reg[5]};
? ? ? ? ? ? end ??
? ? ? ? ? ? else begin
? ? ? ? ? ? ? ? quotient_reg[6] <= 1'b0;
? ? ? ? ? ? ? ? remainder_reg[7:5] <= {remainder_reg[7:6],dividend_reg[5]};
? ? ? ? ? ? end
? ? ? ? end
? ? ? ? 4'd2: begin //第三次運算
? ? ? ? ? ? if(remainder_reg[7:5] >= divisor) begin
? ? ? ? ? ? ? ? quotient_reg[5] <= 1'b1;
? ? ? ? ? ? ? ? remainder_reg[7:4] <= {(remainder_reg[7:5] - divisor),dividend_reg[4]};
? ? ? ? ? ? end ??
? ? ? ? ? ? else begin
? ? ? ? ? ? ? ? quotient_reg[5] <= 1'b0;
? ? ? ? ? ? ? ? remainder_reg[7:4] <= {remainder_reg[7:5],dividend_reg[4]};
? ? ? ? ? ? end
? ? ? ? end
? ? ? ? 4'd3: begin //第四次運算
? ? ? ? ? ? if(remainder_reg[7:4] >= divisor) begin
? ? ? ? ? ? ? ? quotient_reg[4] <= 1'b1;
? ? ? ? ? ? ? ? remainder_reg[7:3] <= {(remainder_reg[7:4] - divisor),dividend_reg[3]};
? ? ? ? ? ? end ??
? ? ? ? ? ? else begin
? ? ? ? ? ? ? ? quotient_reg[4] <= 1'b0;
? ? ? ? ? ? ? ? remainder_reg[7:3] <= {remainder_reg[7:4],dividend_reg[3]};
? ? ? ? ? ? end
? ? ? ? end
? ? ? ? 4'd4: begin //第五次運算
? ? ? ? ? ? if(remainder_reg[7:3] >= divisor) begin
? ? ? ? ? ? ? ? quotient_reg[3] <= 1'b1;
? ? ? ? ? ? ? ? remainder_reg[7:2] <= {(remainder_reg[7:3] - divisor),dividend_reg[2]};
? ? ? ? ? ? end ??
? ? ? ? ? ? else begin
? ? ? ? ? ? ? ? quotient_reg[3] <= 1'b0;
? ? ? ? ? ? ? ? remainder_reg[7:2] <= {remainder_reg[7:3],dividend_reg[2]};
? ? ? ? ? ? end
? ? ? ? end
? ? ? ? 4'd5: begin //第六次運算
? ? ? ? ? ? if(remainder_reg[7:2] >= divisor) begin
? ? ? ? ? ? ? ? quotient_reg[2] <= 1'b1;
? ? ? ? ? ? ? ? remainder_reg[7:1] <= {(remainder_reg[7:2] - divisor),dividend_reg[1]};
? ? ? ? ? ? end ??
? ? ? ? ? ? else begin
? ? ? ? ? ? ? ? quotient_reg[2] <= 1'b0;
? ? ? ? ? ? ? ? remainder_reg[7:1] <= {remainder_reg[7:2],dividend_reg[1]};
? ? ? ? ? ? end
? ? ? ? end
? ? ? ? 4'd6: begin //第七次運算
? ? ? ? ? ? if(remainder_reg[7:1] >= divisor) begin
? ? ? ? ? ? ? ? quotient_reg[1] <= 1'b1;
? ? ? ? ? ? ? ? remainder_reg[7:0] <= {(remainder_reg[7:1] - divisor),dividend_reg[0]};
? ? ? ? ? ? end ??
? ? ? ? ? ? else begin
? ? ? ? ? ? ? ? quotient_reg[1] <= 1'b0;
? ? ? ? ? ? ? ? remainder_reg[7:0] <= {remainder_reg[7:1],dividend_reg[0]};
? ? ? ? ? ? end
? ? ? ? end
? ? ? ? 4'd7: begin //第八次運算
? ? ? ? ? ? if(remainder_reg[7:0] >= divisor) begin
? ? ? ? ? ? ? ? quotient_reg[0] <= 1'b1;
? ? ? ? ? ? ? ? remainder_reg[7:0] <= (remainder_reg[7:0] - divisor);
? ? ? ? ? ? end ??
? ? ? ? ? ? else begin
? ? ? ? ? ? ? ? quotient_reg[0] <= 1'b0;
? ? ? ? ? ? ? ? remainder_reg[7:0] <= remainder_reg[7:0];
? ? ? ? ? ? end
? ? ? ? end
? ? ? ? default :;
? ? endcase
end

always@(posedge clk)
begin
? ? if(state == END_STATE) begin
? ? ? ? quotient <= quotient_reg;
? ? ? ? remainder <= remainder_reg[4:0];
? ? end
end
? ??
endmodule
?

?

除法器使用位移和相減實現,同樣的,乘法器也可以使用位移與加法實現。更高效率的乘法與除法運算,復雜度較高,還是推薦使用IP核實現。

總結

以上是生活随笔為你收集整理的FPGA除法实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。