1. 程式人生 > >數字積體電路設計---除法運算

數字積體電路設計---除法運算

實現演算法

基於減法的除法器的演算法:

        對於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?
  1. /*  
  2. * module:div_rill  
  3. * file name:div_rill.v  
  4. * syn:yes  
  5. * author:network  
  6. * modify:rill  
  7. * date:2012-09-07  
  8. */  
  9. module div_rill  
  10. (  
  11. input[31:0] a,   
  12. input[31:0] b,  
  13. output reg [31:0] yshang,  
  14. output reg [31:0] yyushu  
  15. );  
  16. reg[31:0] tempa;  
  17. reg[31:0] tempb;  
  18. reg[63:0] temp_a;  
  19. reg[63:0] temp_b;  
  20. integer i;  
  21. always @(a or b)  
  22. begin  
  23.     tempa <= a;  
  24.     tempb <= b;  
  25. end  
  26. always @(tempa or tempb)  
  27. begin  
  28.     temp_a = {32'h00000000,tempa};  
  29.     temp_b = {tempb,32'h00000000};   
  30.     for(i = 0;i <32;i = i + 1)  
  31.         begin  
  32.             temp_a = {temp_a[62:0],1'b0};  
  33.             if(temp_a[63:32] >
    = tempb)  
  34.                 temp_a = temp_a - temp_b + 1'b1;  
  35.             else  
  36.                 temp_a = temp_a;  
  37.         end  
  38.     yshang <= temp_a[31:0];  
  39.     yyushu <= temp_a[63:32];  
  40. end  
  41. endmodule  
  42. /*************** 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?在CODE上檢視程式碼片派生到我的程式碼片
  1. /*  
  2. * module:div_rill  
  3. * file name:div_rill.v  
  4. * syn:yes  
  5. * author:network  
  6. * modify:rill  
  7. * date:2012-09-10  
  8. */  
  9. module div_rill  
  10. (  
  11. input clk,  
  12. input rst,  
  13. input[31:0] a,   
  14. input[31:0] b,  
  15. output reg [31:0] yshang,  
  16. output reg [31:0] yyushu,  
  17. output reg calc_done  
  18. );  
  19. reg[31:0] tempa;  
  20. reg[31:0] tempb;  
  21. reg[63:0] temp_a;  
  22. reg[63:0] temp_b;  
  23. reg [5:0] counter;  
  24. always @(a or b)  
  25. begin  
  26.     tempa <= a;  
  27.     tempb <= b;  
  28. end  
  29. always @(posedge clk)  
  30. begin  
  31.     if(!rst)  
  32.         begin  
  33.             temp_a <= 64'h0000_0000_0000_0000;  
  34.             temp_b <= 64'h0000_0000_0000_0000;     
  35.             calc_done <= 1'b0;  
  36.         end  
  37.     else  
  38.         begin  
  39.             if(counter <= 31)  
  40.                 begin  
  41.                     temp_a <= {temp_a[62:0],1'b0};  
  42.                     if(temp_a[63:32] >= tempb)  
  43.                         begin  
  44.                             temp_a <= temp_a - temp_b + 1'b1;  
  45.                         end  
  46.                     else  
  47.                         begin  
  48.                             temp_a <= temp_a;  
  49.                         end  
  50.                     counter <= counter + 1;  
  51.                     calc_done <= 1'b0;  
  52.                 end  
  53.             else  
  54.                 begin  
  55.                     counter <= 0;  
  56.                     calc_done <= 1'b1;  
  57.                     temp_a <= {32'h00000000,tempa};  
  58.                     temp_b <= {tempb,32'h00000000};   
  59.                     yshang <= temp_a[31:0];  
  60.                     yyushu <= temp_a[63:32];  
  61.                 end  
  62.         end  
  63. end  
  64. endmodule  
  65. /*************** EOF ******************/