cordic算法基本原理不用解释了,很多博客和文章已经有讲到了。
同时有很多关于cordic算法来计算sin和cos的文章,但是想自己算e指数的时候却没有太多相关的文章(不使用vivado ip核)基本的cordic算法来计算e指数的时候是有输入自变量范围的。旋转模式下为[-1.113,1.113],很多时候这个范围不能够满足需求,就需要在一定位数的需求下扩大自变量的输入范围。本文将自变量输入范围扩大到了[-3.999,3.999]。同时误差很小。
输入输出数据格式,输入数据为16位,其中最高位表示符号位,2位整数位,13位小数位。输入可表示的最大范围为[-3.999,3.999]。输出数据格式为16位,其中最高位表示符号位,9位小数位,6位整数位。模块内部X和Y的位宽为17位,最高位表示符号位,7位整数位,9位小数位。
比如说,如果M=5,那么
这里取M=2,N=13,来进行16次迭代。M对应的value为
An计算得0.09228252133203,并给定X0和Y0的初值为1/An为10.836288j进行16次迭代之后。所得到的Xn或者Yn即为要求的e指数。由于在模块内部将X和Y的数据的整数位进行扩展了一位防止数据的中间计算的溢出,在最后输出数据的时候,将X和Y数据的次高位进行舍弃,重新得到16位的数据格式。输出数据格式为[16 9]。
i<=0时的迭代计算过程如下。
always@(posedge clk or negedge rst_n)
begin
if(rst_n!=1)
begin
x[1]<=17'b0;
y[1]<=17'b0;
z[1]<=16'b0;
end
else
begin
if(z[0][15])
begin
x[1]<=$signed (x[0])-$signed (y[0])+($signed (y[0])>>>4);
y[1]<=$signed (y[0])-$signed (x[0])+($signed (x[0])>>>4);
z[1]<=z[0]+angel[0];
end
else
begin
x[1]<=$signed (x[0])+$signed (y[0])-($signed (y[0])>>>4);
y[1]<=$signed (y[0])+$signed (x[0])-($signed (x[0])>>>4);
z[1]<=z[0]-angel[0];
end
end
end
i>0时的迭代计算过程如下
always@(posedge clk or negedge rst_n)
begin
if(rst_n!=1)
begin
x[4]<=17'b0;
y[4]<=17'b0;
z[4]<=16'b0;
end
else
begin
if(z[3][15])
begin
x[4]<=$signed (x[3])-($signed (y[3])>>>1);
y[4]<=$signed (y[3])-($signed (x[3])>>>1);
z[4]<=z[3]+angel[3];
end
else
begin
x[4]<=$signed (x[3])+($signed (y[3])>>>1);
y[4]<=$signed (y[3])+($signed (x[3])>>>1);
z[4]<=z[3]-angel[3];
end
end
end
>>vs>>>
计算sinh、cosh以及tanh-1都可以用这样的方式进行计算。
参考文献:
X. Hu, R. Huber, S. Bass, “Expanding the Range of Convergence of the CORDIC Algorithm”, IEEE Transactions on Computers. Vol. 40, Nº 1, pp. 13-21, Jan. 1991.