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等只能处理定点的平台.只 ...
随机推荐
- SRAM(静态)存储器芯片的读/写周期
一. 要保证正确地读/写,必须注意CPU时序与存储器读/写周期的配合.一般存储器芯片手册都会给出芯片读/写周期的时序图. Intel 2114芯片的读.写周期时序如图所示. 二. 读周期 读操作时,必 ...
- HTTP协议图--HTTP 响应状态码(重点分析)
1. 状态码概述 HTTP 状态码负责表示客户端 HTTP 请求的返回结果.标记服务器端的处理是否正常.通知出现的错误等工作. HTTP 状态码如 200 OK ,以 3 位数字和原因短语组成.数字中 ...
- 1、Node.js 我的开始+安装
内容:为什么开始学习node.js,需要安装哪些东西,及其安装过程 node.js的学习是按照菜鸟教程的node.js教程学习,学习这项技术主要是因为需要使用. 需要安装的东西:解释器,IDE(集成开 ...
- java查找字符串里与指定字符串相同的个数
public class EmployeeDemo { //方法一: public int search(String str,String strRes) {//查找字符串里与指定字符串相同的个数 ...
- python 中的set与list,tuple
__author__ = 'liunnis' #-*-coding:utf-8 -*- a=[1,2,3,4,4] print a print list(set(a)) b=[str(i) for i ...
- 消息中间件--"rocketmq"01之环境搭建
前置知识 ssh工具 连接linux工具SecureCRT 颜色设置,参考 中文乱码,参考 Linux相关知识 centos7 防火墙firewalld的基本使用,参考 启动: systemctl s ...
- webpack中使用babel处理es6语法
index.js const arr = [ new Promise(()=>{}), new Promise(()=>{}) ]; arr.map(item => { consol ...
- 安装TA-Lib时报错:ubuntu****, Command "/usr/bin/python -u -c "import setuptools, tokenize;__file__='
使用pip install TA-Lib 时报错: ERROR: Complete output from command /usr/bin/python3 -u -c 'import setupto ...
- weblogic之CVE-2016-0638反序列化分析
此漏洞是基于CVE-2015-4852漏洞进行黑名单的绕过,CVE-2015-4852补丁主要应用在三个位置上 weblogic.rjvm.InboundMsgAbbrev.class :: Serv ...
- 4、Android-数据存储方案(SQLite数据库存储)
4.4.SQLite数据库存储 这是Android内置的数据库 是一款轻量级的关系型数据库 运算速度非常快.占用资源少.通常只需要几百kb的内存就够了 因而特别适合在移动端设备上使用 SQLite不仅 ...