0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Verilog除法器设计

冬至子 来源:数字IC与好好生活的两居室 作者:除夕之夜啊 2023-05-30 17:31 次阅读

除法器原理(定点)

和十进制除法类似,计算 27 除以 5 的过程如下所示:

图片

除法运算过程如下:

(1) 取被除数的高几位数据,位宽和除数相同(实例中是 3bit 数据)。

(2) 将被除数高位数据与除数作比较,如果前者不小于后者,则可得到对应位的商为 1,两者做差得到第一步的余数;否则得到对应为的商为 0,将前者直接作为余数。

(3) 将上一步中的余数与被除数剩余最高位 1bit 数据拼接成新的数据,然后再和除数做比较。可以得到新的商和余数。

(4) 重复过程 (3),直到被除数最低位数据也参与计算。

需要说明的是,商的位宽应该与被除数保持一致,因为除数有可能为1。所以上述手动计算除法的实例中,第一步做比较时,应该取数字 27 最高位 1 (3'b001) 与 3'b101 做比较。

根据此计算过程,设计位宽可配置的流水线式除法器,流水延迟周期个数与被除数位宽一致。


除法器设计

◆ 单步运算设计

单步除法计算时,单步被除数位宽(信号 dividend)需比原始除数(信号 divisor)位宽多 1bit 才不至于溢出。

为了便于流水,输出端需要有寄存器来存储原始的除数(信号 divisor 和 divisor_kp)和被除数信息(信号 dividend_ci 和 dividend_kp)。

单步的运算结果就是得到新的 1bit 商数据(信号 merchant)和余数(信号 remainder)。

为了得到最后的除法结果,新的 1bit 商数据(信号 merchant)还需要与上一周期的商结果(merchant_ci)进行移位累加。

单步运算单元设计如下(文件名 divider_cell.v):

// parameter M means the actual width of divisor
module    divider_cell
    #(parameter N=5,
      parameter M=3)
    (
      input                     clk,
      input                     rstn,
      input                     en,


      input [M:0]               dividend,
      input [M-1:0]             divisor,
      input [N-M:0]             merchant_ci , //上一级输出的商
      input [N-M-1:0]           dividend_ci , //原始除数


      output reg [N-M-1:0]      dividend_kp,  //原始被除数信息
      output reg [M-1:0]        divisor_kp,   //原始除数信息
      output reg                rdy ,
      output reg [N-M:0]        merchant ,  //运算单元输出商
      output reg [M-1:0]        remainder   //运算单元输出余数
    );


    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            rdy            <= 'b0 ;
            merchant       <= 'b0 ;
            remainder      <= 'b0 ;
            divisor_kp     <= 'b0 ;
            dividend_kp    <= 'b0 ;
        end
        else if (en) begin
            rdy            <= 1'b1 ;
            divisor_kp     <= divisor ;  //原始除数保持不变
            dividend_kp    <= dividend_ci ;  //原始被除数传递
            if (dividend >= {1'b0, divisor}) begin
                merchant    <= (merchant_ci<<1) + 1'b1 ; //商为1
                remainder   <= dividend - {1'b0, divisor} ; //求余
            end
            else begin
                merchant    <= merchant_ci<<1 ;  //商为0
                remainder   <= dividend ;        //余数不变
            end
        end // if (en)
        else begin
            rdy            <= 'b0 ;
            merchant       <= 'b0 ;
            remainder      <= 'b0 ;
            divisor_kp     <= 'b0 ;
            dividend_kp    <= 'b0 ;
        end
    end 


endmodule

◆ 流水级例化

将单步计算的余数(信号 remainder)和原始被除数(信号 dividend)对应位的 1bit 数据重新拼接,作为新的单步被除数输入到下一级单步除法计算单元。

其中,被除数、除数、及商的数据信息也要在下一级运算单元中传递。

流水级模块例化完成除法的设计如下(文件名 divider_man.v):

//parameter N means the actual width of dividend
//using 29/5=5...4
module    divider_man
    #(parameter N=5,
      parameter M=3,
      parameter N_ACT = M+N-1)
    (
      input                     clk,
      input                     rstn,
      input                     data_rdy ,  //数据使能
      input [N-1:0]             dividend,   //被除数
      input [M-1:0]             divisor,    //除数


      output                    res_rdy ,
      output [N_ACT-M:0]        merchant ,  //商位宽:N
      output [M-1:0]            remainder ); //最终余数


    wire [N_ACT-M-1:0]   dividend_t [N_ACT-M:0] ;
    wire [M-1:0]         divisor_t [N_ACT-M:0] ;
    wire [M-1:0]         remainder_t [N_ACT-M:0];
    wire [N_ACT-M:0]     rdy_t ;
    wire [N_ACT-M:0]     merchant_t [N_ACT-M:0] ;


    //初始化首个运算单元
    divider_cell      #(.N(N_ACT), .M(M))
       u_divider_step0
    ( .clk              (clk),
      .rstn             (rstn),
      .en               (data_rdy),
      //用被除数最高位 1bit 数据做第一次单步运算的被除数,高位补0
      .dividend         ({{(M){1'b0}}, dividend[N-1]}),
      .divisor          (divisor),                 
      .merchant_ci      ({(N_ACT-M+1){1'b0}}),   //商初始为0
      .dividend_ci      (dividend[N_ACT-M-1:0]), //原始被除数
      //output
      .dividend_kp      (dividend_t[N_ACT-M]),   //原始被除数信息传递
      .divisor_kp       (divisor_t[N_ACT-M]),    //原始除数信息传递
      .rdy              (rdy_t[N_ACT-M]),
      .merchant         (merchant_t[N_ACT-M]),   //第一次商结果
      .remainder        (remainder_t[N_ACT-M])   //第一次余数
      );


    genvar               i ;
    generate
        for(i=1; i<=N_ACT-M; i=i+1) begin: sqrt_stepx
            divider_cell      #(.N(N_ACT), .M(M))
              u_divider_step
              (.clk              (clk),
               .rstn             (rstn),
               .en               (rdy_t[N_ACT-M-i+1]),
               .dividend         ({remainder_t[N_ACT-M-i+1], dividend_t[N_ACT-M-i+1][N_ACT-M-i]}),   //余数与原始被除数单bit数据拼接
               .divisor          (divisor_t[N_ACT-M-i+1]),
               .merchant_ci      (merchant_t[N_ACT-M-i+1]),
               .dividend_ci      (dividend_t[N_ACT-M-i+1]),
               //output
               .divisor_kp       (divisor_t[N_ACT-M-i]),
               .dividend_kp      (dividend_t[N_ACT-M-i]),
               .rdy              (rdy_t[N_ACT-M-i]),
               .merchant         (merchant_t[N_ACT-M-i]),
               .remainder        (remainder_t[N_ACT-M-i])
              );
        end // block: sqrt_stepx
    endgenerate


    assign res_rdy       = rdy_t[0];
    assign merchant      = merchant_t[0];  //最后一次商结果作为最终的商
    assign remainder     = remainder_t[0]; //最后一次余数作为最终的余数


endmodule

◆testbench

取被除数位宽为 5,除数位宽为 3,testbench 中加入自校验,描述如下:

`timescale 1ns/1ns
module test ;
    parameter    N = 5 ;
    parameter    M = 3 ;
    reg          clk;
    reg          rstn ;
    reg          data_rdy ;
    reg [N-1:0]  dividend ;
    reg [M-1:0]  divisor ;


    wire         res_rdy ;
    wire [N-1:0] merchant ;
    wire [M-1:0] remainder ;


    //clock
    always begin
        clk = 0 ; #5 ;
        clk = 1 ; #5 ;
    end


    //driver
    initial begin
        rstn      = 1'b0 ;
        #8 ;
        rstn      = 1'b1 ;


        #55 ;
        @(negedge clk ) ;
        data_rdy  = 1'b1 ;
                dividend  = 25;      divisor      = 5;
        #10 ;   dividend  = 16;      divisor      = 3;
        #10 ;   dividend  = 10;      divisor      = 4;
        #10 ;   dividend  = 15;      divisor      = 1;
        repeat(32)    #10   dividend   = dividend + 1 ;
        divisor      = 7;
        repeat(32)    #10   dividend   = dividend + 1 ;
        divisor      = 5;
        repeat(32)    #10   dividend   = dividend + 1 ;
        divisor      = 4;
        repeat(32)    #10   dividend   = dividend + 1 ;
        divisor      = 6;
        repeat(32)    #10   dividend   = dividend + 1 ;
    end


    //对输入延迟,便于数据结果同周期对比,完成自校验
    reg  [N-1:0]   dividend_ref [N-1:0];
    reg  [M-1:0]   divisor_ref [N-1:0];
    always @(posedge clk) begin
        dividend_ref[0] <= dividend ;
        divisor_ref[0]  <= divisor ;
    end


    genvar         i ;
    generate
        for(i=1; i<=N-1; i=i+1) begin
            always @(posedge clk) begin
                dividend_ref[i] <= dividend_ref[i-1];
                divisor_ref[i]  <= divisor_ref[i-1];
            end
        end
    endgenerate


    //自校验
    reg  error_flag ;
    always @(posedge clk) begin
    # 1 ;
        if (merchant * divisor_ref[N-1] + remainder != dividend_ref[N-1] && res_rdy) beginb      //testbench 中可直接用乘号而不考虑运算周期
            error_flag <= 1'b1 ;
        end
        else begin
            error_flag <= 1'b0 ;
        end
    end


    //module instantiation
    divider_man  #(.N(N), .M(M))
    u_divider
     (
      .clk              (clk),
      .rstn             (rstn),
      .data_rdy         (data_rdy),
      .dividend         (dividend),
      .divisor          (divisor),
      .res_rdy          (res_rdy),
      .merchant         (merchant),
      .remainder        (remainder));


   //simulation finish
   initial begin
      forever begin
         #100;
         if ($time >= 10000)  $finish ;
      end
   end


endmodule

仿真结果

由图可知,2 个输入数据在延迟了和被除数相同位宽的周期数以后,输出了正确的除法结果。而且可流水式无延迟输出,符合设计。

图片

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5282

    浏览量

    119763
  • Verilog
    +关注

    关注

    28

    文章

    1343

    浏览量

    109910
  • 除法器
    +关注

    关注

    2

    文章

    14

    浏览量

    13887
  • CLK
    CLK
    +关注

    关注

    0

    文章

    127

    浏览量

    17096
收藏 人收藏

    评论

    相关推荐

    verilog 除法问题

    一个变量除以一个常数81,怎么写啊 。想直接调用IP核,可是还没法控制什么时候进行除法运算。又不想自己写除法器求指点啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    发表于 04-16 15:08

    ise的除法器modelsim仿不了?

    `大虾们,小女子最近调程序的时候用到了ise ip core的除法器,但是调用modelsim仿真的时候发现木有进行除法啊,单独写了个除法器也还是用不了,这是什么情况呢?(vhdl写的程序哈)`
    发表于 06-15 11:52

    高速硬件除法器

    这是一个高速硬件除法器,要求画出此硬件的除法器的工作流程图。说明其工作原理特别是高速原理。要求有仿真时序波形图并说出说明在fpga上验证器硬件功能。
    发表于 12-17 09:10

    求大神分享一种基于Verilog计算精度可调的整数除法器的设计

    求大神分享一种基于Verilog计算精度可调的整数除法器的设计
    发表于 04-29 06:30

    除法器的设计资料分享

    4.3 实例九 除法器设计4.3.1. 本章导读要求掌握除法器原理,并根据原理设计除法器模块以及设计对应的测试模块,最后在 Robei可视化仿真软件经行功能实现和仿真验证。设计原理这个除法器
    发表于 11-12 07:03

    并行除法器 ,并行除法器结构原理是什么?

    并行除法器 ,并行除法器结构原理是什么?   1.可控加法/减法(CAS)单元    和阵列乘法器非常相似,阵列式除法器也是一种并行运算部件,采用大规模集成
    发表于 04-13 10:46 1.6w次阅读

    除法器对数运算电路的应用

    除法器对数运算电路的应用 由对数电路实现除法运算的数学原理是:
    发表于 04-24 16:07 2670次阅读
    <b class='flag-5'>除法器</b>对数运算电路的应用

    基于Verilog计算精度可调的整数除法器的设计

    除法器是电子技术领域的基础模块,在电子电路设计中得到广泛应用。目前,实现除法器的方法有硬件实现和软件实现两种方法。硬件实现的方法主要是以硬件的消耗为代价,从而有实
    发表于 05-24 09:41 1979次阅读
    基于<b class='flag-5'>Verilog</b>计算精度可调的整数<b class='flag-5'>除法器</b>的设计

    一种模拟除法器的设计及仿真验证CMOS工艺

    模拟除法器是一种能实现两个模拟量相除的电子器件。目前不仅应用于模拟运算方面,而且已扩展到无线通讯、电视广播、人工神经网路、机器人控制技术等领域。此外,模拟除法器在模糊控制和测量仪表中也是非常重要的器件。
    发表于 09-19 15:14 3459次阅读

    AD734:10 MHz四象限乘法器/除法器数据表

    AD734:10 MHz四象限乘法器/除法器数据表
    发表于 05-15 10:18 12次下载
    AD734:10 MHz四象限乘<b class='flag-5'>法器</b>/<b class='flag-5'>除法器</b>数据表

    简化合成器的有源乘法器除法器

    简化合成器的有源乘法器除法器
    发表于 05-16 17:15 9次下载
    简化合成器的有源乘<b class='flag-5'>法器</b>和<b class='flag-5'>除法器</b>

    实例九— 除法器设计

    4.3 实例九 除法器设计4.3.1. 本章导读要求掌握除法器原理,并根据原理设计除法器模块以及设计对应的测试模块,最后在 Robei可视化仿真软件经行功能实现和仿真验证。设计原理这个除法器
    发表于 11-07 10:51 18次下载
    实例九— <b class='flag-5'>除法器</b>设计

    Verilog除法器设计

    取被除数的高几位数据,位宽和除数相同(实例中是 3bit 数据)。
    的头像 发表于 03-27 11:32 850次阅读
    <b class='flag-5'>Verilog</b><b class='flag-5'>除法器</b>设计

    FPGA常用运算模块-除法器

    本文是本系列的第四篇,本文主要介绍FPGA常用运算模块-除法器,xilinx提供了相关的IP以便于用户进行开发使用。
    的头像 发表于 05-22 16:20 3299次阅读
    FPGA常用运算模块-<b class='flag-5'>除法器</b>

    使用IAR IDE仿真RL78内置硬件乘法器除法器注意事项

    使用IAR IDE仿真RL78内置硬件乘法器除法器注意事项
    的头像 发表于 10-30 17:04 1031次阅读
    使用IAR IDE仿真RL78内置硬件乘<b class='flag-5'>法器</b>和<b class='flag-5'>除法器</b>注意事项