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等只能处理定点的平台.只 ...
随机推荐
- Linux server配置安装Java,Tomcat服务器
系统:Ubuntu 16.04 dev_desktop 1.Java安装并配置环境变量 (1)从Java官方网站下载最新版JDK: http://www.oracle.com/technetwork/ ...
- Python学习---Python的框架基础学习
框架基础 框架实质: 所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端 B/S结构的响应: import socket def handle_requ ...
- Sqoop操作集合
1.在hive中建一个与mysql中一模一样的表 sqoop create-hive-table --connect jdbc:mysql://***.**.***.**:3306/数据库名称 --t ...
- 为什么TCP协议终止链接要四次?
为什么TCP协议终止链接要四次? 1.当主机A确认发送完数据且知道B已经接受完了,想要关闭发送数据口(当然确认信号还是可以发),就会发FIN给主机B. 2.主机B收到A发送的FIN,表示收到了,就会发 ...
- 微软最新设计Fluent Design System初体验
微软最新设计Fluent Design System初体验 本文图片不全!建议移步知乎专栏查看!!! https://zhuanlan.zhihu.com/p/30582886 原创 2017-11- ...
- strerror的坑
最近写的一段代码,总是出core,精简了一下,稳定复现. #include <stdio.h> #include <errno.h> int main() { printf(& ...
- Hadoop学习之路(二十)MapReduce求TopN
前言 在Hadoop中,排序是MapReduce的灵魂,MapTask和ReduceTask均会对数据按Key排序,这个操作是MR框架的默认行为,不管你的业务逻辑上是否需要这一操作. 技术点 MapR ...
- BurpSuite Intruder 4种攻击模式
BurpSuite intruder attack-type 4种爆破模式 Sniper 单参数爆破,多参数时同一个字典按顺序替换各参数,总之初始值有一个参数不变 Battering ram 多参数同 ...
- array和matrix
array:数组 matrix:矩阵 list:列表 a = [[1,2,3],[4,5,6]] 两种array的定义方式,第一种方式可以看出list不是array,但却有很大的联系 a = np.a ...
- 每天to do list
至少写一页书 写代码做一个实验 读10+页专业书 一年时间,如果经济状况没有改善的话,回归企业.