关于FPGA之CORDIC算法的纯逻辑实现,善良的一休军“https://blog.csdn.net/qq_39210023/article/details/77456031”的博文均给出了较为详细完整的代码,整个算法的思想较为简单,就

是利用迭代流水线的思想,让角度不停逼近所求角度,一般迭代16次就已经比较接近所求角度值:

1、算法实现步骤:

1)设置迭代次数为16,则x0 = 0.607253,y0 = 0(关于初值的设定,上一篇博文有写到)并输入待计算的角度θ,θ在[-99.7°,99.7°]范围内。

2)根据三个迭代公式进行迭代,i从0至15:
xi+1 = xi – d iy i2-i
yi+1 = yi + d ix i2-i
zi+1 = zi - diθi
注:z0 = θ,di与zi同符号。

3) 经过16次迭代计算后,得到的x16 和y16分别为cosθ和sinθ。

2、代码解析:

1)16级流水线迭代实现

always  @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= (din<<);
end
else if(din_vld_ff[]) begin //初始化设置赋值 x0==0.607253*2^16,y0=0;
x[] <= {'b0,COS_LM};
y[] <= ;
z[] <= {'b0,din_ff,16'b0}; //角度初始化设置
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT0;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT0;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT1;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT1;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT2;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT2;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT3;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT3;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT4;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT4;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT5;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT5;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT6;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT6;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT7;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT7;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT8;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT8;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT9;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT9;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT10;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT10;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT11;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT11;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT12;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT12;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT13;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT13;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT14;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT14;
end
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
x[] <= ;
y[] <= ;
z[] <= ;
end
else if(din_vld_ff[])begin
if(z[][]==)begin
x[] <= x[] - (y[]>>>);
y[] <= y[] + (x[]>>>);
z[] <= z[] - `ROT15;
end
else begin
x[] <= x[] + (y[]>>>);
y[] <= y[] - (x[]>>>);
z[] <= z[] + `ROT15;
end
end
end

2)打拍同步

这点是我看了博主“洋葱洋葱”的代码,发现的简洁打拍写法。

a、din_vld是单比特信号,假设信号din_vld打4拍输入,可以对比下简洁写法和传统写法的代码量:

//传统写法:将信号din_vld_ff打4拍
always @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
din_vld_ff <=;
din_vld_ff0 <= ;
din_vld_ff1 <= ;
din_vld_ff2 <= ;
end
else begin
din_vld_ff0 <= din_vld_ff;
din_vld_ff1 <= din_vld_ff0;
din_vld_ff2 <= din_vld_ff1;
end
end //简洁写法:将信号din_vld_ff打4拍
always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
din_vld_ff <= () ;
end
else begin
din_vld_ff <= ({din_vld_ff[:],din_vld}) ; //din_vld为1bit
end
end

以上是单比特din_vld打4拍的对比写法,假如是要打十几拍,可以明显看出简洁写法的代码量少很多,这种打拍子的写法值得推崇。

b、din_vld是多比特信号,假设din_vld同样打4拍输入,利用简洁写法可以写成:

always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
din_vld_ff <= () ;
end
else begin
din_vld_ff <= ({din_vld_ff[5:],din_vld}) ; //din_vld为2bit
end
end

3)反正切函数,要注意由于θ在[-99.7°,99.7°]范围内,因此在角度输入时要注意换成第一、第四象限,最后结果输出时要注意还原成真实角度。

always  @(posedge clk or negedge rst_n)begin
if(rst_n=='b0)begin
din_ff <= ;
flag <= ;
end
else if(din_vld)begin
if(din<)begin
din_ff = din;
flag = ;
end
else if(din<)begin
din_ff = din-;
flag = ;
end
else if(din<)begin
din_ff = din-;
flag = ;
end
else begin
din_ff = din-;
flag = ;
end
end
end
//角度还原为真实值
always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
dout_sin <= () ;
end
else if(flag_ff[:]==)begin //第一象限,y(16) = sin(x)
dout_sin <= (y[]) ;
end
else if(flag_ff[:]==)begin //第二象限,Sin(X)=Sin(A+90)=CosA,Cos(X)=Cos(A+90)=-SinA
dout_sin <= (x[]) ;
end
else if(flag_ff[:]==)begin //第三象限,the Sin(X)=Sin(A+180)=-SinA,Cos(X)=Cos(A+180)=-CosA
dout_sin <= ~(y[]) + 'b1 ;
end
else if(flag_ff[:]==)begin //第四象限,the Sin(X)=Sin(A+270)=-CosA,Cos(X)=Cos(A+270)=SinA
dout_sin <= ~(x[])

至此,基于FPGA的cordic算法代码实现需要注意的问题就讨论到这里。

FPGA之CORDIC算法实现_代码实现(下)的更多相关文章

  1. FPGA之CORDIC算法实现_理论篇(上)

    关于cordic的算法原理核心思想就是规定好旋转角度,然后通过不停迭代逐步逼近的思想来实现数学求解,网上关于这部分的资料非常多,主要可以参考: 1)https://blog.csdn.net/qq_3 ...

  2. 基于FPGA的Cordic算法实现

    CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法,是J.D.Volder1于1959年首次提出,主要用于三角函数.双曲线.指数.对数的 ...

  3. 基于FPGA的cordic算法的verilog初步实现

    最近在看cordic算法,由于还不会使用matlab,真是痛苦,一系列的笔算才大概明白了这个算法是怎么回事.于是尝试用verilog来实现.用verilog实现之前先参考软件的程序,于是先看了此博文h ...

  4. 定点CORDIC算法求所有三角函数及向量模的原理分析、硬件实现(FPGA)

    一.CORDIC算法 CORDIC(Coordinate Rotation DIgital Computer)是一种通过迭代对多种数学函数求值的方法,它可以对三角函数.双曲函数和平面旋转问题进行求解. ...

  5. cordic算法的fpga实现

    cordic算法参考:http://wenku.baidu.com/view/6c623aa8910ef12d2bf9e732.html 这是百度文库的一个文档,详细介绍了cordic算法的基本内容. ...

  6. [黑金原创教程] FPGA那些事儿《数学篇》- CORDIC 算法

    简介 一本为完善<设计篇>的书,教你CORDIC算法以及定点数等,内容请看目录. 贴士 这本教程难度略高,请先用<时序篇>垫底. 目录 Experiment 01:认识CORD ...

  7. 三角函数计算,Cordic 算法入门

    [-] 三角函数计算Cordic 算法入门 从二分查找法说起 减少乘法运算 消除乘法运算 三角函数计算,Cordic 算法入门 三角函数的计算是个复杂的主题,有计算机之前,人们通常通过查找三角函数表来 ...

  8. (转)三角函数计算,Cordic 算法入门

    由于最近要使用atan2函数,但是时间上消耗比较多,因而网上搜了一下简化的算法. 原帖地址:http://blog.csdn.net/liyuanbhu/article/details/8458769 ...

  9. Cordic算法——verilog实现

    上两篇博文Cordic算法--圆周系统之旋转模式.Cordic算法--圆周系统之向量模式做了理论分析和实现,但是所用到的变量依然是浮点型,而cordic真正的用处是基于FPGA等只能处理定点的平台.只 ...

随机推荐

  1. 乘风破浪:LeetCode真题_014_Longest Common Prefix

    乘风破浪:LeetCode真题_014_Longest Common Prefix 一.前言 如何输出最长的共同前缀呢,在给定的字符串中,我们可以通过笨办法去遍历,直到其中某一个字符不相等了,这样就得 ...

  2. 沉淀再出发:redis的安装和使用

    沉淀再出发:redis的安装和使用 一.前言 下面让我们看看Redis这个键值对内存数据库的使用方法和相关注意事项. 二.Redis的安装和使用 2.1.Redis的定义 REmote DIction ...

  3. 最优化作业 共轭梯度法 matlab代码

    syms f x1 x2 f=(1/2)*x1^2+x2^2; x=[2;1]; a=[1 0;0 2];% A g1=diff(f,x1); g2=diff(f,x2); g=[g1;g2];%导数 ...

  4. 深入浅出SharePoint2013——常用术语

    CAS(Code Access Security)自定义代码访问安全性 Sandboxed solution 沙箱解决方案

  5. Java自学之路(新手一定要看)

    Java自学之路(新手一定要看) 转自尚学堂 JAVA自学之路 一:学会选择 为了就业,不少同学参加各种各样的培训. 决心做软件的,大多数人选的是java,或是.net,也有一些选择了手机.嵌入式.游 ...

  6. python面向对象之类成员修饰符

      类的所有成员分为: 公有成员,在任何地方都能访问 私有成员,只有在类的内部才能访问 私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线.(特殊成员除外,例如:__init__.__c ...

  7. idea更新maven依赖包

    IntelljIdea 自动载入Maven依赖的功能很好用,但有时候会碰到问题,导致pom文件修改却没有触发自动重新载入的动作,此时需要手动强制更新依赖. 如下: (1)右键单击项目: (2)在弹出菜 ...

  8. MVC5新特性(一)之RouteAttribute打造自己的URL规则

    1.RouteAttribute概述 RouteAttribute的命名空间是System.Web.Mvc,区别与web api的RouteAttribute(它的命名空间是System.Web.Ht ...

  9. Android攻城狮学习笔记—入门篇一

    第一章 搭建Android开发环境 1.1 环境组成 JDK(Java Development Kit) Eclipse Android SDK(Software Development Kit) A ...

  10. UVALive - 6837 Kruskal+一点性质(暴力枚举)

    ICPC (Isles of Coral Park City) consist of several beautiful islands. The citizens requested constru ...