FPGA之CORDIC算法实现_代码实现(下)
关于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算法实现_代码实现(下)的更多相关文章
- FPGA之CORDIC算法实现_理论篇(上)
关于cordic的算法原理核心思想就是规定好旋转角度,然后通过不停迭代逐步逼近的思想来实现数学求解,网上关于这部分的资料非常多,主要可以参考: 1)https://blog.csdn.net/qq_3 ...
- 基于FPGA的Cordic算法实现
CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法,是J.D.Volder1于1959年首次提出,主要用于三角函数.双曲线.指数.对数的 ...
- 基于FPGA的cordic算法的verilog初步实现
最近在看cordic算法,由于还不会使用matlab,真是痛苦,一系列的笔算才大概明白了这个算法是怎么回事.于是尝试用verilog来实现.用verilog实现之前先参考软件的程序,于是先看了此博文h ...
- 定点CORDIC算法求所有三角函数及向量模的原理分析、硬件实现(FPGA)
一.CORDIC算法 CORDIC(Coordinate Rotation DIgital Computer)是一种通过迭代对多种数学函数求值的方法,它可以对三角函数.双曲函数和平面旋转问题进行求解. ...
- cordic算法的fpga实现
cordic算法参考:http://wenku.baidu.com/view/6c623aa8910ef12d2bf9e732.html 这是百度文库的一个文档,详细介绍了cordic算法的基本内容. ...
- [黑金原创教程] FPGA那些事儿《数学篇》- CORDIC 算法
简介 一本为完善<设计篇>的书,教你CORDIC算法以及定点数等,内容请看目录. 贴士 这本教程难度略高,请先用<时序篇>垫底. 目录 Experiment 01:认识CORD ...
- 三角函数计算,Cordic 算法入门
[-] 三角函数计算Cordic 算法入门 从二分查找法说起 减少乘法运算 消除乘法运算 三角函数计算,Cordic 算法入门 三角函数的计算是个复杂的主题,有计算机之前,人们通常通过查找三角函数表来 ...
- (转)三角函数计算,Cordic 算法入门
由于最近要使用atan2函数,但是时间上消耗比较多,因而网上搜了一下简化的算法. 原帖地址:http://blog.csdn.net/liyuanbhu/article/details/8458769 ...
- Cordic算法——verilog实现
上两篇博文Cordic算法--圆周系统之旋转模式.Cordic算法--圆周系统之向量模式做了理论分析和实现,但是所用到的变量依然是浮点型,而cordic真正的用处是基于FPGA等只能处理定点的平台.只 ...
随机推荐
- Exchange 2007 前端 IIS 内存占用过高
已经碰见了好几次,在Exchange2007的场景中,前端角色所在服务器的w3wp.exe进程总是占用大量内存,以至于触发反压组件,停止了正常的邮件流投递,造成业务中断. 终于下决心查一下到底问题问题 ...
- 使用TryUpdateModel进行数据更新
在控制器中可以使用TryUpdateModel或者UpdateModel方法来对指定的数据Model进行更新,如图所示的更新操作. POST请求数据如下所示 使用如下代码就可以对指定的字段进行更新 使 ...
- 沉淀,再出发:VUE的简单理解
沉淀,再出发:VUE的简单理解 一.前言 Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的渐进式框架.Vue 只关注视图层,采用自底向上增量开发的设计.Vue 的目标是通过 ...
- codeforces 420D Cup Trick
codeforces 420D Cup Trick 题意 题解 官方做法需要用到线段树+平衡树(? 如果数据小的话似乎可以用莫队).然后代码好长好长.我补了一个只要用到树状数组的做法. 代码 #inc ...
- node.js和MongoDB学习网址
回想我写的node.js和MongoDB的博客,都是菜鸟教程那里的知识,所以我打算不写了,那些都是基础,在项目开发中,我发现单单有那些基础不行,这些基础可以尽快学好,然后学习项目开发过程 下面是两个教 ...
- Shell的egrep、grep、fgrep命令的使用
Linux egrep 命令用于在文件内查找指定的字符串.与grep-E使用语法及参数相似,不同点在于解读字符串的方法. 语法: egrep [范本模式] [文件或目录] 参数说明: [范本模式]:查 ...
- spring mvc 多数据源切换,不支持事务控制[一]
一个项目中需要使用两个数据库,Oracle 和Mysql ,于是参考各个blog,实现此功能.写好后才发现,原来的事务失效了,我去... spring-mybatis.xml 配置 <bean ...
- sublime text 3 搭建python ide
SublimeCodeIntel 代码提示插件 安装步骤: 1.打开Package Control[Preferences>>Package Control] 2.输入 install 选 ...
- Kali-linux使用Nessus
Nessus号称是世界上最流行的漏洞扫描程序,全世界有超过75000个组织在使用它.该工具提供完整的电脑漏洞扫描服务,并随时更新其漏洞数据库.Nessus不同于传统的漏洞扫描软件,Nessus可同时在 ...
- [转]PowerDesigner使用常见问题锦集
1. 附加:PowerDesigner 的调色板(Palette)快捷工具栏不见了,怎么重新打开,找回来呢 上网搜索了一下”powerdesigner 图形工具栏”,找到了找回PowerDesigne ...