摘 要: 在对传统CORDIC算法" title="CORDIC算法">CORDIC算法进行改进的基础上,讨论了一种基于改进型CORDIC算法的NCO实现方法,该设计占用资源少、运算速度快、易于扩展。仿真结果证明该设计具有较高的性价比。
关键词: CORDIC算法 数控振荡器" title="数控振荡器">数控振荡器 FPGA
数控振荡器(NCO)的作用是产生正交的正弦和余弦样本,应具有频率分辨率高、频率变化速度快、相位可连续线性变化及生成的正弦和余弦信号正交特性好等特点。传统的数控振荡器中,相位到幅度的转化是通过查找表(LUT)的方式来实现的。这种方法实现简单,但是如果要提高频率分辨率,往往需要消耗大量的存储资源。而且,由于受到RAM读取速度的影响,使NCO输出速率受到制约。CORDIC算法以其算法简单、硬件实现方便等特点在很多方面得到了应用,其中之一就是用于NCO的设计。本文在传统CORDIC算法的基础上进行了改进,并将其运用到一个NCO的设计当中,具有运算速度快、资源占用少、易于扩展等优点。
1 NCO实现原理
NCO可以看成是由相位累加器(PA)和函数发生器(FG)两部分组成,如图1所示。其中相位累加器的设计较简单,设计NCO的关键是设计正弦函数发生器。传统的实现函数发生器的方法为查表法(LUT),对于一个相位位数为n,输出信号幅度位数为M的NCO,所需查找表的大小为M×2n。为了提高NCO的频率分辨率,往往需要扩大查找表的容量,这会造成存储资源的大量消耗。而且,由于受到RAM读取速度的影响,NCO的输出速率受到制约。可以看出LUT是NCO设计的瓶颈。为了避免使用大容量的存储器,可以考虑通过计算来产生正余弦函数样本。基于矢量旋转的CORDIC算法正好满足了这一需求。
2 CORDIC算法原理
CORDIC算法最初是由J.Volder于1959年提出,1971年J.Walther提出了统一的CORDIC形式。用CORDIC算法求三角函数的基本原理如下:
如果P(x,y)是直角坐标系中单位圆上一点, θ为向量OP和X轴正向之间夹角, 则有x=cosθ,y=sinθ。因此若将单位向量OM(1,0)旋转n次得到向量OP(x,y),让旋转角度的总和等于输入的角度?兹,则x,y即为所需输出值cosθ和sinθ,这就是CORDIC算法实现正交三角函数cosθ和sinθ的基本思路。如图2所示。
向量x1+jy1旋转角度θ到向量x2+jy2:
经变换为:
为了便于硬件实现,设旋转n次,令每一次旋转的角度为θi,并且θi满足tanθi=2-i,则cosθi,第i次的旋转表示为:
其中,第i次旋转后的角度变化为zi,每次旋转的方向为δi,由zi的符号位来决定;δi=sign(zi),即δi=+1时,逆时针旋转,δi=-1时,顺时针旋转。为每一级的校正因子,也就是每一级旋转时向量模长发生的变化,对于字长一定的运算,总的校正因子是一个常数。若总的旋转级数为N,则总校正因子用K表示为:
以16位为例,K=0.607252935。
可以先将输入数据校正后再进行运算,这样每一级的运算可以简化成:
由上式可以看出所有运算简化成了加减法和移位操作。当给定的初始输入数据为x0=K,y0=0时,z0=θ,经过n次迭代结果为:
3 CORDIC算法及其改进FPGA" title="FPGA">FPGA实现
考虑到迭代序列所能覆盖的角度范围:,若直接采用n(n→∞)级迭代序列:0,1,2,…,n-1,则能覆盖到的角度范围是-99.9°~+99.9°,不能达到NCO角度覆盖范围-π~π的要求。 因此,需要在初次迭代前增加一个特定的“起始”步骤来扩大角度覆盖范围,即根据输入相位的正负将向量先顺时针或逆时针旋转90°,从而达到覆盖要求。这个步骤的数学表达式如下:
其中δ=sign(z0)。
采用CORDIC算法取代查找表能够节省大量的RAM资源,但是同时却带来了更多的LE消耗,这就需要在设计中考虑如何减少LE的消耗。
对于小角度的正弦和余弦值,有:
而在CORDIC算法有限精度的迭代运算中,到一定级数的坐标旋转角度也是接近于0的小角度值。利用这个特性,可以对CORDIC算法进行改进。下面以16位输出宽度的CORDIC算法为例介绍本文对CORDIC算法的改进。
注意到迭代9次以后,余下的角度为:θ=0.003906,
其中,z8为迭代9次后所余下的角度。可以将前9次迭代采用常规的CORDIC算法,对于后面几级,直接采用初始角度旋转变化计算公式:
已知z8<2-8,对于16位输出精度来说,cosz8=1,sinz8=z8,则上式可以写成:
由此可知,对于16位输出宽度的CORDIC运算,这里只需要9级迭代加1级初始的角度旋转运算。这种结构可以有效地提高CORDIC运算的效率,大量节约实现所需的资源。
图3是用FPGA实现CORDIC算法的一个流水线结构单元,由9个这样的单元构成前面9级的迭代流水线,如图4所示。
对于(10)式中的乘法,可以通过并行加法来计算,这样就将多级级联加法运算变为了一级合成进位存储加法器。合成进位存储加法器的表达式是:
当δ8=1时,αi为z8的第i位;δ8=-1时,αi为z8二进制反码的第i位。结构如图5。
加上预迭代,采用传统CORDIC算法实现16位输出宽度CORDIC算法需要17级流水线。而采用改进后的CORDIC算法只需要9级流水线加1级进位存储加法器,改进后的CORDIC算法总体结构如图6所示。这种流水线结构正常工作时,在初始延迟之后,每次新的循环完成就会生成一个新的输出值,即只需一个时钟周期就可输出一个数据。
如需提高精度, 可以在增加输出位宽的同时相应地增加流水线级数即可。
4 仿真结果
图7是在Quartus Ⅱ" title="Quartus Ⅱ">Quartus Ⅱ4.1中进行仿真后的结果,输入输出数据用16位补码表示,首位为符号位,第2、3位为整数位,后13位为小数位。表1列出了几个典型相位的正弦仿真输出值与理论值对比。从表1中的仿真结果可以看出,采用改进型的CORDIC流水线结构实现的本地数控震荡器计算精度已趋近理论值。表2是传统CORDIC算法和改进型CORDIC算法消耗硬件资源的比较。可以看出,采用改进型CORDIC算法比传统算法节约了约33.6%的资源。
本文提出了基于改进型CORDIC算法的NCO设计及硬件实现,其简单的流水线结构使得FPGA的资源耗费大为减少,能充分利用CORDIC算法的灵活性,具有较好的实用价值。
参考文献
[1] Hu Y H.CORDIC-based VLSI architecture for digital signal processing[C].IEEE SP Mag,1992,(7):17-35.
[2] Uwe Meyer Baese著,刘凌,胡永生,译.Digital signal processing with field programmable gate arrays[M].北京:清华大学出版社,2003.