FPGA基于线性迭代法的除法器设计

描述

        01前言

       FPGA实现除法的方法有几种,比如直接用/来进行除法运算,调用IP核进行除法运算,但这两种方式都有个共同的问题——都是黑盒子,在进行时序违例处理时,往往不好操作,比如想打打拍改善下时序都不知从何下手。

02原理介绍

       我们都知道商(s)=  分子(FZ)/分母(FM),该计算过程可等效于公式1

FPGA

其中FM0为FM/2**fm_shift_bit后所得的取值范围为[1,2)数,通过取一个合适的fm_shift_bit的值,使得FM0的值在[1,2]之间。

同理FZ0为FZ/2**fz_shift_bit后所得的取值范围为[1,2)数,通过取一个合适的fz_shift_bit的值,使得FZ0的值在[1,2]之间。

最后经过多次迭代后,由公式1和公式4得,

当FM0*F1*F2*......FN=1时                                        s=FZ0*F1*F2*......FN*2**(fz_shift_bit-fm_shift_bit)

例子

利用线性迭代的方式计算33/9

 

步骤如下:
第1步:将分子分母转换为[1,2)之间的数此时得
FZ0 =33/2**5 = 1.03125
FM0=9/2**3 = 1.125
以上部分在FPGA中相当于右移
由公式2、3得到
fm_shift_bit = 3
fz_shift_bit = 5
第2步:利用公式进行线性迭代,令FM0*F1*F2*......FN=FM_PRE,使FM_PRE接近于1
由第1步得FM0=1.125  
再通过公式5和公式6得
F1=2-1.125=0.875                FM1=1.125*0.875=0.984375   
F2=2-0.9875=1.0125              FM2=0.984375*1.0125=0.9966796875
F3=2-0.9966796875=1.0033203125  
迭代 3次后FM_PRE=1.125*0.875*1.0125*1.0033203125 = 0.99998897552490234375接近于1
此时由公式4得:
s=1.03125*F1*F2*F3*2**(5-3)= 3.66662624359130859375
与理论计算值误差为4.0423075358072916666666666666667e-6

 

在实际过程应用中,我们可以根据实际的误差要求确认迭代的次数。

01根据原理建立的matlab浮点数仿真模型

具体的matlab模型代码如下所示

Code

matlab迭代运算代码

 

function s = div_float(fz, fm, itr )
%----------------------判断结果的符号-----------------
if ((fz >= 0) && (fm >= 0)) || ((fz < 0) && (fm < 0))
    sign_flag = 0;
else
    sign_flag = 1;
end


%---------------限定分子范围在[1,2)---------
if fz >=0
    fz = fz;
else 
    fz = -fz;
end


fz_shift_bit = 0;
if fz ~= 0
    fz_inner = fz ;
  while(fz_inner >= 2 || fz_inner < 1)
      if fz_inner >= 2
        fz_inner = floor(fz_inner/2);
      fz_shift_bit = fz_shift_bit + 1;
      else
        fz_inner = fz_inner * 2;
      fz_shift_bit = fz_shift_bit - 1;
    end
  end
    fz = fz/2^fz_shift_bit;
end
%fprintf('a_shift_bit = ');disp(a_shift_bit);
%---------------限定分母范围在[1,2)---------
if fm >=0
    fm = fm;
else 
    fm = -fm;
end


fm_shift_bit = 0;
if fm ~= 0
    fm_inner = fm ;
  while((fm_inner >= 2) || (fm_inner < 1))
      if fm_inner >= 2
        fm_inner = floor(fm_inner/2);
      fm_shift_bit = fm_shift_bit + 1;
      else
        fm_inner = fm_inner * 2;
      fm_shift_bit = fm_shift_bit - 1;
    end
  end
    fm = fm/2^fm_shift_bit;
end
%fprintf('b_shift_bit = ');disp(b_shift_bit);
%-----------迭代过程------------------
for cnt = 0:itr-1
    f = 2 - fm;
  fz = fz * f;
  fm = fm * f;
end
%------------迭代完成后计算商-------------------
%------------当分子分母同时等于0时,令商等于0,
%------------否则,当符号标志为正数时,令其等于商的最大值
if fm ~= 0
    s = fz * 2^(fz_shift_bit - fm_shift_bit);
%    fprintf('a = ');disp(a);
%    fprintf('b = ');disp(b);
%    fprintf('c = ');disp(c);
  if sign_flag == 0
      s = s;
    else
      s = -s;
%    fprintf('~c = ');disp(c);
  end
else 
    if fz == 0
      s = 0;
  else 
      if sign_flag == 0
        s = 256 - 2^-7;
      else
        s = -256;
    end
  end
end

 

Code

matlab仿真tb

 

clear;
clc;
close all;


itr = 8;
%-----------定义分子分母和商的精度---------------
delt_fz = 2^-4;
delt_fm = 2^-2;
delt_s = 2^-7;


cntwhole = 1;
for fz = -3232 - delt_fz
    for fm = -8 : delt_fm : 8 - delt_fm
        s = div_float(fz, fm, itr);
    
    s_real = fz/fm;
    
    if s_real >= 256
        s_real = 256 - delt_s;
    elseif s_real < -256
        s_real = -256;
    else 
        s_real = s_real;
    end
    
    err = abs(s_real - s);
    
    s_reg(cntwhole) = s;
    s_real_reg(cntwhole) = s_real;
    err_reg(cntwhole) = err;
    
    cntwhole = cntwhole + 1;
  end
end
figure;plot(s_reg);title("迭代算出的结果");
figure;plot(s_real_reg);title("理论结果");
figure;plot(err_reg);title("误差图");
grid on;
    

 

下图迭代参数itr取不同值时的理论值与线性迭代值之间的误差图。

 

itr=8时

此时最大误差为2.7466*10**-7

FPGA

itr=10时

此时最大误差为7.10543*10**-15

FPGA

itr=50时

此时最大误差为7.10543*10**-15

FPGA

由itr分别取8,10,50后所得到的理论值与线性迭代算出的值做差所得到的误差图可知,并不是迭代次数越多精度越小,当迭代次数达到一个临界值后,迭代的次数其实对商的影响就不是很大了。

  审核编辑:汤梓红
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分