數字訊號處理中,有大量的演算法是基於迭代演算法,即下一次的運算需要上一次運算的結果,將運算部分固化為迭代單元可以將資料處理和流程控制區分,更容易做出時序和面積優化更好的硬體描述,這次將基於迭代單元構造恢復餘數和不恢復餘數除法器
演算法將除數移位i位
判斷位移後的除數與餘數大小
若位移除數大於餘數,則餘數輸出當前餘數,結果輸出0;否則輸出餘數減位移除數,結果輸出1
恢復餘數除法器cell(來自《基於fpga的數字訊號處理》)
rtl**
module restore_cell #(
parameter width = 4,
parameter step = 1
)( input clk,
input rst_n,
input [width * 3 - 1:0]remainder_din,
input [width - 1:0]divisor,
output reg [width * 3 - 1:0]remainder_dout,
output reg quotient
);wire [width * 3:0]divisor_exd = ';
wire [width * 3:0]sub = - (divisor_exd << step);
always @ (posedge clk or negedge rst_n) begin
if(~rst_n) begin
<= 'b0;
end else begin
if(sub[width * 3] == 1'b0) begin
remainder_dout = sub;
end else begin
remainder_dout = remainder_din;
endquotient = ~(sub[3 * width]);
endendendmodule
module restore_cell_divider #(
parameter width = 4
)( input clk, // clock
input rst_n, // asynchronous reset active low
input [2 * width - 1:0]dividend,
input [width - 1:0]divisor,
output [2 * width - 1:0]dout,
output [width - 1:0]remainder
);genvar i;
generate
for (i = 2 * width - 1; i >= 0; i = i - 1) begin:restore
wire [3 * width - 1:0]last_remaider;
wire [3 * width - 1:0]this_remaider;
if(i == 2 * width - 1) begin
assign last_remaider = ';
end else begin
assign last_remaider = restore[i + 1].this_remaider;
endrestore_cell #(
.width(width),
.step(i)
) u_restore_cell (
.clk(clk),
.rst_n(rst_n),
.remainder_din(last_remaider),
.divisor(divisor),
.remainder_dout(this_remaider),
.quotient(dout[i])
);end
endgenerate
assign remainder = restore[0].this_remaider[width - 1:0];
endmodule
演算法
將除數移位i位
若餘數大於0,餘數輸出餘數減移位除數;否則餘數輸出餘數加移位除數。結果輸出餘數符號位取反
不恢復餘數除法器cell(來自《基於fpga的數字訊號處理》
rtl**
module norestore_cell #(
parameter width = 4,
parameter step = 1
)( input clk,
input rst_n,
input [width * 3:0]remainder_din,
input [width - 1:0]divisor,
output reg [width * 3:0]remainder_dout,
output reg quotient
);wire [width * 3:0]divisor_exd = ';
wire [width * 3:0]divisor_move = divisor_exd << step;
wire [width * 3:0]sub = remainder_din - divisor_move;
wire [width * 3:0]add = remainder_din + divisor_move;
always @ (posedge clk or negedge rst_n) begin
if(~rst_n) begin
<= 'b0;
end else begin
if(remainder_din[3 * width] == 'b0) begin
remainder_dout = sub;
quotient = ~(sub[3 * width]);
end else begin
remainder_dout = add;
quotient = ~(add[3 * width]);
endend
endendmodule
module norestore_cell_divider #(
parameter width = 4
)( input clk, // clock
input rst_n, // asynchronous reset active low
input [2 * width - 1:0]dividend,
input [width - 1:0]divisor,
output [2 * width - 1:0]dout,
output reg [width - 1:0]remainder
);genvar i;
generate
for (i = 2 * width - 1; i >= 0; i = i - 1) begin:restore
wire [3 * width:0]last_remaider;
wire [3 * width:0]this_remaider;
if(i == 2 * width - 1) begin
assign last_remaider = ';
end else begin
assign last_remaider = restore[i + 1].this_remaider;
endnorestore_cell #(
.width(width),
.step(i)
) u_restore_cell (
.clk(clk),
.rst_n(rst_n),
.remainder_din(last_remaider),
.divisor(divisor),
.remainder_dout(this_remaider),
.quotient(dout[i])
);end
endgenerate
wire [3 * width:0]remainder_final = restore[0].this_remaider;
always @ (*) begin
if(remainder_final[3 * width] == 1'b0) begin
remainder = remainder_final[width - 1:0];
end else begin
remainder = remainder_final[width - 1:0] + divisor;
endendendmodule
需要注意的是,不恢復餘數除法器最後需要調整餘數為 fpga除法器的設計要點
fpga中除法器的設計 在fpga中除法器可通過位移比較實現,通過觸發器的設計使面積功耗不會因為位數的變化有較大的變動,位數設定最好用引數進行設定這樣可以在上層模組中對位數進行重定義,防止對引腳的浪費。演算法解析 當輸入確認訊號來臨時,商和餘數,及所有暫存器被全部清零,新一輪計算開始,計數器cnt賦...
基於迭代單元的恢復餘數開方器
該開方器的演算法與 手算 以前並不知道開方還有這種手算的方法 演算法相似,使用迭代解決,文字描述如下 將0為餘數的初值a,0作為結果初值b將被開方數前兩位取出,與01比較大小。若前兩位大,則 01為輸出餘數 a m 輸出結果1 b m 否則為輸出餘數 a m 輸出結果0 b m 將被開方數的從高位數...
基於ARMv5TE架構的軟體除法
近來有點悠閒,所以無聊中做了乙個基於二進位制試商法的無符號整型除法實現。以下函式僅對於armv5t架構或更高版本架構的處理器有效。彙編用的是rvct3.1或更高版本 演算法彙編檔案 1 area my test,code,readonly 23 preserve8 45 export my udiv...