使用verilog基于减法实现16位无符号位除法,得到商和余数

(写本文的目的仅源于记笔记的想法,好记性不如烂笔头~)
参考来源:https://blog.youkuaiyun.com/alangaixiaoxiao/article/details/81624946

使用verilog基于减法实现无符号位除法,得到商和余数

1. 实现原理

对于16的无符号除法,被除数a除以除数b,他们的商和余数一定不会超过16位。首先将a转换成高16位为0,低16位为a的temp_a。把b转换成高16位为b,低16位为0的temp_b。在每个周期开始时,先将temp_a左移一位,末尾补0,然后与b比较,是否大于b,是则temp_a减去temp_b将且加上1,否则继续往下执行。上面的移位、比较和减法(视具体情况而定)要执行16次,执行结束后temp_a的高16位即为余数,低16位即为商。

手推说明无符号位4位除法的实现:
在这里插入图片描述
为啥要加1?????
即:
在这里插入图片描述

2组合逻辑实现代码

module chu2_CL_top(
   a,b,shang,yushu,enable, rst
    );
    input   rst,enable;
    input [15:0]  a,b;
    output[15:0]  shang,yushu;
    
    reg [15:0] temp_a1,temp_b1;
    reg [31:0] temp_a2,temp_b2;  
     integer i;
     
     always@(*)
        begin
        if(!rst)
        begin
          temp_a1 = 16'h0;
          temp_b1 = 16'h0;
        end
        else if(enable)             //赋初值
        begin
           temp_a1 = a;
           temp_b1 = b;
        end
        else
         begin
            temp_a1 = temp_a1;
            temp_b1 = temp_b1;
          end
        end
     
     always@(*)
     begin
        if(!rst)
        begin
          temp_a2 = 32'h0;
          temp_b2 = 32'h0;
        end
        else 
        begin
           temp_a2 = {16'h0,temp_a1};
           temp_b2 = {temp_b1,16'h0};
           for(i = 0; i < 16; i = i+1)         //除数左移位16次
              begin
                 temp_a2 = {temp_a2[30:0],1'b0}  ;
                 if(temp_a2[31:16] >= temp_b2[31:16] )
                    temp_a2 = temp_a2 - temp_b2 + 1;
                 else
                    temp_a2 = temp_a2;
              end                      
        end
       end
      assign shang = temp_a2[15:0];//商在低位
      assign yushu = temp_a2[31:16];//余数在高位
endmodule

3时序逻辑实现代码

`timescale 1ns / 1ps

module chu_top(
   clk,rst,a,b,enable,shang,yushu
    );
    input   clk;
    input   rst;
    input   enable;
    input [15:0]  a,b;
    output[15:0]  shang,yushu;
    
    reg [15:0] temp_a1,temp_b1;
    reg [31:0] temp_a2,temp_b2;
    reg [4:0]  counter;
    reg [31:0] shang_yu_temp;
    reg move_start;
  always@ (posedge clk or negedge rst)
    begin
    if(!rst)
      begin
      temp_a1 <= 16'b0;
      temp_b1 <= 16'b0;
      end
    else if(enable)   //赋初值
      begin
      temp_a1 <= a;
      temp_b1 <= b;
      end
     else
     begin
      temp_a1 <= temp_a1;
      temp_b1 <= temp_b1;
      end
    end
    
   always@ (posedge clk or negedge rst)  //控制移位
   begin
     if(!rst)
       move_start <= 1'b0;
     else if(enable && move_start == 0)
       move_start <= 1'b1;  
     else if(counter==5'd16) 
       move_start <= 0;   
     else
       move_start <= move_start;   
   end
   
   always@(posedge clk or negedge rst)   //计数器,用于计移位次数
   begin
     if(!rst)
       counter <= 5'd0;
     else if(move_start)
      counter <= counter+1;
     else
      counter <= 5'd0;
   end
   
   always@ (posedge clk or negedge rst)
      begin
      if(!rst)
        begin
        temp_a2 <= 32'b0;
        temp_b2 <= 32'b0;
        end
      else if(counter==5'd0 && move_start)   //赋初值
        begin
        temp_a2 <= {16'b0,temp_a1};
        temp_b2 <= {temp_b1,16'b0};
        end  
      else if(temp_a2[31:16] >= temp_b2[31:16])
              temp_a2  <=  (temp_a2-temp_b2+1'b1)<<1;       
      else  
       begin
           temp_a2 <= temp_a2<<1;
           temp_b2 <= temp_b2;
       end  
      end
   reg move_start_reg;
   wire move_end;
   reg[15:0] shang,yushu;
       
   always@(posedge clk or negedge rst)
   begin
     if (!rst)
      move_start_reg <= 1'b0;
     else
      move_start_reg <= move_start;  
   end
  assign  move_end = move_start_reg & (~move_start);  //输出控制信号
  
   always@(posedge clk or negedge rst)   //输出结果
  begin
    if (!rst)
    begin
     shang <= 16'h0;
     yushu <= 16'h0;
     end
    else if(move_end)
    begin
      shang <= temp_a2[15:0];  //低16位为商
      yushu <= temp_a2[31:16];  //高16位为余数
    end
    else
     begin
        shang <= 16'h0;
        yushu <= 16'h0;
        end
  end
   
endmodule


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值