文档

使用CORDIC计算平方根

这个例子展示了如何在MATLAB®中使用CORDIC内核算法计算平方根。基于cordic的算法对于许多嵌入式应用都是至关重要的,包括电机控制、导航、信号处理和无线通信。

介绍

CORDIC是坐标旋转数字计算机的首字母缩写。基于Givens旋转的CORDIC算法(见[1,2])是硬件效率最高的算法之一,因为它只需要迭代的shift-add操作。CORDIC算法消除了显式乘法器的需要,适用于计算各种函数,如正弦、余弦、反正弦、反余弦、反正切、矢量幅值、除、平方根、双曲和对数函数。

定点CORDIC算法需要进行如下操作:

  • 1表查找每个迭代

  • 2班每个迭代

  • 3增加每个迭代

注意,对于基于双曲cordic的算法,例如平方根,某些迭代(i = 4,13,40,121,…, k, 3k+1,…),以实现结果收敛。

使用双曲计算模式的CORDIC内核算法

您可以使用CORDIC计算模式算法来计算双曲函数,例如双曲三角函数、平方根、log、exp等。

双曲矢量模式下的Cordic方程

计算采用双曲矢量模式平方根

对于矢量模式,CORDIC方程如下:

$$ x_{i+1} = x_{i} + y_{i}*d_{i}*2^{-i} $$

$$ y_{i+1} = y_{i} + x_{i}*d_{i}*2^{-i} $$

$ $ z_ {i + 1} = z_{我}- d_{我}* \ mbox {atanh} (2 ^ {-}) $ $

在哪里

$$ d_{i} = +1 $$如果$$ y_{i} < 0 $$,$$ -1 $$否则。

此模式提供了以下结果$ n $$方法$$ +\infty $$

  • $$ x_{N} \约A_{N}\√{x_{0}^2-y_{0}^2} $$

  • $$ y_{N} \约0 $$

  • $ $ z_ {N} \大约z_ {0} + \ mbox {atanh} ({y_{0} /间的{0}})$ $

在哪里

$$ A_{N} = \ pro_ {i=0}^{N-1}{\sqrt{1-2^{-2i}} $$

通常$ n $$选择为一个足够大的常数值。因此,$$ a_ {n} $$可能是预先计算好的。

还要注意,对于平方根我们将只使用$$ x_{N} $$结果。

CORDIC双曲矢量算法的MATLAB实现

下面是CORDIC双曲矢量核算法的MATLAB代码实现示例(对于标量的情况xy,z).这段代码既可以用于定点数据类型,也可以用于浮点数据类型。

双曲矢量核

K = 4;用于重复的(3*k + 1)迭代步骤
Idx = 1:n XTMP = bitsra(x, Idx);%乘以2^(-idx)Ytmp = bitsra(y, idx);%乘以2^(-idx)如果Y < 0 x(:) = x + ytmp;Y (:) = Y + xtmp;z(:) = z - atanhLookupTable(idx);其他的X (:) = X - ytmp;Y (:) = Y - xtmp;z(:) = z + atanhLookupTable(idx);结束
如果idx==k XTMP = bitsra(x, idx);%乘以2^(-idx) ytmp = bitsra(y, idx);%乘以2^(-idx)如果y < 0 x(:) = x + ytmp;Y (:) = Y + xtmp;z(:) = z - atanhLookupTable(idx);Else x(:) = x - ytmp;Y (:) = Y - xtmp;z(:) = z + atanhLookupTable(idx);端k = 3*k + 1;结束结束% idx循环

基于cordic的平方根计算

使用CORDIC双曲矢量核的平方根计算

初值的明智选择允许CORDIC核双曲矢量模式算法计算平方根。

首先,执行以下初始化步骤:

  • $$ x_{0} $$设置为$$ v + 0.25 $$

  • $$ y_{0} $$设置为$$ v - 0.25 $$

$ n $$迭代时,这些初始值会导致以下输出$ n $$方法$$ +\infty $$

$ $间{N} \大约现代{N} \√6 {(v + 0.25) ^ 2 - (v - 0.25) ^ 2} $ $

这可以进一步简化如下:

$$ x_{N} \约A_{N}\√{v} $$

在哪里$$ a_ {n} $$是上面定义的CORDIC增益。

注意:对于平方根,$ z $$atanhLookupTable对结果没有影响。因此,$ z $$atanhLookupTable不使用。

一个CORDIC平方根核的MATLAB实现

下面是CORDIC平方根核算法的MATLAB代码实现示例(对于标量的情况xy).这段代码既可以用于定点数据类型,也可以用于浮点数据类型。

CORDIC平方根内核

K = 4;用于重复的(3*k + 1)迭代步骤
Idx = 1:n XTMP = bitsra(x, Idx);%乘以2^(-idx)Ytmp = bitsra(y, idx);%乘以2^(-idx)如果Y < 0 x(:) = x + ytmp;Y (:) = Y + xtmp;其他的X (:) = X - ytmp;Y (:) = Y - xtmp;结束
如果idx==k XTMP = bitsra(x, idx);%乘以2^(-idx) ytmp = bitsra(y, idx);%乘以2^(-idx)如果y < 0 x(:) = x + ytmp;Y (:) = Y + xtmp;Else x(:) = x - ytmp;Y (:) = Y - xtmp;端k = 3*k + 1;结束结束% idx循环

此代码与双曲矢量核除了上面的实现zatanhLookupTable不使用。这节省了每次迭代查找1个表和添加1个表的成本。

例子

使用CORDICSQRT函数来计算的近似平方根v_fix使用10次CORDIC内核迭代:

Step = 2^-7;V_fix = fi(0.5:step:(2-step), 1,20);%范围[.]的定点输入。5、2)镍= 10;CORDIC迭代次数的%X_sqr = cordicsqrt(v_fix, niter);获取CORDIC输出的真实世界值(RWV)进行比较%,并绘制MATLAB参考值与CORDIC平方根值之间的误差X_cdc = double(x_sqr);% CORDIC结果(按An_hp缩放)V_ref = double(v_fix);引用浮点输入值X_ref =√(v_ref);MATLAB参考浮点结果图;次要情节(211);情节(v_ref x_cdc,“r”。, v_ref, x_ref,“b -”);传奇(“CORDIC”“参考”“位置”“东南”);标题(CORDIC平方根(范围内)和MATLAB参考结果);次要情节(212);absErr = abs(x_ref - x_cdc);情节(v_ref absErr);标题(绝对误差(相对于MATLAB SQRT参考结果));

克服算法输入范围限制

许多平方根算法将输入值归一化,$$ v $$,到[0.5,2)范围内。这种预处理通常使用固定的字长归一化来完成,并且可以用于支持小的和大的输入值范围。金宝app

基于cordic的平方根算法实现对超出这个范围的输入特别敏感。函数CORDICSQRT通过基于以下数学关系的归一化方法克服了这种算法范围限制:

$$ v = u * 2^{n} $$,对一些人来说$ 0.5 <= u < 2 $$还有一个偶数$ n $$

因此:

$$ \√{v} = \√{u} * 2^{n/2} $$

的值在CORDICSQRT函数中$$ u $$$ n $$,上面所描述的,都是在输入的规范化过程中发现的$$ v $$$ n $$输入的二进制表示中前导零最高有效位(msb)的数量是多少$$ v $$。这些值是通过一系列按位逻辑和移位找到的。注意:因为$ n $$必须是偶数,如果前导零msb的数量是奇数,额外的位移位要做$ n $$偶数。这些移位后的结果值就是该值$ 0.5 <= u < 2 $$

$$ u $$成为基于cordic的平方根内核的输入,其中的近似值为$$ \ root {u} $$计算。然后将结果按比例缩放$$ 2^{n/2} $$这样它就回到了正确的输出范围。这是通过一个简单的位移位实现的$$ n/2 $$位。(向左或向右)移位方向取决于的符号$ n $$

例子

使用CORDIC计算具有较小非负范围的10位定点输入数据的平方根。将基于cordic的算法结果与相同输入范围内的浮点MATLAB参考结果进行比较。

Step = 2^-8;U_ref = 0:step:(0.5-step);输入数组(值范围小)U_in_arb = fi(u_ref,0,10);% 10位无符号定点输入数据值U_len = number (u_ref);Sqrt_ref = sqrt(double(u_in_arb));% MATLAB根号参考结果镍= 10;结果= 0 (u_len, 2);Results (:,2) = sqrt_ref(:);计算用于绘图的等效真实世界值结果。。绘制CORDIC和MATLAB参考结果的真实世界值(RWV)。X_out = cordicsqrt(u_in_arb, niter);Results (:,1) = double(x_out);图;次要情节(211);情节(u_ref结果(:1),“r”。, u_ref, results(:,2),“b -”);传奇(“CORDIC”“参考”“位置”“东南”);标题(CORDIC平方根(小输入范围)和MATLAB参考结果);轴([0 0.5 0 0.75]);次要情节(212);absErr = abs(results(:,2) - results(:,1));情节(u_ref absErr);标题(绝对误差(相对于MATLAB SQRT参考结果));

例子

使用CORDIC计算具有较大正范围的16位定点输入数据的平方根。将基于cordic的算法结果与相同输入范围内的浮点MATLAB参考结果进行比较。

U_ref = 0:5:2500;输入数组(更大范围的值)U_in_arb = fi(u_ref,0,16);% 16位无符号定点输入数据值U_len = number (u_ref);Sqrt_ref = sqrt(double(u_in_arb));% MATLAB根号参考结果镍= 16;结果= 0 (u_len, 2);Results (:,2) = sqrt_ref(:);计算用于绘图的等效真实世界值结果。。绘制CORDIC和MATLAB参考结果的真实世界值(RWV)。X_out = cordicsqrt(u_in_arb, niter);Results (:,1) = double(x_out);图;次要情节(211);情节(u_ref结果(:1),“r”。, u_ref, results(:,2),“b -”);传奇(“CORDIC”“参考”“位置”“东南”);标题(CORDIC平方根(大输入范围)和MATLAB参考结果);轴([0 2500 0 55]);次要情节(212);absErr = abs(results(:,2) - results(:,1));情节(u_ref absErr);标题(绝对误差(相对于MATLAB SQRT参考结果));

参考文献

  1. Jack E. Volder, CORDIC三角计算技术,电子计算机学报,卷EC-8, 1959年9月,第330-334页。

  2. Ray Andraka,基于FPGA的计算机CORDIC算法的研究,1998年ACM/SIGDA第六届现场可编程门阵列国际研讨会论文集,1998年2月22-24日,pp191-200

这个话题有用吗?