网上有很多类似的介绍,但是本文会结合实例进行介绍,尽量以最简单的语言进行解析。 CORDIC ( Coordinate Rotation Digital Computer ) 是坐标旋转数字计算机算法的简称, 由 Vloder• 于 1959 年在设计美国航空导航控制系统的过程中首先提出[1], 主要用于解决导航系统中三角函数、 反三角函数和开方等运算的实时计算问题。 1971 年, Walther 将圆周系统、 线性系统和双曲系统统一到一个 CORDIC 迭代方程里 , 从而提出了一种统一的CORDIC 算法形式[2]。 CORDIC 算法应用广泛, 如离散傅里叶变换 、 离散余弦变换、 离散 Hartley 变换、Chirp-Z 变换、 各种滤波以及矩阵的奇异值分解中都可应用 CORDIC 算法。 从广义上讲,CORDIC 算法提供了一种数学计算的逼近方法。 由于它最终可分解为一系列的加减和移位操作, 故非常适合硬件实现。 例如, 在工程领域可采用 CORDIC 算法实现直接数字频率合成器。 本节在阐述 CORDIC 算法三种旋转模式的基础上, 介绍了利用 CORDIC 算法计算三角函数、 反三角函数和复数求模等相关理论。 以此为依据, 阐述了基于 FPGA 的 CORDIC 算法的设计与实现及其工程应用。
整个系列分别从圆周系统、 线性系统和双曲系统及硬件实现进行分析,如下:
CORDIC算法详解(一)- CORDIC 算法之圆周系统之旋转模式( Rotation Mode ) CORDIC算法详解(二)- CORDIC 算法之圆周系统之向量模式(Vectoring Mode) CORDIC算法详解(三)- CORDIC 算法之线性系统及其数学应用 CORDIC算法详解(四)- CORDIC 算法之双曲系统及其数学应用 CORDIC算法详解(五)- 统一的 CORDIC 算法形式 CORDIC算法详解(六)- CORDIC 算法的硬件实现 其中第五篇及第六篇后会放出相关参考资料及源码。
线性系统下的坐标系如下所示,基本推导过程和旋转坐标系类似,就不在多述。
线性系统下的 CORDIC 算法亦有旋转模式与向量模式, 如图 3.83 所示。 其中, 旋转模式解决了乘法计算问题, 向量模式解决了除法计算问题。
在线性系统中, 第 i次的旋转角度为
这里初始化迭代的顺序号由 1 起始而不是由 0 起始, 从而
计算 y=xz 可如式(3.114 ) 所示。
式 (3.114) 中, 将 z 分解为一系列的2-i 的组合, 即:
其中di∈{+1, -1} 结合式 (3.114 ) 和 (3.115 ) 可得出图 3.83 所示的迭代过程。 式 (3.115 )也进一步表明, 只有当|z|≤1 时, 才可以表示为一系列的2-i(i=1,2,…,) 的线性组合; 也证明了为什么迭代顺序号由 1 开始而不是由 0 开始。 由此也限定了在旋转模式下|z1|≤1 ,在向量模 式 下|y1/x1|≤1 。
旋转模式下, 可利用 CORDIC 算法实现乘法运算, 要求|z|≤1 ,如图 3.84 所示。 图中x1= 100 , z1 =-1:0.1:1 , 即 z1起始值为-1,步进为 0.1,终止值为 1。
向量模式下, 可利用 CORDIC 算法实现除法运算, 要求|y1/x1|≤1 即 |y1|≤ |x1|且x1>1 。若令y1=1,x1>1,z1=0,则可以获得x1>1的倒数1/x1>1,如图3.85所示。
获得倒数之后就可以很方便的实现除法运算了。
% /*
% * @Author: ZLK
% * @Date: 2018-10-31 10:00:17
% * @Last Modified by: ZLK
% * @Last Modified time: 2018-10-31 10:05:24
% */
function a = cordic_lr(x1,y1,z1,mode,it)
% File: cordic_lr.m
% Note: Linear Rotation of Cordic Algorithm.
% xl,yl,zl: input parameters.
% mode: 0 rotation mode; 1 vectoring mode.
% mode: 0 z0 [-1,1].
% mode: 1 abs(y)<=abs(x).
% it: iteration number.
x = zeros(it+1,1);
y = zeros(it+1,1);
z = zeros(it+1,1);
x(1)= x1;
y(1)= y1;
z(1) = z1;
di = 0;
for k=1:it
if mode==0
di = sign(z(k));
else
di = sign(-y(k));
end
x(k+1)= x(k);
y(k+1)= y(k)+x(k)*di*2^(-k);
z(k+1)= z(k)-di*2^(-k);
end
xn = x(it+1);
yn = y(it+1);
zn = z(it+1);
if mode==0
xt = x1;
yt = y1+x1*z1;
zt = 0;
else
xt = x1;
yt = 0;
zt = z1+y1/x1;
end
a =[xn,xt,yn,yt,zn,zt];
结果如下: 旋转模式下:100*(±1)
向量模式下:分别求1/2 及 1/4