0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Verilog除法器設(shè)計

冬至子 ? 來源:數(shù)字IC與好好生活的兩居室 ? 作者:除夕之夜啊 ? 2023-05-30 17:31 ? 次閱讀

除法器原理(定點)

和十進制除法類似,計算 27 除以 5 的過程如下所示:

圖片

除法運算過程如下:

(1) 取被除數(shù)的高幾位數(shù)據(jù),位寬和除數(shù)相同(實例中是 3bit 數(shù)據(jù))。

(2) 將被除數(shù)高位數(shù)據(jù)與除數(shù)作比較,如果前者不小于后者,則可得到對應(yīng)位的商為 1,兩者做差得到第一步的余數(shù);否則得到對應(yīng)為的商為 0,將前者直接作為余數(shù)。

(3) 將上一步中的余數(shù)與被除數(shù)剩余最高位 1bit 數(shù)據(jù)拼接成新的數(shù)據(jù),然后再和除數(shù)做比較。可以得到新的商和余數(shù)。

(4) 重復(fù)過程 (3),直到被除數(shù)最低位數(shù)據(jù)也參與計算。

需要說明的是,商的位寬應(yīng)該與被除數(shù)保持一致,因為除數(shù)有可能為1。所以上述手動計算除法的實例中,第一步做比較時,應(yīng)該取數(shù)字 27 最高位 1 (3'b001) 與 3'b101 做比較。

根據(jù)此計算過程,設(shè)計位寬可配置的流水線式除法器,流水延遲周期個數(shù)與被除數(shù)位寬一致。


除法器設(shè)計

◆ 單步運算設(shè)計

單步除法計算時,單步被除數(shù)位寬(信號 dividend)需比原始除數(shù)(信號 divisor)位寬多 1bit 才不至于溢出。

為了便于流水,輸出端需要有寄存器來存儲原始的除數(shù)(信號 divisor 和 divisor_kp)和被除數(shù)信息(信號 dividend_ci 和 dividend_kp)。

單步的運算結(jié)果就是得到新的 1bit 商數(shù)據(jù)(信號 merchant)和余數(shù)(信號 remainder)。

為了得到最后的除法結(jié)果,新的 1bit 商數(shù)據(jù)(信號 merchant)還需要與上一周期的商結(jié)果(merchant_ci)進行移位累加。

單步運算單元設(shè)計如下(文件名 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 , //原始除數(shù)


      output reg [N-M-1:0]      dividend_kp,  //原始被除數(shù)信息
      output reg [M-1:0]        divisor_kp,   //原始除數(shù)信息
      output reg                rdy ,
      output reg [N-M:0]        merchant ,  //運算單元輸出商
      output reg [M-1:0]        remainder   //運算單元輸出余數(shù)
    );


    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 ;  //原始除數(shù)保持不變
            dividend_kp    <= dividend_ci ;  //原始被除數(shù)傳遞
            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 ;        //余數(shù)不變
            end
        end // if (en)
        else begin
            rdy            <= 'b0 ;
            merchant       <= 'b0 ;
            remainder      <= 'b0 ;
            divisor_kp     <= 'b0 ;
            dividend_kp    <= 'b0 ;
        end
    end 


endmodule

◆ 流水級例化

將單步計算的余數(shù)(信號 remainder)和原始被除數(shù)(信號 dividend)對應(yīng)位的 1bit 數(shù)據(jù)重新拼接,作為新的單步被除數(shù)輸入到下一級單步除法計算單元。

其中,被除數(shù)、除數(shù)、及商的數(shù)據(jù)信息也要在下一級運算單元中傳遞。

流水級模塊例化完成除法的設(shè)計如下(文件名 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 ,  //數(shù)據(jù)使能
      input [N-1:0]             dividend,   //被除數(shù)
      input [M-1:0]             divisor,    //除數(shù)


      output                    res_rdy ,
      output [N_ACT-M:0]        merchant ,  //商位寬:N
      output [M-1:0]            remainder ); //最終余數(shù)


    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),
      //用被除數(shù)最高位 1bit 數(shù)據(jù)做第一次單步運算的被除數(shù),高位補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]), //原始被除數(shù)
      //output
      .dividend_kp      (dividend_t[N_ACT-M]),   //原始被除數(shù)信息傳遞
      .divisor_kp       (divisor_t[N_ACT-M]),    //原始除數(shù)信息傳遞
      .rdy              (rdy_t[N_ACT-M]),
      .merchant         (merchant_t[N_ACT-M]),   //第一次商結(jié)果
      .remainder        (remainder_t[N_ACT-M])   //第一次余數(shù)
      );


    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]}),   //余數(shù)與原始被除數(shù)單bit數(shù)據(jù)拼接
               .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];  //最后一次商結(jié)果作為最終的商
    assign remainder     = remainder_t[0]; //最后一次余數(shù)作為最終的余數(shù)


endmodule

◆testbench

取被除數(shù)位寬為 5,除數(shù)位寬為 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


    //對輸入延遲,便于數(shù)據(jù)結(jié)果同周期對比,完成自校驗
    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

仿真結(jié)果

由圖可知,2 個輸入數(shù)據(jù)在延遲了和被除數(shù)相同位寬的周期數(shù)以后,輸出了正確的除法結(jié)果。而且可流水式無延遲輸出,符合設(shè)計。

圖片

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5294

    瀏覽量

    119816
  • Verilog
    +關(guān)注

    關(guān)注

    28

    文章

    1343

    瀏覽量

    109925
  • 除法器
    +關(guān)注

    關(guān)注

    2

    文章

    14

    瀏覽量

    13887
  • CLK
    CLK
    +關(guān)注

    關(guān)注

    0

    文章

    127

    瀏覽量

    17104
收藏 人收藏

    評論

    相關(guān)推薦

    verilog 除法問題

    一個變量除以一個常數(shù)81,怎么寫啊 。想直接調(diào)用IP核,可是還沒法控制什么時候進行除法運算。又不想自己寫除法器求指點啊!?。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。?/div>
    發(fā)表于 04-16 15:08

    ise的除法器modelsim仿不了?

    `大蝦們,小女子最近調(diào)程序的時候用到了ise ip core的除法器,但是調(diào)用modelsim仿真的時候發(fā)現(xiàn)木有進行除法啊,單獨寫了個除法器也還是用不了,這是什么情況呢?(vhdl寫的程序哈)`
    發(fā)表于 06-15 11:52

    高速硬件除法器

    這是一個高速硬件除法器,要求畫出此硬件的除法器的工作流程圖。說明其工作原理特別是高速原理。要求有仿真時序波形圖并說出說明在fpga上驗證器硬件功能。
    發(fā)表于 12-17 09:10

    求大神分享一種基于Verilog計算精度可調(diào)的整數(shù)除法器的設(shè)計

    求大神分享一種基于Verilog計算精度可調(diào)的整數(shù)除法器的設(shè)計
    發(fā)表于 04-29 06:30

    除法器的設(shè)計資料分享

    4.3 實例九 除法器設(shè)計4.3.1. 本章導(dǎo)讀要求掌握除法器原理,并根據(jù)原理設(shè)計除法器模塊以及設(shè)計對應(yīng)的測試模塊,最后在 Robei可視化仿真軟件經(jīng)行功能實現(xiàn)和仿真驗證。設(shè)計原理這個除法器
    發(fā)表于 11-12 07:03

    并行除法器 ,并行除法器結(jié)構(gòu)原理是什么?

    并行除法器 ,并行除法器結(jié)構(gòu)原理是什么?   1.可控加法/減法(CAS)單元    和陣列乘法器非常相似,陣列式除法器也是一種并行運算部件,采用大規(guī)模集成
    發(fā)表于 04-13 10:46 ?1.6w次閱讀

    除法器對數(shù)運算電路的應(yīng)用

    除法器對數(shù)運算電路的應(yīng)用 由對數(shù)電路實現(xiàn)除法運算的數(shù)學(xué)原理是:
    發(fā)表于 04-24 16:07 ?2672次閱讀
    <b class='flag-5'>除法器</b>對數(shù)運算電路的應(yīng)用

    基于Verilog計算精度可調(diào)的整數(shù)除法器的設(shè)計

    除法器是電子技術(shù)領(lǐng)域的基礎(chǔ)模塊,在電子電路設(shè)計中得到廣泛應(yīng)用。目前,實現(xiàn)除法器的方法有硬件實現(xiàn)和軟件實現(xiàn)兩種方法。硬件實現(xiàn)的方法主要是以硬件的消耗為代價,從而有實
    發(fā)表于 05-24 09:41 ?1982次閱讀
    基于<b class='flag-5'>Verilog</b>計算精度可調(diào)的整數(shù)<b class='flag-5'>除法器</b>的設(shè)計

    一種模擬除法器的設(shè)計及仿真驗證CMOS工藝

    模擬除法器是一種能實現(xiàn)兩個模擬量相除的電子器件。目前不僅應(yīng)用于模擬運算方面,而且已擴展到無線通訊、電視廣播、人工神經(jīng)網(wǎng)路、機器人控制技術(shù)等領(lǐng)域。此外,模擬除法器在模糊控制和測量儀表中也是非常重要的器件。
    發(fā)表于 09-19 15:14 ?3465次閱讀

    AD734:10 MHz四象限乘法器/除法器數(shù)據(jù)表

    AD734:10 MHz四象限乘法器/除法器數(shù)據(jù)表
    發(fā)表于 05-15 10:18 ?12次下載
    AD734:10 MHz四象限乘<b class='flag-5'>法器</b>/<b class='flag-5'>除法器</b>數(shù)據(jù)表

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

    簡化合成器的有源乘法器除法器
    發(fā)表于 05-16 17:15 ?9次下載
    簡化合成器的有源乘<b class='flag-5'>法器</b>和<b class='flag-5'>除法器</b>

    實例九— 除法器設(shè)計

    4.3 實例九 除法器設(shè)計4.3.1. 本章導(dǎo)讀要求掌握除法器原理,并根據(jù)原理設(shè)計除法器模塊以及設(shè)計對應(yīng)的測試模塊,最后在 Robei可視化仿真軟件經(jīng)行功能實現(xiàn)和仿真驗證。設(shè)計原理這個除法器
    發(fā)表于 11-07 10:51 ?18次下載
    實例九— <b class='flag-5'>除法器</b>設(shè)計

    Verilog除法器設(shè)計

    取被除數(shù)的高幾位數(shù)據(jù),位寬和除數(shù)相同(實例中是 3bit 數(shù)據(jù))。
    的頭像 發(fā)表于 03-27 11:32 ?857次閱讀
    <b class='flag-5'>Verilog</b><b class='flag-5'>除法器</b>設(shè)計

    FPGA常用運算模塊-除法器

    本文是本系列的第四篇,本文主要介紹FPGA常用運算模塊-除法器,xilinx提供了相關(guān)的IP以便于用戶進行開發(fā)使用。
    的頭像 發(fā)表于 05-22 16:20 ?3352次閱讀
    FPGA常用運算模塊-<b class='flag-5'>除法器</b>

    使用IAR IDE仿真RL78內(nèi)置硬件乘法器除法器注意事項

    使用IAR IDE仿真RL78內(nèi)置硬件乘法器除法器注意事項
    的頭像 發(fā)表于 10-30 17:04 ?1039次閱讀
    使用IAR IDE仿真RL78內(nèi)置硬件乘<b class='flag-5'>法器</b>和<b class='flag-5'>除法器</b>注意事項