基于减法操作除法器的算法---Verilog实现

除法器在FPGA里怎么实现呢?当然不是让用“/”和“%”实现;
在Verilog HDL语言中虽然有除的运算指令,但是除运算符中的除数必须是2的幂,因此无法实现除数为任意整数的除法,很大程度上限制了它的使用领域。并且多数综合工具对于除运算指令不能综合出令人满意的结果,有些甚至不能给予综合。即使可以综合,也需要比较多的资源。对于这种情况,一般使用相应的算法来实现除法,分为两类:基于减法操作和基于乘法操作的算法

实现算法

基于减法的除法器的算法:
        对于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位即为商

算法推倒(非原创):
假设4bit的两数相除 a/b,商和余数最多只有4位 (假设1101/0010也就是13除以2得6余1)

我们先自己做二进制除法,则首先看a的MSB,若比除数小则看前两位,大则减除数,然后看余数,以此类推直到最后看到LSB;而上述算法道理一样,a左移进前四位目的就在于从a本身的MSB开始看起,移4次则是看到LSB为止,期间若比除数大,则减去除数,注意减完以后正是此时所剩的余数。而商呢则加到了这个数的末尾,因为只要比除数大,商就是1,而商0则是直接左移了,因为会自动补0。这里比较巧因为商可以随此时的a继续左移,然后新的商会继续加到末尾。经过比对会发现移4位后左右两边分别就是余数和商。

画个简单的图:

1.时序逻辑除法

module div_timing_logic(
                        input               I_clk,
                        input               I_rst_p,
                        input               I_data_valid,
                        input       [7:0]   I_data_a,
                        input       [7:0]   I_data_b,
                        output reg          O_data_valid,
                        output reg [7:0]    O_data_shang,
                        output reg [7:0]    O_data_yushu

    );
reg  [7:0]   tempa;
reg  [7:0]   tempb;
reg  [15:0]  temp_a;
reg  [15:0]  temp_b;
reg          div_start;
reg          div_start_d1;
wire         div_start_neg;
reg  [4:0]   div_cnt;

always@(posedge I_clk or posedge I_rst_p)
   begin
      if(I_rst_p)
         begin
            tempa <= 8'h0;            
            tempb <= 8'h0;            
         end
      else if(I_data_valid)
         begin
            tempa <= I_data_a;            
            tempb <= I_data_b;            
         end
      else
         begin
            tempa <= tempa;            
            tempb <= tempb;            
         end
   end

always@(posedge I_clk or posedge I_rst_p)
   begin
      if(I_rst_p)
         div_start <= 1'b0;
      else if(I_data_valid && div_start == 1'b0)
         div_start <= 1'b1;
      else if(div_cnt == 5'd16 )
         div_start <= 1'b0;
      else
          div_start <= div_start;
   end
//========================================================div_cnt
always@(posedge I_clk or posedge I_rst_p)
   if(I_rst_p)
      div_cnt <= 5'd0;
   else if(div_start)
      div_cnt <= div_cnt + 1;
   else
      div_cnt <= 5'd0;
//=======================================================           
always@(posedge I_clk or posedge I_rst_p)
   begin
      if(I_rst_p)
         begin
            temp_a <= 16'h0;
            temp_b <= 16'h0;            
         end
      else if(div_start )
         if(div_cnt == 4'd0)
            begin
               temp_a <= {8'h0,tempa};
               temp_b <= {tempb,8'h0};
            end
         else if(div_cnt[0] == 1'b1)
            begin
               temp_a <= {temp_a[14:0],1'b0};
            end
         else
            begin
               temp_a <= (temp_a[15:8] >= temp_b[15:8])?(temp_a - temp_b + 1):temp_a;//如果比temp_b大,则减去temp_b然后加1
            end
      else
         begin
            temp_a <= 16'h0;
            temp_b <= 16'h0;              
         end

   end
always@(posedge I_clk)
   begin
      div_start_d1 <= div_start;
   end
assign div_start_neg = div_start_d1 & (~div_start);//下降沿检测

always@(posedge I_clk or posedge I_rst_p)
   begin
      if(I_rst_p)
         begin
            O_data_valid <= 1'b0;
            O_data_shang <= 1'b0;
            O_data_yushu <= 1'b0;         
         end
      else if(div_start_neg)
         begin
            O_data_valid <= 1'b1;
            O_data_shang <= temp_a[7:0];
            O_data_yushu <= temp_a[15:8];              
         end
      else
         begin
            O_data_valid <= 1'b0;
            O_data_shang <= 1'b0;
            O_data_yushu <= 1'b0;          
         end
   end
endmodule

2.纯组合逻辑

module div_combinatory_logic
(
           input       [7:0]        a,//被除数
           input       [7:0]        b,//除数
           output reg  [7:0]        y_shang,//商
           output reg  [7:0]        y_yushu//余数
);

reg [7:0] tempa;
reg [7:0] tempb;
reg [15:0] temp_a;
reg [15:0] temp_b;

integer i;

always@(*)
   begin
      tempa = a;
      tempb = b;
   end

always@(*)
   begin
      temp_a = {8'h0,tempa};
      temp_b = {tempb,8'h0};
      for(i = 0; i < 8; i = i+1)         //注意是移动8次
         begin:shift_left
//            temp_a = temp_a << 1 ;
            temp_a = {temp_a[14:0],1'b0}  ;
            if(temp_a[15:8] >= temp_b[15:8] )//temp_b的低8位都是0,所以只需要比较高八位
               temp_a = temp_a - temp_b + 1;
            else
               temp_a = temp_a;
         end
       y_shang = temp_a[7:0];//商在低位
       y_yushu = temp_a[15:8];//余数在高位
   end


endmodule

 

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Verilog语言中实现除法器的方法一般有两种,基于减法操作和基于乘法操作算法。其中,基于乘法操作算法相对于基于减法操作算法来说,具有更高的效率和更少的资源占用。以下是一个基于乘法操作Verilog除法器的代码示例: ```verilog module divider( input clk, input signed [31:0] dividend, input signed [31:0] divisor, output signed [31:0] quotient, output signed [31:0] remainder ); reg signed [31:0] quotient_reg; reg signed [31:0] remainder_reg; reg signed [31:0] divisor_reg; reg signed [31:0] dividend_reg; reg signed [31:0] product_reg; reg signed [31:0] difference_reg; reg signed [31:0] one_reg; integer i; always @(posedge clk) begin if (dividend < 0) begin dividend_reg <= -dividend; end else begin dividend_reg <= dividend; end if (divisor < 0) begin divisor_reg <= -divisor; end else begin divisor_reg <= divisor; end product_reg <= dividend_reg * divisor_reg; quotient_reg <= 0; remainder_reg <= 0; one_reg <= 1; for (i = 31; i >= 0; i = i - 1) begin difference_reg <= product_reg - (divisor_reg << i); if (difference_reg >= 0) begin quotient_reg <= quotient_reg + (one_reg << i); product_reg <= difference_reg; end end if ((dividend < 0) ^ (divisor < 0)) begin quotient <= -quotient_reg; end else begin quotient <= quotient_reg; end if (dividend < 0) begin remainder <= -product_reg; end else begin remainder <= product_reg; end end endmodule ``` 该代码实现了一个带符号的32位除法器,输入为被除数和除数,输出为商和余数。在时钟上升沿触发时,除法器会将输入的被除数和除数转换为正数,并计算它们的乘积。然后,除法器使用一个循环来计算商,每次将除数左移一位,并将其与乘积相减,如果差值大于等于0,则将商的对应位设置为1。最后,除法器根据输入的符号位来确定输出的商和余数的符号。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值