0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用Verilog HDL设计实现Cordic算法

lp7u_bia 来源:硅农 作者:硅农 2021-08-16 11:21 次阅读

任何适合产品实现的算法,都是将简易实现作为第一目标。CORDIC算法是建立在适应性滤波器、FFT、解调器等众多应用基础上计算超越函数的方法。其核心思想是二分逐次逼近。

CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法,是J.D.Volder1于1959年首次提出,主要用于三角函数、双曲线、指数、对数的计算。该算法通过基本的加和移位运算代替乘法运算,使得矢量的旋转和定向的计算不再需要三角函数、乘法、开方、反三角、指数等函数。

本文是基于使用Verilog HDL设计实现Cordic算法,实现正弦、余弦、反正切函数的实现。将复杂的运算转化成RTL擅长的加减法和乘法,而乘法运算可以用移位运算代替。Cordic算法有两种模式,旋转模式和向量模式。可以在圆坐标系、线性坐标系、双曲线坐标系使用。本文初步实现在圆坐标系下的两种模式的算法实现。

cfefd67e-fdb9-11eb-9bcf-12bb97331649.png

旋转模式,迭代位移算法。假设有一点P0(x0,y0),经过逆时针旋转角度θ,到达点Pm(xm,ym),我们根据数学运算可以得到公式如下:

xm = x0cosθ - y0sinθ

= cosθ(x0 – y0tanθ)

ym = x0sinθ +y0cosθ

=cosθ(x0tanθ+y0)

如果不考虑旋转后的向量模值,只考虑旋转角度,即去掉cosθ,得到如下方程式。这里旋转的角度的正确的,但xm和ym的值增加。cosθ值是小于等于1的,它的倒数值大于等于1,所以xm和ym模值增大了。去掉cosθ项可以方便我们后面的坐标平面旋转的计算。这里称为伪旋转。

xm = x0 – y0tanθ ym =x0tanθ+y0

Cordic的方法核心就是伪旋转,将旋转角θ细化成若干个大小固定的角度θi,规定θi满足tanθi = 2^-i,通过一系列的迭代旋转,每次旋转θi,i为迭代次数,规定∑θi的范围即旋转角度θ的范围为[-99.7, 99.7]。如果θ的大于这个范围则可通过三角运算操作转化到该范围的角度。

我们通过事先将所有每次旋转的角度计算出来,由于每次旋转的角度是固定的,所以经过i次旋转的∑θi可能会超过θ,所以就必须设置一个方向值di,如果旋转角度之和已经小于θ,则di为1,下次旋转继续为逆时针旋转,如果旋转角度之和大于θ,则di为-1,下次旋转为顺时针。设置zi+1为旋转剩余角度,zi+1 = z0 – di *zi,z0 = θ,随着i值的增大,zi+1会趋向于0时,即旋转结束。di与zi的符号位相同。

采用伪旋转的方法,每次提出一个cosθi,旋转结束后会产生一个∏cosθi的累乘,一旦我们确定了迭代次数,∏cosθi就是一个常数,迭代公式可写为。这是将cosθi提出、tanθi 替换成 2^-i后的结果。di与zi的符号位相同。

xi+1 = xi - di * yi * 2^-i yi+1 = yi + di * xi * 2^-i zi+1 = z0 - di * θi

设迭代i = n - 1,那么旋转n次后得到Pm的坐标应该为(xn * ∏cosθi, yn * ∏cosθi)。因为每次迭代都会提出一个cosθi,旋转n次后的xn和yn就会少乘一个∏cosθi,所以实际上最终的Pm坐标角度近似于(xn * ∏cosθi, yn * ∏cosθi)。

xn * ∏cosθi = x0cosθ - y0sinθ yn * ∏cosθi = y0cosθ + x0sinθ xn = 1/∏cosθi (x0cosθ – y0sinθ) yn = 1/∏cosθi (y0cosθ +x0sinθ)

伸缩因子,KN = 1 / ∏cosθi,已知迭代次数,我们可以预先计算KN的值。如下这是使用MATLAB计算出的迭代结果数值。

xn =KN (x0cosθ – y0sinθ) yn = KN (y0cosθ +x0sinθ)

从上表可以得出,我们预先计算出KN的值,然后令x0 = ∏cosθi,y0 = 0,则上述公式可化简为

xn = cosθ yn = sinθ 即可实现正弦、余弦操作了。旋转模式

Cordic算法旋转模式使用Verilog HDL的实现流程

确定迭代次数,将每次迭代的角度计算出来,预先定义为参数,为了避免浮点运算,将角度值向左移位16位,取整数部分。

根据迭代公式进行迭代计算,本设计取16次迭代,从上表可以看出,当迭代次数越大时,1/∏cosθi会趋向于一个确定值。如果对结果精度要求更高,可以设置更高的迭代次数,根据迭代次数,可以将伸缩因子KN = 1/∏cosθi计算出来。同样将其左移16位。

xi+1 = xi - di * yi * 2^-i yi+1 = yi + di * xi * 2^-i zi+1 = z0 - di * θi

设置x0 = ∏cosθi,y0 = 0,则求出x16 = cosθ,y16 = sinθ。

这里需要注意的是,我们在进行迭代运算的时候,将2^-i变成移位运算,对于正余弦来说是有正负的,所以在一开始定义的时候,就应该定义成有符号数,Verilog中也可以定义有符号数,最高位表示符号位,定义如下

d05925c0-fdb9-11eb-9bcf-12bb97331649.jpg

迭代寄存器定义为有符号数,那么我们移位运算就不能用>>逻辑右移<<逻辑左移或来移位了,而是用>>>算术右移和<<<算术左移。逻辑左移也就相当于算数左移,右边统一添0 ,逻辑右移,左边统一添0 ,算数右移,左边添加的数和符号有关。

例如1010_1010, []是添加的位 逻辑左移一位:0101_010[0] 算数左移一位:0101_010[0] 逻辑右移一位:[0]101_0101 算数右移一位:[1]101_0101

迭代运算采用16级流水线进行运算,最终需要判断输出的正余弦值在哪个象限,前面讲旋转角度θ的范围为[-99.7,99.7],不在这个范围我们要进行三角运算使其满足这个范围,当输入的角度小于90度即可进行计算,当输入角度大于90度小于180度,将输入角度减去90度并设定当前角度处于第二象限,然后进行计算,当输入角度大于180度小于270度,将输入的角度减去180度设置当前角度处于第三象限,进行计算,当输入的角度大于270度,减去270设置当前角度处于第四象限,进行计算。象限的设定通过quarant寄存器实现。

如果角度在第一象限,sin(x) = sin(a),cos(x) = sin(a)最后的结果x16 = cosθ, y16 = sinθ,这里我想起了那句口诀,一全正,二正弦,三正切,四余弦

如果角度在第二象限,

sin(x) = sin(a+90) = cos(a),

cos(x) = cos(a+90) = -sin(a)

如果角度在第三象限,

sin(x) = sin(a+180) = -sin(a),

cos(x) = cos(a+180) = -cos(a)

如果角度在第四象限,

sin(x) = sin(a+270) = cos(a),

cos(x) = cos(a+270) = -sin(a)

d0a88142-fdb9-11eb-9bcf-12bb97331649.png

对于正数,我们直接赋值输出,负数,这里使用有符号数表示,将其取反加1即可。最终使用modelsim对算法进行仿真,从波形图上看已经初步实现了sin,cos函数。

向量模式

Cordic算法在向量模式下的计算方法和旋转模式基本上是类似的,设有一点P0(x0, y0),经过旋转一定角度到与x轴重合,得到点Pm(xm, ym),即ym = 0。

xm = x0cosθ - y0sinθ

= cosθ(x0 – y0tanθ)

ym = y0cosθ + x0sinθ

= cosθ(y0 +x0tanθ) = 0

我们设置x0 = x, y0 = y, z0 = 0,迭代次数为16,经过16次迭代后得到zn = θ = arctan(y/x)和坐标所代表的向量的模值d = xm = xn * ∏cosθi,di与yi方向相反,即当时结束运算。实现方法为判断yi的符号位,符号位为1,di为1,符号位为0,di为-1。

xi+1 = xi - di * yi * 2^-i

yi+1 = yi + di * xi * 2^-i

zi+1 = z0 - di * θi

关于反正切函数,由于在[-99.7°,99.7°]范围内,所以我们输入向量P0(x0, y0)时,需要保证其在第一、四象限。

d0feb292-fdb9-11eb-9bcf-12bb97331649.png

下面是使用MATLAB计算出来的数据和FPGA计算出来的数据进行比较。

d11d1bc4-fdb9-11eb-9bcf-12bb97331649.jpg

d141af8e-fdb9-11eb-9bcf-12bb97331649.jpg

从FPGA计算出的结果与MATLAB来比较,和实际结果之间的误差还是挺小的,毕竟是硬件计算出来的数据,向量的误差就比较大了,如果对于精度比较高的计算,我们可以通过提高迭代次数来提高精度

使用ISE进行综合并下载工程到开发板上实验结果比较。

旋转模式

Sin的理论数据

Chipscope抓取到的数据

d159baca-fdb9-11eb-9bcf-12bb97331649.jpg

Cos的理论数据

d1a7c7ec-fdb9-11eb-9bcf-12bb97331649.jpg

Chipscope抓取到的数据

d1c563e2-fdb9-11eb-9bcf-12bb97331649.jpg

向量模式

Arctan(y/x)理论数值

d1eb7820-fdb9-11eb-9bcf-12bb97331649.jpg

Chipscope抓取到的数据

d20cba58-fdb9-11eb-9bcf-12bb97331649.jpg

坐标的模值的理论数据

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Verilog
    +关注

    关注

    28

    文章

    1326

    浏览量

    109302
  • HDL
    HDL
    +关注

    关注

    8

    文章

    323

    浏览量

    47101

原文标题:基于Verilog的Cordic算法实现

文章出处:【微信号:bianpinquan,微信公众号:变频圈】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    例说Verilog HDL和VHDL区别

    Verilog和VHDL之间的区别将在本文中通过示例进行详细说明。对优点和缺点的Verilog和VHDL进行了讨论。
    的头像 发表于 12-20 09:03 656次阅读
    例说<b class='flag-5'>Verilog</b> <b class='flag-5'>HDL</b>和VHDL区别

    基于流水线CORDIC算法通用数字调制器的FPGA实现方案

    电子发烧友网站提供《基于流水线CORDIC算法通用数字调制器的FPGA实现方案.pdf》资料免费下载
    发表于 10-27 09:46 0次下载
    基于流水线<b class='flag-5'>CORDIC</b><b class='flag-5'>算法</b>通用数字调制器的FPGA<b class='flag-5'>实现</b>方案

    Verilog HDL实用精解配套源代码

    轻松成为设计高手Verilog HDL 实用精解 配套源代码。
    发表于 10-09 06:28

    FPGA实现Cordic算法求解arctanθ

    由于在项目中需要使用的MPU6050,进行姿态解算,计算中设计到arctan 和 sqr(x*2 + y * 2),这两部分的计算,在了解了一番之后,发现Cordic算法可以很方便的一次性求出这两个这两部分的计算。
    的头像 发表于 09-27 09:30 803次阅读
    FPGA<b class='flag-5'>实现</b><b class='flag-5'>Cordic</b><b class='flag-5'>算法</b>求解arctanθ

    怎样使用CORDIC算法求解角度正余弦呢?

    CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法,是J.D.Volder1于1959年首次提出,主要用于三角函数、双曲线、指数、对数的计算。
    的头像 发表于 08-31 14:54 1256次阅读
    怎样使用<b class='flag-5'>CORDIC</b><b class='flag-5'>算法</b>求解角度正余弦呢?

    Verilog HDL语言的发展历史和主要能力

    Verilog HDL是一种硬件描述语言,以文本形式来描述数字系统硬件的结构和行为的语言,用它可以表示逻辑电路图、逻辑表达式,还可以表示数字逻辑系统所完成的逻辑功能。 Verilog HDL
    发表于 08-29 15:58 0次下载

    二十进制编码器及Verilog HDL描述 Verilog HDL程序的基本结构及特点

    节通过硬件描述语言Verilog HDL对二十进制编码器的描述,介绍Verilog HDL程序的基本结构及特点。
    的头像 发表于 08-28 09:54 1391次阅读
    二十进制编码器及<b class='flag-5'>Verilog</b> <b class='flag-5'>HDL</b>描述 <b class='flag-5'>Verilog</b> <b class='flag-5'>HDL</b>程序的基本结构及特点

    Verilog例程 Verilog HDL程序设计教程

    Verilog大量例程(简单入门到提高)
    发表于 08-16 11:49 0次下载

    Cordic IP用户手册

    CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法,是 J.D.Volder1于 1959 年首次提出,主要用于三角函数、双曲线、指数
    发表于 08-09 06:45

    使用Verilog HDL描述寄存器的硬件

    刚接触数字集成电路设计,特别是Verilog HDL语言的同学,往往不理解什么时候变量需要设置为wire型,什么时候需要设置成reg型。
    发表于 07-13 15:53 599次阅读
    使用<b class='flag-5'>Verilog</b> <b class='flag-5'>HDL</b>描述寄存器的硬件

    Verilog HDL中使用分频器的8位计数器的设计

    电子发烧友网站提供《在Verilog HDL中使用分频器的8位计数器的设计.zip》资料免费下载
    发表于 06-15 10:14 0次下载
    在<b class='flag-5'>Verilog</b> <b class='flag-5'>HDL</b>中使用分频器的8位计数器的设计

    xilinx vivado调用cordic IP核进行实现时报错多重驱动?

    用vivado2019.2建立工程,工程中调用cordic IP核进行atan求解,功能仿真时正常且满足要求;综合时正常;实现时报错提示多重驱动。 如果经cordic计算后的输出值不用于后续的操作
    发表于 06-06 17:17

    一本Verilog HDL代码对应电路的书,助你快速编写可综合模型

    建立用于RTL综合的Verilog标准化子集。他是贝尔实验室所开发的ArchSyn综合系统的主要设计者之一。他曾为AT&T和Lucent的许多设计师讲授Verilog HDL语言和Verilo
    的头像 发表于 05-26 16:59 977次阅读
    一本<b class='flag-5'>Verilog</b> <b class='flag-5'>HDL</b>代码对应电路的书,助你快速编写可综合模型

    Verilog HDL数字集成电路设计原理与应用

    Verilog HDL数字集成电路设计原理与应用(蔡觉平)西安电子科技大学出版社
    发表于 05-26 15:23 0次下载

    Vivado HDL编写示例

    Vivado 软件提供了HDL编写中常用的示例,旨在帮助初学者更好地理解和掌握HDL编程,这里分享一下verilog代码示例。
    的头像 发表于 05-16 16:58 679次阅读