數字積體電路設計---除法運算
阿新 • • 發佈:2019-02-15
實現演算法
基於減法的除法器的演算法:
對於32的無符號除法,被除數a除以除數b,他們的商和餘數一定不會超過32位。首先將a轉換成高32位為0,低32位為a的temp_a。把b轉換成高32位為b,低32位為0的temp_b。在每個週期開始時,先將temp_a左移一位,末尾補0,然後與b比較,是否大於b,是則temp_a減去temp_b將且加上1,否則繼續往下執行。上面的移位、比較和減法(視具體情況而定)要執行32次,執行結束後temp_a的高32位即為餘數,低32位即為商。
verilog HDL程式碼
[html] view plain copy print?- /*
- * module:div_rill
- * file name:div_rill.v
- * syn:yes
- * author:network
- * modify:rill
- * date:2012-09-07
- */
- module div_rill
- (
- input[31:0] a,
- input[31:0] b,
- output reg [31:0] yshang,
- output reg [31:0] yyushu
- );
- reg[31:0] tempa;
- reg[31:0] tempb;
- reg[63:0] temp_a;
-
reg[63:0] temp_b;
- integer i;
- always @(a or b)
- begin
- tempa <= a;
- tempb <= b;
- end
- always @(tempa or tempb)
- begin
- temp_a = {32'h00000000,tempa};
- temp_b = {tempb,32'h00000000};
- for(i = 0;i <32;i = i + 1)
- begin
- temp_a = {temp_a[62:0],1'b0};
-
if(temp_a[63:32] >
- temp_a = temp_a - temp_b + 1'b1;
- else
- temp_a = temp_a;
- end
- yshang <= temp_a[31:0];
- yyushu <= temp_a[63:32];
- end
- endmodule
- /*************** EOF ******************/
改進
1,將組合邏輯改成時序邏輯,用32個clk實現計算。
2,計算位寬可以配置,具有擴充套件性。
附錄:演算法推倒(非原創):
假設4bit的兩數相除 a/b,商和餘數最多隻有4位 (假設1101/0010也就是13除以2得6餘1)
我們先自己做二進位制除法,則首先看a的MSB,若比除數小則看前兩位,大則減除數,然後看餘數,以此類推直到最後看到LSB;而上述演算法道理一樣,a左移進前四位目的就在於從a本身的MSB開始看起,移4次則是看到LSB為止,期間若比除數大,則減去除數,注意減完以後正是此時所剩的餘數。而商呢則加到了這個數的末尾,因為只要比除數大,商就是1,而商0則是直接左移了,因為會自動補0。這裡比較巧因為商可以隨此時的a繼續左移,然後新的商會繼續加到末尾。經過比對會發現移4位後左右兩邊分別就是餘數和商。
畫個簡單的圖:
1,改成clk方式。 2,新增clk,50MHz。 3, 新增rst,同步復位。 4,新增calc_done,指示計算完成,高有效。
3.1 模組程式碼
[html] view plain copy print?- /*
- * module:div_rill
- * file name:div_rill.v
- * syn:yes
- * author:network
- * modify:rill
- * date:2012-09-10
- */
- module div_rill
- (
- input clk,
- input rst,
- input[31:0] a,
- input[31:0] b,
- output reg [31:0] yshang,
- output reg [31:0] yyushu,
- output reg calc_done
- );
- reg[31:0] tempa;
- reg[31:0] tempb;
- reg[63:0] temp_a;
- reg[63:0] temp_b;
- reg [5:0] counter;
- always @(a or b)
- begin
- tempa <= a;
- tempb <= b;
- end
- always @(posedge clk)
- begin
- if(!rst)
- begin
- temp_a <= 64'h0000_0000_0000_0000;
- temp_b <= 64'h0000_0000_0000_0000;
- calc_done <= 1'b0;
- end
- else
- begin
- if(counter <= 31)
- begin
- temp_a <= {temp_a[62:0],1'b0};
- if(temp_a[63:32] >= tempb)
- begin
- temp_a <= temp_a - temp_b + 1'b1;
- end
- else
- begin
- temp_a <= temp_a;
- end
- counter <= counter + 1;
- calc_done <= 1'b0;
- end
- else
- begin
- counter <= 0;
- calc_done <= 1'b1;
- temp_a <= {32'h00000000,tempa};
- temp_b <= {tempb,32'h00000000};
- yshang <= temp_a[31:0];
- yyushu <= temp_a[63:32];
- end
- end
- end
- endmodule
- /*************** EOF ******************/