cordic sinx 代码_使用CORDIC算法求解角度正余弦及Verilog实现

本文是用于记录在了解和学习CORDIC算法期间的收获,以供日后自己及他人参考;并且附上了使用Verilog实现CORDIC算法求解角度的正弦和余弦的代码、简单的testbench测试代码、以及在Modelsim下的仿真结果。

本文主要参考了:

感谢!

-------------------------------------------------------------------------------------------------------------

1、算法简介

CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法,是J.D.Volder1于1959年首次提出,主要用于三角函数、双曲线、指数、对数的计算。该算法通过基本的加和移位运算代替乘法运算,使得矢量的旋转和定向的计算不再需要三角函数、乘法、开方、反三角、指数等函数,计算向量长度并能把直角坐标系转换为极坐标系。因为Cordic 算法只用了移位和加法,很容易用纯硬件来实现,非常适合FPGA实现。

CORDIC算法是天平称重思想在数值运算领域的杰出范例。核心的思想是把非线性的问题变成了线性的迭代问题【4】。

CORDIC算法完成坐标或向量的平面旋转(下图以逆时针旋转为例)。

f67c120755aa642ba7e2124701266c4c.png

旋转后,可得如下向量:

07d65eb4247ca7d7ad41ad40ac9834a5.png

旋转的角度θ经过多次旋转得到的(步步逼近,接近二分查找法),每次旋转一小角度。单步旋转定义如下公式:

13831757cf1cbd88a545a3aa6a3ec80c.png

公式(2)提取cosθ,可修改为:

56b148689a43dafd74aed49499865395.png

修改后的公式把乘法次数从4次改为3次,剩下的乘法运算可以通过选择每次旋转的角度去除,将每一步的正切值选为2的指数(二分查找法),除以2的指数可以通过右移操作完成(verilog)。

每次旋转的角度可以表示为:

a024a552431ccb557c7a1a91ba12d6c7.png

所有迭代角度累加值等于最终需要的旋转角度θ:

005cd6058f2fb6a3b51b962fb89d6363.png

这里Sn为1或者-1,根据旋转方向确定(后面有确定方法,公式(15)),顺时针为-1,逆时针为1。

18b3bb56946cc6b3b1a9637fbc02184f.png

可以得到如下公式:

a2c530557f56752584892ec1396cec0c.png

结合公式(3)和(7),得到公式(8):

36d9c6fcecbce10a73979267e677fb4c.png

到这里,除了余弦值这个系数,算法只要通过简单的移位和加法操作完成。而这个系数可以通过预先计算最终值消掉。首先重新重写这个系数如下:

4838c8b6922efedd40daa48342f56697.png

第二步计算所有的余弦值并相乘,这个值K称为增益系数。

5f958ebc0f5ae89f08ac34d3d64cf0a3.png

由于K值是常量,我们可以先忽略它。

e2ea2c630084131a75e10bf122269dda.png

faeecfe2cf4d5a50607191ff3fa91790.png

到这里我们发现,算法只剩下移位和加减法,这就非常适合硬件实现了,为硬件快速计算三角函数提供了一种新的算法。在进行迭代运算时,需要引入一个新的变量Z,表示需要旋转的角度θ中还没有旋转的角度。

b75998f3946012fd3275bafcce2d68f3.png

这里,我们可以把前面提到确定旋转方向的方法介绍了,就是通过这个变量Z的符号确定。

eb19829968205e84e13c785f7c09f78a.png

a39422859a47392ce4b365d210bfe103.png

通过公式(5)和(15),将未旋转的角度变为0。

一个类编程风格的结构如下,反正切值是预先计算好的。

9c0b6c3b011d6a020293068f83618c3e.png

1.1 旋转模式

旋转模式下,CORDIC算法驱动Z变为0,结合公式(13)和(16),算法的核心计算如下:

7bb141ca143b211f159596122f9fb061.png

一种特殊情况是,另初始值如下:

5287676d36f06881a231127e9e6754e5.png

因此,旋转模式下CORDIC算法可以计算一个输入角度的正弦值和余弦值。

1.2 向量模式

向量模式下,有两种特例:

b18f4a32103638c4bde4cd4804c03c1a.png

因此,向量模式下CORDIC算法可以用来计算输入向量的模和反正切,也能开方计算,并可以将直角坐标转换为极坐标。

2、硬件算法实现

根据【5】,可以看到CORDIC迭代算法的一种直接实现方式是反馈结构,此结构只设计一级CORDIC运算迭代单元、然后在系统时钟的驱动下,将本级的输出作为本级的输入,通过同一级迭代完成运算。这种方法硬件开销小、但控制相对复杂。

所以根据【1】、【2】,使用流水线结构实现了CORDIC迭代算法、求取了角度的正弦和余弦值。

下面分段介绍下各部分代码:

首先是角度的表示,进行了宏定义,360读用16位二进制表示2^16,每一度为2^16/360。

//360°--2^16,phase_in = 16bits (input [15:0] phase_in)//1°--2^16/360

`define rot0 16'h2000 //45

`define rot1 16'h12e4 //26.5651

`define rot2 16'h09fb //14.0362

`define rot3 16'h0511 //7.1250

`define rot4 16'h028b //3.5763

`define rot5 16'h0145 //1.7899

`define rot6 16'h00a3 //0.8952

`define rot7 16'h0051 //0.4476

`define rot8 16'h0028 //0.2238

`define rot9 16'h0014 //0.1119

`define rot10 16'h000a //0.0560

`define rot11 16'h0005 //0.0280

`define rot12 16'h0003 //0.0140

`define rot13 16'h0002 //0.0070

`define rot14 16'h0001 //0.0035

`define rot15 16'h0000 //0.0018

然后是流水线级数定义、增益放大倍数以及中间结果位宽定义。流水线级数16,为了满足精度要求,有文献指出流水线级数必须大于等于角度位宽16(针对正弦余弦计算的CORDIC算法优化及其FPGA实现)。增益放大2^16,为了避免溢出状况中间结果(x,y,z)定义为17为,最高位作为符号位判断,1为负数,0为正数。

modulecordic

(i

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值