tag 标签: 除法器,dsp

相关博文
  • 热度 19
    2012-8-22 09:20
    4849 次阅读|
    0 个评论
    专题四:除法器          除法运算也是数字信号处理中经常需要使用的。在FPGA设计中,通常为了简化算法,通常将除法近似为对数据进行移位操作即除数是2的整数次幂,因为在FPGA中进行移位很容易,比如右移2位相当于除4;但是在某些特殊情况下,为了满足数据处理的指标要求,不得不进行非2的整数次幂除法运算,此时就需要设计除法器。          对于被除数Nom,除数Den,除法可产生商Quo和余数Rem,计算式如下:                                                          直接用上式在FPGA中实现,好像不是那么容易,对上式做一变换得到 Rem=Nom-Den*Quo ,这样就有些灵感了,被除数Nom和除数Den是给定的,可以通过比对 Nom 和 Den*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 nom; input den; output reg quo; output reg rem; reg den_d ; reg quo_d ; reg rem_d ; reg clk_en_d ; always@(posedge clk)     if(rst) begin         rem_d ={(n_width+d_width){1'b0}};         den_d ={(n_width+d_width){1'b0}};         quo_d ={q_width{1'b0}};         clk_en_d =1'b0;     end     else         if(clk_en) begin             rem_d ={{d_width{1'b0}},nom};             den_d ={1'b0,den,{(n_width-1){1'b0}}};             quo_d ={q_width{1'b0}};             clk_en_d =1'b1;         end         else begin             rem_d ={(n_width+d_width){1'b0}};             den_d ={(n_width+d_width){1'b0}};             quo_d ={q_width{1'b0}};             clk_en_d =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 ={(n_width+d_width){1'b0}};     den_d ={(n_width+d_width){1'b0}};     quo_d ={q_width{1'b0}};     clk_en_d =1'b0;   end   else     if(clk_en_d ) begin       if(rem_d = den_d )    begin           rem_d =rem_d - den_d ;           den_d =den_d 1;           quo_d ={quo_d ,1'b1};       end       else begin           rem_d =rem_d ;           den_d =den_d 1;           quo_d ={quo_d ,1'b0};       end       clk_en_d =1'b1;     end     else begin       rem_d ={(n_width+d_width){1'b0}};       den_d ={(n_width+d_width){1'b0}};       quo_d ={q_width{1'b0}};       clk_en_d =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 ) begin         if((rem_d = den_d ))    begin             rem=rem_d - den_d ;             quo={quo_d ,1'b1};         end         else begin             rem=rem_d ;             quo={quo_d ,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 den_d ; reg quo_d ; reg signed rem_d ; reg clk_en_d ; always@(posedge clk)          if(rst) begin                    rem_d ={(n_width+d_width){1'b0}};                    den_d ={(n_width+d_width){1'b0}};                    quo_d ={q_width{1'b0}};                    clk_en_d =1'b0;          end          else                    if(clk_en) begin                             rem_d ={{d_width{1'b0}},nom} - {1'b0,den,{(n_width-1){1'b0}}};                             den_d ={1'b0,den,{(n_width-1){1'b0}}};                             quo_d ={q_width{1'b0}};                             clk_en_d =1'b1;                    end                    else begin                             rem_d ={(n_width+d_width){1'b0}};                             den_d ={(n_width+d_width){1'b0}};                             quo_d ={q_width{1'b0}};                             clk_en_d =1'b0;                    end          generate genvar i; for(i=1;i;i=i+1) begin:U0          always@(posedge clk)   if(rst)  begin     rem_d ={(n_width+d_width){1'b0}};     den_d ={(n_width+d_width){1'b0}};     quo_d ={q_width{1'b0}};     clk_en_d =1'b0;   end   else     if(clk_en_d ) begin         if(rem_d 0)  begin             rem_d =rem_d + den_d ;             quo_d ={quo_d ,1'b0};         end         else begin             rem_d =rem_d ;             quo_d ={quo_d ,1'b1};         end         den_d =den_d 1;         clk_en_d =1'b1;     end     else begin       rem_d ={(n_width+d_width){1'b0}};       den_d ={(n_width+d_width){1'b0}};       quo_d ={q_width{1'b0}};       clk_en_d =1'b0;     end  always@(posedge clk)   if(rst) begin     rem_d ={(n_width+d_width){1'b0}};     den_d ={(n_width+d_width){1'b0}};     quo_d ={q_width{1'b0}};     clk_en_d =1'b0;   end   else     if(clk_en_d )  begin         rem_d =rem_d - den_d ;         den_d =den_d ;            quo_d =quo_d ;            clk_en_d =1'b1;     end     else begin       rem_d ={(n_width+d_width){1'b0}};       den_d ={(n_width+d_width){1'b0}};       quo_d ={q_width{1'b0}};       clk_en_d =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 ) begin                    if(rem_d 0 )     begin                             rem=rem_d + den_d ;                             quo={quo_d ,1'b0};                    end                    else begin                             rem=rem_d ;                             quo={quo_d ,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除法器相对节省资源,在应用时可根据实际需求决定采用哪一种结构的除法器。