转载 fpga中 restoring 和 non-restoring 除法实现。

对于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];
[email protected](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
  [email protected](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
    
[email protected](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];

[email protected](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

         [email protected](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

 [email protected](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

        

[email protected](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除法器相对节省资源,在应用时可根据实际需求决定采用哪一种结构的除法器。

时间: 2024-10-28 21:49:05

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

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

有些FPGA中是不能直接对浮点数进行操作的,仅仅能採用定点数进行数值运算.对于FPGA而言,參与数学运算的书就是16位的整型数,但假设数学运算中出现小数怎么办呢?要知道,FPGA对小数是无能为力的,一种解决的方法就是採用定标.数的定标就是将要运算的浮点数扩大非常多倍,然后取整,再用这个数进行运算,运算得到的结果再缩小对应的倍数就能够了.在设计中,一定不要忘记小数点.在FPGA 中是体现不出来小数点的,小数点的位置仅仅有程序猿知道.Q表示小数点的位置,Q15就表示小数点在第15位. 浮点数(x)转

转载FPGA学习之内嵌乘法器调用

补充一点,除法的时候如果直接a/b那么就会调用lpm模块,不管输入是否是常数,乘法的时候输入都是reg型变量会调用硬件乘法器,有一个是常数就会调用lpm模块. 上课的时候一直听老师说真正实践的时候你别想着要自己写一个乘法器,那样子做的孩子是笨蛋. 不管老师说得对不对,总之,既然FPGA内部有硬件乘法器那么为啥不直接使用呢,而且在写verilog使用是非常简单的,只是用个*号就轻易搞定. 只要所使用的FPGA内嵌有乘法器,则综合软件在综合的时候就会自动帮你调用乘法器实现. 下面是一段简单代码: m

FPGA中的INOUT接口和高阻态

除了输入输出端口,FPGA中还有另一种端口叫做inout端口.如果需要进行全双工通信,是需要两条信道的,也就是说需要使用两个FPGA管脚和外部器件连接.但是,有时候半双工通信就能满足我们的要求,理论上来说只需要一条信道就足够了,而FPGA上实现这一功能的管脚就是inout端口.管脚相连时,input对应output,因此inout只能和inout连接(否则就不是inout了).本文将概述FPGA的inout端口. 1. 三态门 三态门,故名思议就是这个期间具有三种状态.对于数字电路来说,三种状态

【转】FPGA中的建立时间和保持时间的关系以及影响时钟的因素

时钟是整个电路最重要.最特殊的信号,系统内大部分器件的动作都是在时钟的跳变沿上进行, 这就要求时钟信号时延差要非常小, 否则就可能造成时序逻辑状态出错:因而明确FPGA设计中决定系统时钟的因素,尽量较小时钟的延时对保证设计的稳定性有非常重要的意义. 1.1 建立时间与保持时间 建立时间(Tsu:set up time)是指在时钟沿到来之前数据从不稳定到稳定所需的时间,如果建立的时间不满足要求那么数据将不能在这个时钟上升沿被稳定的打入触发器:保持时间(Th:hold time)是指数据稳定后保持的

Altera FPGA中的pin进一步说明

最近END china上的大神阿昏豆发表了博文 <FPGA研发之道(25)-管脚>,刚好今天拿到了新书<深入理解Altera FPGA应用设计>第一章开篇就讲pin.这里就两者的知识做一个整理.至于cyclone IV器件的I/O特性笔记博文后续会补上. 上一篇Altera FPGA中的pin简介已经对altera FPGA中的pin做了一个简要的全面说明,下面就做一些深入的了解 1,一般来说,DDR的接口信号最好能在一个BANK上约束,如果不能则其控制信号要约束到同一BANK上,

[转载]Java中异常的捕获顺序(多个catch)

http://blog.sina.com.cn/s/blog_6b022bc60101cdbv.html [转载]Java中异常的捕获顺序(多个catch) (2012-11-05 09:47:28) 转载▼ 标签: 转载 分类: 转载 原文地址:Java中异常的捕获顺序(多个catch)作者:leesa Java代码 import java.io.IOException; public class ExceptionTryCatchTest { public void doSomething(

转载http中302与301的区别

http://blog.csdn.net/qmhball/article/details/7838989 一.官方说法301,302 都是HTTP状态的编码,都代表着某个URL发生了转移,不同之处在于: 301 redirect: 301 代表永久性转移(Permanently Moved).302 redirect: 302 代表暂时性转移(Temporarily Moved ). 这是很官方的说法,那么它们的区别到底是什么呢? 二.现实中的差异2.1.对于用户301,302对用户来说没有区别

FPGA中的delay与latency

delay和latency都有延迟的意义,在FPGA中二者又有具体的区别. latency出现在时序逻辑电路中,表示数据从输入到输出有效经过的时间,通常以时钟周期为单位. delay出现在组合逻辑电路.布线中,表示数据从一端到另一端经过的时间,通常以绝对时间衡量. 引起delay的有线延迟.门延迟等,通常是不希望出现的. latency和电路的逻辑设计有关,如果latency很大,通过提升工作的时钟频率,那么绝对的响应时间不会太长. 而delay很大,那么电路的工作频率会受限,从而影响电路的整体

FPGA中改善时序性能的方法

本文内容摘自<advanced FPGA design>对应中文版是 <高级FPGA设计,结构,实现,和优化>第一章中的内容 FPGA中改善时序,我相信也是大家最关心的话题之一,在这本书中列举了一些方法供给大家参考. 1,插入寄存器(Add Register Layers),在中文版中被翻译成:添加寄存器层次.即,在关键路径中插入寄存器. 这种方式会增加设计的时滞(clock latency).插入了几个寄存器,结果输出就会延长几个周期,在不违反设计规格(对clock latenc