对于non-restoring方法,主要是用rem和den移位数据比较,rem_d长度为den+nom的总长,den_d长度为den+nom的总长度,rem_d的初始值为{{d_width{1'b0}},nom};den_d的初始值为{1'b0,den,{(n_width-1){1'b0}}}。每次比较,移位同时进行。

除法运算也是数字信号处理中经常需要使用的。在FPGA设计中,通常为了简化算法,通常将除法近似为对数据进行移位操作即除数是2的整数次幂,因为在FPGA中进行移位很容易,比如右移2位相当于除4;但是在某些特殊情况下,为了满足数据处理的指标要求,不得不进行非2的整数次幂除法运算,此时就需要设计除法器。

对于被除数Nom,除数Den,除法可产生商Quo和余数Rem,计算式如下:

直接用上式在FPGA中实现,好像不是那么容易,对上式做一变换得到Rem=Nom-Den*Quo,这样就有些灵感了,被除数Nom和除数Den是给定的,可以通过比对NomDen*Quo值大小来调节商Quo的值,因为FPGA中数值都是以二进制表示的,因此按位来调节Quo的值,Den*Quo的乘法操作可用移位实现,因此可以完全使用逻辑实现整个除法器。

本文介绍两种常用除法器结构:Restoring除法器和NonRestoring除法器

NonRestoring除法器

Verilog HDL代码如下:

//nonrestoring division
module div_uu(clk,rst,clk_en,nom,den,quo,rem);
parameter integer n_width=32;
parameter integer d_width=16;
parameter integer q_width=n_width;
parameter integer r_width=d_width;
input clk;
input rst;
input clk_en;
input [n_width-1:0] nom;
input [d_width-1:0] den;
output reg [q_width-1:0] quo;
output reg [r_width-1:0] rem;
reg [n_width+d_width-1 : 0] den_d[q_width : 1];
reg [q_width-1 : 0] quo_d[q_width : 1];
reg [n_width+d_width-1 : 0] rem_d[q_width : 1];
reg clk_en_d[q_width : 1];
always@(posedge clk)
    if(rst) begin
        rem_d[1]<={(n_width+d_width){1'b0}};
        den_d[1]<={(n_width+d_width){1'b0}};
        quo_d[1]<={q_width{1'b0}};
        clk_en_d[1]<=1'b0;
    end
    else
        if(clk_en) begin
            rem_d[1]<={{d_width{1'b0}},nom};
            den_d[1]<={1'b0,den,{(n_width-1){1'b0}}};
            quo_d[1]<={q_width{1'b0}};
            clk_en_d[1]<=1'b1;
        end
        else begin
            rem_d[1]<={(n_width+d_width){1'b0}};
            den_d[1]<={(n_width+d_width){1'b0}};
            quo_d[1]<={q_width{1'b0}};
            clk_en_d[1]<=1'b0;
        end
            
generate
genvar i;
for(i=2;i<=q_width;i=i+1)
begin:U
  always@(posedge clk)
  if(rst) begin
    rem_d[i]<={(n_width+d_width){1'b0}};
    den_d[i]<={(n_width+d_width){1'b0}};
    quo_d[i]<={q_width{1'b0}};
    clk_en_d[i]<=1'b0;
  end
  else
    if(clk_en_d[i-1]) begin
      if(rem_d[i-1] >= den_d[i-1])    begin
          rem_d[i]<=rem_d[i-1] - den_d[i-1];
          den_d[i]<=den_d[i-1]>>1;
          quo_d[i]<={quo_d[i-1][q_width-2:0],1'b1};
      end
      else begin
          rem_d[i]<=rem_d[i-1];
          den_d[i]<=den_d[i-1]>>1;
          quo_d[i]<={quo_d[i-1][q_width-2:0],1'b0};
      end
      clk_en_d[i]<=1'b1;
    end
    else begin
      rem_d[i]<={(n_width+d_width){1'b0}};
      den_d[i]<={(n_width+d_width){1'b0}};
      quo_d[i]<={q_width{1'b0}};
      clk_en_d[i]<=1'b0;
        end
end
endgenerate
    
always@(posedge clk)
if(rst) begin
    rem<={d_width{1'b0}};
    quo<={q_width{1'b0}};
end
else
    if(clk_en_d[q_width]) begin
        if((rem_d[q_width] >= den_d[q_width]))    begin
            rem<=rem_d[q_width] - den_d[q_width];
            quo<={quo_d[q_width][q_width-2:0],1'b1};
        end
        else begin
            rem<=rem_d[q_width];
            quo<={quo_d[q_width][q_width-2:0],1'b0};
        end
    end
    else begin
        rem<={d_width{1'b0}};
        quo<={q_width{1'b0}};
    end
        
endmodule

上述代码实现了32位除16位无符号除法操作,综合得到结果如下:

Number of Slice Registers:   2112

Number of Slice LUTs:       1565

Minimum period: 2.070ns (Maximum Frequency: 483.139MHz)

仿真结果如图1所示

图1

Restoring除法器

Verilog HDL代码如下(贴出了核心部分代码,其它部分代码与NonRestoring相同):

//restoring division

reg [n_width+d_width-1 : 0] den_d[2*q_width-1 : 1];

reg [q_width-1 : 0] quo_d[2*q_width-1 : 1];

reg signed [n_width+d_width-1 : 0] rem_d[2*q_width-1 : 1];

reg clk_en_d[2*q_width-1:1];

always@(posedge clk)

         if(rst) begin

                   rem_d[1]<={(n_width+d_width){1'b0}};

                   den_d[1]<={(n_width+d_width){1'b0}};

                   quo_d[1]<={q_width{1'b0}};

                   clk_en_d[1]<=1'b0;

         end

         else

                   if(clk_en) begin

                            rem_d[1]<={{d_width{1'b0}},nom} - {1'b0,den,{(n_width-1){1'b0}}};

                            den_d[1]<={1'b0,den,{(n_width-1){1'b0}}};

                            quo_d[1]<={q_width{1'b0}};

                            clk_en_d[1]<=1'b1;

                   end

                   else begin

                            rem_d[1]<={(n_width+d_width){1'b0}};

                            den_d[1]<={(n_width+d_width){1'b0}};

                            quo_d[1]<={q_width{1'b0}};

                            clk_en_d[1]<=1'b0;

                   end

generate

genvar i;

for(i=1;i<q_width;i=i+1)< em="">

begin:U0

         always@(posedge clk)

  if(rst)  begin

    rem_d[2*i]<={(n_width+d_width){1'b0}};

    den_d[2*i]<={(n_width+d_width){1'b0}};

    quo_d[2*i]<={q_width{1'b0}};

    clk_en_d[2*i]<=1'b0;

  end

  else

    if(clk_en_d[2*i-1]) begin

        if(rem_d[2*i-1]<0)  begin

            rem_d[2*i]<=rem_d[2*i-1] + den_d[2*i-1];

            quo_d[2*i]<={quo_d[2*i-1][q_width-2:0],1'b0};

        end

        else begin

            rem_d[2*i]<=rem_d[2*i-1];

            quo_d[2*i]<={quo_d[2*i-1][q_width-2:0],1'b1};

        end

        den_d[2*i]<=den_d[2*i-1]>>1;

        clk_en_d[2*i]<=1'b1;

    end

    else begin

      rem_d[2*i]<={(n_width+d_width){1'b0}};

      den_d[2*i]<={(n_width+d_width){1'b0}};

      quo_d[2*i]<={q_width{1'b0}};

      clk_en_d[2*i]<=1'b0;

    end

 always@(posedge clk)

  if(rst) begin

    rem_d[2*i+1]<={(n_width+d_width){1'b0}};

    den_d[2*i+1]<={(n_width+d_width){1'b0}};

    quo_d[2*i+1]<={q_width{1'b0}};

    clk_en_d[2*i+1]<=1'b0;

  end

  else

    if(clk_en_d[2*i])  begin

        rem_d[2*i+1]<=rem_d[2*i] - den_d[2*i];

        den_d[2*i+1]<=den_d[2*i];

           quo_d[2*i+1]<=quo_d[2*i];

           clk_en_d[2*i+1]<=1'b1;

    end

    else begin

      rem_d[2*i+1]<={(n_width+d_width){1'b0}};

      den_d[2*i+1]<={(n_width+d_width){1'b0}};

      quo_d[2*i+1]<={q_width{1'b0}};

      clk_en_d[2*i+1]<=1'b0;

     end

end

endgenerate

        

always@(posedge clk)

if(rst)  begin

         rem<={n_width{1'b0}};

         quo<={q_width{1'b0}};

end

else

         if(clk_en_d[2*q_width-1]) begin

                   if(rem_d[2*q_width-1]<0 )     begin

                            rem<=rem_d[2*q_width-1] + den_d[2*q_width-1];

                            quo<={quo_d[2*q_width-1][q_width-2:0],1'b0};

                   end

                   else begin

                            rem<=rem_d[2*q_width-1][n_width-1:0];

                            quo<={quo_d[2*q_width-1][q_width-2:0],1'b1};

                   end

         end

         else begin

                   rem<={d_width{1'b0}};

                   quo<={q_width{1'b0}};

         end

上述代码实现了32位除16位无符号除法操作,综合得到结果如下:

Number of Slice Registers:   3875

Number of Slice LUTs:       2974

Minimum period: 1.794ns (Maximum Frequency: 557.414MHz)

         仿真结果如图2所示,

图2

 

         两种结构的乘法器有所区别,通过比较可发现,NonRestoring除法器没有“Rem=Nom-Den*Quo”的操作,而是直接比较Nom和Den*Quo的值,加上移位操作都在一个时钟周期内完成;而Restoring除法器将“Rem=Nom-Den*Quo”的结果寄存,并且在下一个时钟周期进行移位操作。因此,NonRestoring除法器Fmax较高, Restoring除法器相对节省资源,在应用时可根据实际需求决定采用哪一种结构的除法器。

转载 fpga中 restoring 和 non-restoring 除法实现。的更多相关文章

  1. FPGA中的除法运算及初识AXI总线

    FPGA中的硬件逻辑与软件程序的区别,相信大家在做除法运算时会有深入体会.硬件逻辑实现的除法运算会占用较多的资源,电路结构复杂,且通常无法在一个时钟周期内完成.因此FPGA实现除法运算并不是一个&qu ...

  2. 【转载】FPGA 中的latch 锁存器

    以下这篇文章讲述了锁存器的一些概念和注意事项.原文标题及链接: FPGA 中的latch 锁存器 - 快乐至永远上的博客 - 与非博客 - 与网 http://www.eefocus.com/liuy ...

  3. FPGA中浮点运算实现方法——定标

    有些FPGA中是不能直接对浮点数进行操作的,仅仅能採用定点数进行数值运算.对于FPGA而言,參与数学运算的书就是16位的整型数,但假设数学运算中出现小数怎么办呢?要知道,FPGA对小数是无能为力的,一 ...

  4. 在FPGA中使用for循环一定浪费资源吗?

    渐渐地,发现自己已经习惯于发现细节,喜欢打破常规,真的非常喜欢这种feel. 相信很多人在书上或者博文上都有提出“在FPGA中使用for语句是很占用资源的”的观点,特权同学也不例外.那么,这种观点正确 ...

  5. FPGA中RAM使用探索

    FPGA中RAM的使用探索.以4bitX4为例,数据位宽为4为,深度为4. 第一种方式,直接调用4bitX4的RAM.编写控制逻辑对齐进行读写. quartus ii 下的编译,资源消耗情况. 85C ...

  6. FPGA中计数器设计探索

    FPGA中计数器设计探索,以计数器为32位为例: 第一种方式,直接定义32位计数器. reg [31:0]count; quartus ii 下的编译,资源消耗情况. 85C模型下的时钟频率. 0C模 ...

  7. 低成本FPGA中实现动态相位调整

    在FPGA中,动态相位调整(DPA)主要是实现LVDS接口接收时对时钟和数据通道的相位补偿,以达到正确接收的目的.ALTERA的高端FPGA,如STRATIX(r) 系列中自带有DPA电路,但低端的F ...

  8. FPGA中的“门”

    逻辑门 在ASIC的世界里,衡量器件容量的常用标准是等效门.这是因为不同的厂商在单元库里提供了不同的功能模块,而每个功能模块的实现都要求不同数量的晶体管.这样在两个器件之间比较容量和复杂度就很困难. ...

  9. FPGA中的delay与latency

    delay和latency都有延迟的意义,在FPGA中二者又有具体的区别. latency出现在时序逻辑电路中,表示数据从输入到输出有效经过的时间,通常以时钟周期为单位. delay出现在组合逻辑电路 ...

随机推荐

  1. MySQL-5.7设置InnoDB表数据文件存储位置

    1.表空间 Innodb存储引擎可将所有数据存放于ibdata*的共享表空间,也可将每张表存放于独立的.ibd文件的独立表空间. 共享表空间以及独立表空间都是针对数据的存储方式而言的. 共享表空间: ...

  2. GitLab 安装与入门

    GitLab介绍: GitLab是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目. GitLab拥有与Github ...

  3. 多线程-信号量Semaphore

    计数信号量用来控制同时访问某个特定资源的操作数量.Semaphore可以用于实现资源池,例如数据库连接池.我们可以构造一个固定长度的资源池,当资源池为空的时候,请求资源将会阻塞,而不是失败.当资源池非 ...

  4. LinuxKit

    LinuxKit是Docker最新发布的一个用于为容器构建安全.便携.可移植操作系统的工具包.它根据用户编写的yaml(指定kernel和基于docker image的一些列服务)自动构建一个常见虚拟 ...

  5. LeetCode第[36]题(Java):Valid Sudoku

    题目:有效的数独表 难度:Medium 题目内容: Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be ...

  6. Object有哪些方法?

    有9个方法 1 clone 2 toString() 3 getClass 4 finalize 5 equals 6 hascode 7 notify 8 notifall 9 wait

  7. SeekBar拖动条控件

    SeekBar拖动条控件 一.简介 1. 二.SeekBar拖动条控件使用方法 1.创建SeekBar控件 <SeekBar android:id="@+id/SeekBar1&quo ...

  8. ArcGIS API For Silverlight使用在线地图的多种方法总结

    引自:http://www.cnblogs.com/meimao5211/p/3283969.html ArcGIS API For Silverlight使用在线地图的多种方法总结 本人也正在学习A ...

  9. poj3311 状压dp+floyd

    先floyd预处理一遍dis,枚举所有状态,dp[ i ] [ j ]表示 以  j  为终点的状态 i 使用最小的时间 #include<map> #include<set> ...

  10. Java基础16:Java多线程基础最全总结

    Java基础16:Java多线程基础最全总结 Java中的线程 Java之父对线程的定义是: 线程是一个独立执行的调用序列,同一个进程的线程在同一时刻共享一些系统资源(比如文件句柄等)也能访问同一个进 ...