Cordic角度旋转算法简介:
在DDS内,Cordic算法相当于替代Rom的一种相幅映射算法,算法通过计算单位圆上点的X坐标和Y坐标,得到角度θ的正弦和余弦值,从一个正弦和余弦已知的初始角度开始,通过多次旋转一系列固定角度来获得所需点的坐标。
其公式如下所示:
硬件内架构如下所示:
通过多次流水迭代即可实现相幅映射关系。
具体迭代的算法详解这里就不再解释,详情可以看一休哥的Cordic算法详解,里面的算法解释及硬件实现代码解释的很清楚。
基于FPGA的CORDIC算法实现——Verilog版算法本身并不是太难,不过结合到具体的设计中需要具体理解,由于项目需求需要位宽较大的相位累加器,而对于基于Rom的查找表来说,相位累加器的位宽和Rom的深度是相关的,不可能在大位宽的输入情况下,完全的根据位宽实现Rom的深度,这带来的Rom大小是不可估量的,为此我查找了文献的DDS实现方案,基本上有两种方案,一是将ROM压缩,这里可以参考我其他的博文,另外一种方案是将Rom替代,也就是本文的Cordic算法详解,这里结合具体项目笔者写下根据项目出发的一些思考:
根据项目需求我对相位累加器的位宽直接采用到了48位,幅值量化位数也就是输出正余弦的位宽上我分别采用了8位和16位,带符号位。
仿真时我才用主频250M,输出波形我分别采用了10M,0.694M。
在联系到具体的设计上,K值直接联系着输出位宽,输出位宽为16位,K值就是0.607253*2^16,输出位宽为8位,K值就是0.607253*2^8.
Cordic算法的流水深度也是根据K值而来的,在K值是16位的情况下,流水迭代基本上也就在16级的流水深度下停止迭代,这点可以根据公式非常容易的推出,X值和Y值在后续的迭代过程中基本上相加的也是0值,而K值是8位的情况下,流水迭代基本上在第8级的流水深度下停止迭代。
输入位宽过大,输出位宽过小,流水迭代过早的停止导致本想由输入位宽大造成的高频率分辨率的优点大大减小,而在实际的迭代过程中由于流水过早的停止,基本上也是高位参与了迭代过程,低位由于流水迭代的深度小没有迭代到低位主要参与的流水深度相当于没起到作用。在仿真过程中我将输入位宽为12位输出数据位宽为8位的仿真模型与输入位宽为48位输出位宽为8位的仿真模型进行了对比,输出数据基本一致,在相位的位宽上基本上只有高位参与了迭代过程。
基本上一致。
从全方位考虑,采用多级流水实现迭代所带来的乘法器和移位器消耗的成本和实现的结果对比而言,完全不如采用Rom查找表实现,但是如果采用高位输出,高位宽输入的情况下,完全可以采用Cordic算法实现,但是在相幅量化位数较低的情况下不如直接采用Rom查找表实现DDS,这样所带来的成本还有实现收益而言是比较合适的。
下图为仿真过程中采用48位输入,8位输出,在内部采用41级流水线实现的资源消耗图:
作为对比下图为采用查找表方式实现的12位输入,8位输出的资源消耗对比:
可以发现相差甚多!而且功耗相差也是甚多!