首页 > 其他分享 >除法的实现2

除法的实现2

时间:2023-03-04 17:35:03浏览次数:34  
标签:begin end 实现 sys WIDTH b1 div 除法

除法的实现,相对于加减乘要麻烦一些。当然目前除法主要支持无符号数除法,我们分为两类进行介绍,一类是被除数是变量,即a/b这种,一类是被除数是常量,即a/B这种。
1. 被除数常量,方法一:长除法,即根据二进制手算除法,每次将被除数左移一位,每个周期得到一位商
    比如 11/4 = 2 于 3

           1011               --->11            
     -     100                ---->4
------------------------------------
           0011              101 > 100 商最高位1, 余数 0011,将0011左移一位
           011
     -     100                011 < 100 商次高位为0, 余数为011
  最终结果上为2'b10, 余数为011
  需要注意一点,如果除数的高位为0,则需要对被除数高位补0,比如1111/001 (15/1)
  由于001的bit2和bit1为0,因此1111需要补位为001111当作被除数,进行运算
   001111
- 001                                              商的bit3为1
------------------------------------
   0001
-    001                                            商的bit2为1
-------------------------------------
     0001
-      001                                          商的bit1为1
-------------------------------------
       0001
-        001                                        商的bit0为1
---------------------------------------
         000                                         余数为0

为了实现简便,我们对被除数的扩位进行归一化,统一扩位到被除数位宽+除数位宽,得到商取低位的被除数位宽即可。


根据这个思路,Verilog代码示意如下:

module SHIFT_DIV #(
                              parameter DIVIDEND_WIDTH = 16,
                              parameter DIVISOR_WIDTH  = 8,
                              parameter QUOTIENT_WIDTH = DIVIDEND_WIDTH,
                              parameter REMAINDER_WIDTH = DIVISOR_WIDTH - 1  
                             )
                            (
                              input                                                         clk_sys,
                              input                                                         rst_sys_n,
                              input                                                         div_strt,
                              input                                                         div_clr,
                              input  [DIVIDEND_WIDTH-1 : 0]                  dividend,
                              input  [DIVISOR_WIDTH-1 : 0]                    divisor,
                              output reg                                                 div_end,
                              output reg [QUOTIENT_WIDTH -1:0]           quotient,
                              output reg [REMAINDER_WIDTH-1:0]          remainder
                             );

    localparam  DIV_CNT_WIDTH = log2(QUOTIENT_WIDTH) + 1'b1;
    localparam  LSF_REG_WIDTH = DIVIDEND_WIDTH+DIVISOR_WIDTH;
/////////////////////////////////////////////////////////////////////////////////
    reg                                         div_cnt_en;
    reg [DIV_CNT_WIDTH-1 : 0]     div_cnt;

    reg [LSF_REG_WIDTH-1 : 0]   lsf_dividend;
   
    reg [DIVISOR_WIDTH-1 + 1 : 0]     sub_dividend_divsor;
     

/////////////////////////////////////////////////////////////////////////////////
    wire [DIVISOR_WIDTH-1 : 0]   divivend_cut;


////////////////////////////////////////////////////////////////////////////////////
//Generate counter to control calculation cycle
   always @(posedge clk_sys or negedge rst_sys_n) begin
        if (rst_sys_n == 1'b0) begin
              div_cnt_en <= 1'b0;
        end
        else begin
              if ((div_clr == 1'b1) ||
                  (div_cnt >= (QUOTIENT_WIDTH))) begin
                   div_cnt_en <= 1'b0;
              end
              else if (div_strt == 1'b1)begin
                    div_cnt_en <= 1'b1;
              end
        end
  end
  always @(posedge clk_sys or negedge rst_sys_n) begin
        if (rst_sys_n == 1'b0) begin
              div_cnt <= {DIV_CNT_WIDTH{1'b0}};
        end
        else begin
              if ((div_clr == 1'b1) || (div_strt == 1'b1) ||
                  (div_cnt >= (QUOTIENT_WIDTH))) begin
                  div_cnt <= {DIV_CNT_WIDTH{1'b0}};
              end
              else if (div_cnt_en == 1'b1)begin
                    div_cnt <= div_cnt + 1'b1;
              end
        end
  end


    assign  divivend_cut = lsf_divivend[DIVIDEND_WIDTH-1 -: DIVISOR_WIDTH];

    always @(*) begin
          sub_dividend_divsor = {1'b0,divivend_cut } - {1'b0, divisor};
    end

    always @(posedge clk_sys or negedge rst_sys_n) begin
          if (rst_sys_n == 1'b0) begin
                lsf_dividend <= {LSF_REG_WIDTH{1'b0}};
          end
          else if ((div_strt == 1'b1) || (div_clr == 1'b1))begin
                lsf_dividend <= {{DIVISOR_WIDTH{1‘b0}},dividend};
          end
          else if (div_cnt_en == 1'b1) begin
                if (sub_dividend_divsor[DIVISOR_WIDTH+1] == 1'b1 ) begin
                      lsf_dividend <= {lsf_dividend[LSF_REG_WIDTH-2:0],1'b0};
                end
                else begin
                     lsf_dividend <= {sub_dividend_divsor[DIVISOR_WIDTH-2:0],
                                              lsf_dividend[LSF_REG_WIDTH-DIVIDEND_WIDTH-1:0],1'b0};
                end
          end
    end


  always @(posedge clk_sys or negedge rst_sys_n) begin
          if (rst_sys_n == 1'b0) begin
                quotient <= {QUOTIENT_WIDTH{1'b0}};
          end
          else if ((div_strt == 1'b1) || (div_clr == 1'b1))begin
                quotient <= {QUOTIENT_WIDTH{1‘b0}};
          end
          else if (div_cnt_en == 1'b1) begin
                if (sub_dividend_divsor[DIVISOR_WIDTH+1] == 1'b1 ) begin
                      quotient <= {quotient[QUOTIENT_WIDTH-2:0],1'b0};
                end
                else begin
                      quotient <= {quotient[QUOTIENT_WIDTH-2:0],1'b1};
                end
          end
    end

    always @(posedge clk_sys or negedge rst_sys_n) begin
          if (rst_sys_n == 1'b0) begin
                remainder <= {REMAINDER_WIDTH{1'b0}};
          end
          else if ((div_strt == 1'b1) || (div_clr == 1'b1))begin
                remainder <= {REMAINDER_WIDTH{1'b0}};
          end
          else if (div_cnt_en == 1'b1 && (div_cnt >= (QUOTIENT_WIDTH)) begin
                remainder <= sub_dividend_divsor[REMAINDER_WIDTH-1:0] ;
          end
    end

always @(posedge clk_sys or negedge rst_sys_n) begin
          if (rst_sys_n == 1'b0) begin
                 div_end <= 1'b0;
          end
          else if ((div_strt == 1'b1) || (div_clr == 1'b1))begin
                 div_end <= 1'b0;
          end
          else if (div_cnt_en == 1'b1 && (div_cnt >= (QUOTIENT_WIDTH)) begin
                 div_end <= 1'b1 ;
          end
          else begin
                div_end <= 1'b0;
          end
    end

endmodule

标签:begin,end,实现,sys,WIDTH,b1,div,除法
From: https://www.cnblogs.com/chunk998/p/17178665.html

相关文章

  • Android-每日打卡APP-实现登录功能
    每日打卡APP新的进展-实现登录功能-昨天已经把注册功能实现了,今天也很快把登录功能做了出来,然后接着着手做其他功能,打卡功能写在下一篇博客能够实现登录和注册,注册相关的......
  • 有符号加法的Verilog实现
    有符号加法的Verilog实现形式,推荐两种方式:方式一:传统方式,手动扩位,实现左右位宽匹配,扩位为符号位,另外信号输入有符号数,一定要显示定义,Verilog默认不定义就是无符号类型1 ......
  • 除法的实现
    对于除法的实现,相对于加减乘要麻烦一些。当然目前除法主要支持无符号数除法,我们分为两类进行介绍,一类是被除数是变量,即a/b这种,一类是被除数是常量,即a/B这种。1.被除数常量......
  • 5. 决策树算法原理以及ID3算法代码实现
    完整的实验代码在我的github上......
  • 3. 朴素贝叶斯原理以及代码实现
    相关的实验代码在我的github上......
  • 算法基础1.3.4高精度除法
    前言先看高精度加法的文章,如果没有看,我把高精度加法文章中的总结前言放到这里该文章探讨的高精度代指C++中极大整数的计算,不是浮点数(y总说那个少见,不讲)。这个问题只在C......
  • KDTree实现KNN算法
    KDTree实现KNN算法完整的实验代码在我的github上......
  • pymysql实现web多条件组合查询
       代码:importpymysqlfromrest_framework.viewsimportAPIViewfromrest_framework.responseimportResponse#Createyourviewshere.'''利用pymysql实现多......
  • 设计模式篇之一文搞懂如何实现单例模式
    设计模式篇之一文搞懂如何实现单例模式大家好,我是小简,这一篇文章,6种单例方法一网打尽,虽然单例模式很简单,但是也是设计模式入门基础,我也来详细讲讲。DEMO仓库:https://gi......
  • 5.闭包的实现原理和作用,可以列举几个开发中闭包的实际应用
    1.闭包的实现原理和作用闭包:指有权访问另一个函数作用域中的变量的函数,一般都是一个函数包含另一个函数。2.闭包的作用:访问函数内部变量、保持函数在环境中一直存在,不会......