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等只能处理定点的平台.只 ...
随机推荐
- 如何在Code First、Database First和Model First之间选择
Code First.Database First和Model First基本图解: 1)Database First: 如果数据库已经存在,可以使用VS自动生成数据模型,已经相关的edmx信息 2) ...
- c++计算器后续(2)
自娱自乐: 大概是了解了一下前缀.中缀.后缀表示法是啥,并没有去深究,比如考虑实现啊,然后Calculation类里面的计算方法还是选用原来的直接对中缀表达式求值,只是把代码改得规范点,以上. 各表示 ...
- facebook页面种简单测试js调用flash开放的js接口的方法
无意间折腾出来的,此方法很triky,但是很简单有效. 背景说明: facebook种内嵌的iframe无法直接访问. 解决方法: chrome浏览器为例 1.右键查看iframe源代码,此时进入if ...
- Git commit comment 汇总标准
参考汇总互联网其它文章建议,结合PEP 257 Docstring Conventions的描述,总结的Git 注释风格,作为个人执行的标准.内容如下: 遵循标准: 1,所有注释尽量坚持使用英文,如果 ...
- python网络爬虫--简单爬取糗事百科
刚开始学习python爬虫,写了一个简单python程序爬取糗事百科. 具体步骤是这样的:首先查看糗事百科的url:http://www.qiushibaike.com/8hr/page/2/?s=4 ...
- BZOJ4032:[HEOI2015]最短不公共子串(SAM)
Description 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列” ...
- 获取主机ip地址
直接访问http://icanhazip.com
- 获取URL链接正则
public static final String HTTP_PATTERN = "http://[a-zA-Z0-9\\.\\/\\-_]+";
- 404 Note Found队-Alpha3
目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:丹丹 组员7:家伟 组员8:政演 组员9:鸿杰 组员10:刘一好 组员11:何宇恒 展示组内最 ...
- nRF5 SDK for Mesh(八) Exploring Mesh APIs using light switch example,使用 灯开关 案例探索BLE mesh 的APIS
Exploring Mesh APIs using light switch example The light switch example is meant to showcase the API ...