最近在看cordic算法,由于还不会使用matlab,真是痛苦,一系列的笔算才大概明白了这个算法是怎么回事。于是尝试用verilog来实现。用verilog实现之前先参考软件的程序,于是先看了此博文http://blog.csdn.net/liyuanbhu/article/details/8458769也不截图了,因为怕图形被其他博客网站检测到后屏蔽图片,造成此博文无法正常阅读。

阅读此博文,需要先阅读上面这个博文的内容。

  这是此博文中的C代码。避免浮点运算,所以angle数组里面的角度值都扩大了256倍。此程序中计算点(10,20)与X轴之间的夹角。最终运行结果是16238。而16238/256=63.43

 #include <stdio.h>
#include <stdlib.h> //double my_atan2(double x, double y); double my_atan2 (int x, int y)
{
const int angle[] = {, , , , , , , , , , , , , , }; int i = ;
int x_new, y_new;
int angleSum = ; x *= ;// ½« X Y ·Å´óһЩ£¬½á¹û»á¸ü׼ȷ
y *= ; printf ("org_x = %d, org_y=%d\n",x,y); for(i = ; i < ; i++)
{
if(y > )
{
x_new = x + (y >> i);
y_new = y - (x >> i);
x = x_new;
y = y_new;
angleSum += angle[i];
}
else
{
x_new = x - (y >> i);
y_new = y + (x >> i);
x = x_new;
y = y_new;
angleSum -= angle[i];
}
printf("Debug: i = %d x=%d, y =%d angleSum = %d, angle = %d\n", i,x,y ,angleSum, angle[i]);
}
return angleSum;
} void main()
{
double z= ;
z = my_atan2(10.0, 20.0);
printf("\n z = %lf \n", z); }

  既然有了C 就很好进行verilog设计。

  先谈架构。

  1,先将角度数据放到一个rom中进行存储

  2,取一个数,运算一个数。直到循环结束。

  这也就是所谓的cordic算法的向量模式。用来求角度。先看顶层

 //
//
//
// module cordic_rotation_top (
clock ,
rst_n ,
x_crd,
y_crd,
ena ,
deg_sum
);
input clock ;
input rst_n ;
input [:] x_crd ;
input [:] y_crd ;
input ena ;
output [:] deg_sum ; wire [:] deg_addr ;
wire [:] deg_data ; alt_ip_rom_cordic u_rom (
.address (deg_addr),
.clock (clock),
.q (deg_data)
); cordic_rotation u_cord (
.clk (clock),
.rst_n (rst_n),
.ena (ena),
.x_crd (x_crd),
.y_crd (y_crd),
.deg_data (deg_data),
.deg_addr (deg_addr),
.deg_sum (deg_sum)
); endmodule

rom的初始化文件为

再看运算单元。

 module cordic_rotation (
clk ,
rst_n ,
ena ,
x_crd,
y_crd,
deg_data,
deg_addr,
deg_sum
); input clk ;
input rst_n ;
input ena ;
input [:] x_crd ; //x coordinate
input [:] y_crd ; //y coordinate
input [:] deg_data ;
output [:] deg_addr ;
output reg[:] deg_sum ; // ------ rotation count 0 - 14 -------
reg [:] rot_cnt ;
reg [:] rot_cnt_r ;
wire opr_en ;
assign opr_en = ((rot_cnt_r<'d15)&(ena)) ; always @ (posedge clk or negedge rst_n)
if (!rst_n) begin
rot_cnt <= 'd0 ;
rot_cnt_r<= 'd0;
end
else if (opr_en) begin
rot_cnt <= rot_cnt + 'd1 ;
rot_cnt_r<= rot_cnt ;
end
else if (!ena) begin
rot_cnt <= 'd0 ;
rot_cnt_r<= rot_cnt ;
end
assign deg_addr = rot_cnt ; //---------------------------------------
reg cal_cnt ;
reg signed [:] x_d, y_d ;
always @ (posedge clk or negedge rst_n)
if (!rst_n) begin
x_d <= 'd0 ;
y_d <= 'd0 ;
deg_sum <= 'd0 ;
cal_cnt <= 'd0 ;
end
else if (opr_en) begin
case (cal_cnt)
'd0 : begin
x_d <= {'d0,x_crd};
y_d <= {'d0,y_crd};
deg_sum <= 'd0 ;
cal_cnt <= 'd1 ;
end
'd1 : begin
if ((y_d[])|(y_d=='d0)) begin
x_d <= x_d - (y_d >>> rot_cnt_r);
y_d <= y_d + (x_d >>> rot_cnt_r) ;
deg_sum <= deg_sum - deg_data ;
end
else begin
x_d <= x_d + (y_d >>> rot_cnt_r);
y_d <= y_d - (x_d >>> rot_cnt_r) ;
deg_sum <= deg_sum + deg_data ;
end
end
endcase
end
else begin
cal_cnt <= 'd0 ;
end endmodule

rot_cnt作为rom的地址。但是由于rom返回度数值需要一个周期,所以下面的运算单元需要等待一个周期才可以进行运算,于是有了rot_cnt_r这个参数。

于是问题又来了,上面的是向量模式。还有一个旋转模式。于是开始捣鼓。

稍微将上述的C代码进行修改,计算30度的cos30,以及sin30

 #include <stdio.h>
#include <stdlib.h> //double my_atan2(double x, double y); double my_atan2 (int x, int y)
{
const int angle[] = {, , , , , , , , , , , , , , }; int i = ;
int x_new, y_new;
int angleSum = *; x *= ;// ½« X Y ·Å´óһЩ£¬½á¹û»á¸ü׼ȷ
y *= ; printf ("org_x = %d, org_y=%d\n",x,y); for(i = ; i < ; i++)
{
if(angleSum <= )
{
x_new = x + (y >> i);
y_new = y - (x >> i);
x = x_new;
y = y_new;
angleSum += angle[i];
}
else
{
x_new = x - (y >> i);
y_new = y + (x >> i);
x = x_new;
y = y_new;
angleSum -= angle[i];
}
printf("Debug: i = %d x=%d, y =%d angleSum = %d, angle = %d\n", i,x,y ,angleSum, angle[i]);
}
return angleSum;
} void main()
{
double z= ;
z = my_atan2(1.0, 0.0);
printf("\n z = %lf \n", z); }

结果是这样子的

先看已知条件:

1,cordic算法中的Kn极限值=1.6476 。  1/Kn=0.6073.

2,上述软件设置y=0. x=1.并且坐标值扩大了1024倍。从公式上,cosa= x      sina= y     角度a=30度

3,运算结果x=1461.  y=844

好,开始运算  cosa=1461/(1024*1.6476)=0.8659。 cos30=0.8660.

      sina=844/(1024*1.6476) = 0.500    。 sin30 = 0.5

精度由loop次数相关

好,既然验证了这个软件程序是可以的。那么就将它转换成Verilog的程序

 //cordic 算法的旋转模式 

 module cordic_rotation (
clk ,
rst_n ,
ena ,
x_crd,
y_crd,
deg_data,
deg_addr,
deg_sum
); input clk ;
input rst_n ;
input ena ;
input [:] x_crd ; //x coordinate
input [:] y_crd ; //y coordinate
input [:] deg_data ;
output [:] deg_addr ;
output [:] deg_sum ; parameter DEGREE = ;
parameter DEG_PARA = (DEGREE*) ;
// ------ rotation count 0 - 14 -------
reg [:] rot_cnt ;
reg [:] rot_cnt_r ;
wire opr_en ;
assign opr_en = ((rot_cnt_r<'d15)&(ena)) ; always @ (posedge clk or negedge rst_n)
if (!rst_n) begin
rot_cnt <= 'd0 ;
rot_cnt_r<= 'd0;
end
else if (opr_en) begin
rot_cnt <= rot_cnt + 'd1 ;
rot_cnt_r<= rot_cnt ;
end
else if (!ena) begin
rot_cnt <= 'd0 ;
rot_cnt_r<= rot_cnt ;
end
assign deg_addr = rot_cnt ; //---------------------------------------
reg cal_cnt ;
reg signed [:] deg_sum_r ;
reg signed [:] x_d, y_d ;
always @ (posedge clk or negedge rst_n)
if (!rst_n) begin
x_d <= 'd0 ;
y_d <= 'd0 ;
deg_sum_r <= 'd0 ;
cal_cnt <= 'd0 ;
end
else if (opr_en) begin
case (cal_cnt)
'd0 : begin
x_d <= {'d0,x_crd};
y_d <= {'d0,y_crd};
deg_sum_r <= DEG_PARA ;
cal_cnt <= 'd1 ;
end
'd1 : begin
if ((deg_sum_r[])|(deg_sum_r=='d0)) begin //<=0
x_d <= x_d + (y_d >>> rot_cnt_r);
y_d <= y_d - (x_d >>> rot_cnt_r) ;
deg_sum_r <= deg_sum_r + deg_data ;
end
else begin
x_d <= x_d - (y_d >>> rot_cnt_r);
y_d <= y_d + (x_d >>> rot_cnt_r) ;
deg_sum_r <= deg_sum_r - deg_data ;
end
end
endcase
end
else begin
cal_cnt <= 'd0 ;
end assign deg_sum = deg_sum_r ; endmodule

这个程序也是在上一个程序的基础上修改的。所以尽量少改动。而是修改了tb。所以需要看看TB是怎么弄的

 ///
//
//
//
`timescale 1ns/100ps module cordic_rotation_top_tb ;
reg clock ,rst_n ;
reg [:] x_crd ,y_crd ;
reg ena ; wire [:] deg_sum ; cordic_rotation_top u_top (
.clock (clock),
.rst_n (rst_n),
.x_crd (x_crd),
.y_crd (y_crd),
.ena (ena),
.deg_sum (deg_sum)
); always # clock = ~clock ;
initial begin
clock = ; rst_n = ;
x_crd = * ; y_crd=;
ena = ;
# rst_n = ;
#
/*
ena = 0 ;
#40
x_crd = 10*1024 ; y_crd=10*1024;
ena = 1 ;
#350 ena = 0 ;
#40
x_crd = 20*1024 ; y_crd=10*1024;
ena = 1 ;
#350 */
$stop ;
end endmodule

将第28行替换为     x_crd = 10*1024 ; y_crd=20*1024;     就变成了上一个工程的测试代码。

此程序输出结果为:

和软件程序输出结果相同。

有没有发现问题,在计算这些东西的时候,很多网络博文说精度和loop次数相关。但是这个扩大256倍运算到第11次就已经定住了。后面的输出结果白循环了。

欢迎加入: FPGA广东交流群:162664354

      FPGA开发者联盟: 485678884

    微信公众号:FPGA攻城狮之家

基于FPGA的cordic算法的verilog初步实现的更多相关文章

  1. 基于FPGA的Cordic算法实现

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

  2. FPGA之CORDIC算法实现_代码实现(下)

    关于FPGA之CORDIC算法的纯逻辑实现,博主洋葱洋葱“https://www.cnblogs.com/cofin/p/9188629.html”以及善良的一休军“https://blog.csdn ...

  3. 基于FPGA的RGB565_YCbCr_Gray算法实现

    前面我们讲了基于FPGA用VGA显示一副静态图片,那么接下来我们就接着前面的工程来实现我们图像处理的基础算法里最简单的一个那就是彩色图像转灰度的实现. 将彩色图像转化为灰度的方法有两种,一个是令RGB ...

  4. cordic算法的verilog实现及modelsim仿真

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

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

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

  6. 基于FPGA的肤色识别算法实现

    大家好,给大家介绍一下,这是基于FPGA的肤色识别算法实现. 我们今天这篇文章有两个内容一是实现基于FPGA的彩色图片转灰度实现,然后在这个基础上实现基于FPGA的肤色检测算法实现. 将彩色图像转化为 ...

  7. 使用CORDIC算法求解角度正余弦及Verilog实现

    本文是用于记录在了解和学习CORDIC算法期间的收获,以供日后自己及他人参考:并且附上了使用Verilog实现CORDIC算法求解角度的正弦和余弦的代码.简单的testbench测试代码.以及在Mod ...

  8. 基于FPGA的中值滤波算法实现

    在这一篇开篇之前,我需要解决一个问题,上一篇我们实现了基于FPGA的均值滤波算法的实现,最后的显示效果图上发现有一些黑白色的斑点,我以为是椒盐噪声,然后在做基于FPGA的中值滤波算法的实验时,我发现黑 ...

  9. 基于FPGA的腐蚀膨胀算法实现

    本篇文章我要写的是基于的腐蚀膨胀算法实现,腐蚀膨胀是形态学图像处理的基础,,腐蚀在二值图像的基础上做"收缩"或"细化"操作,膨胀在二值图像的基础上做" ...

随机推荐

  1. HDU1963 && POJ2063:Investment(完全背包)

    Problem Description John never knew he had a grand-uncle, until he received the notary’s letter. He ...

  2. Oracle中的日期和字符串互相转换

    转载出处:http://blog.sina.com.cn/s/blog_44a005380100k6rv.html TO_DATE格式(以时间:2007-11-02   13:45:25为例)    ...

  3. 寻找所有javaee官方文档的方法

    所有跟java有关的首先要去oracle官网. 所有文档都放在: Oracle Technology Network 即:著名的OTN网站 链接在首页的最后一个标签: 侧面就是documentions ...

  4. 关于gradle /Users/xxxx/Documents/workspace/fontmanager/.gradle/2.2.1/taskArtifacts/cache.properties (No such file or directory)报错办法

    转自:http://www.cnblogs.com/raomengyang/p/4367620.html   Android Studio报错: What went wrong: java.io.Fi ...

  5. java反编译命令javap

    1. 输出所有类和成员 javap -private XX.class 2. 输出分解后的代码 javap -c XX.class

  6. for循环例子1、2、3

    /* Name:for循环例子1.2.3 Copyright: By.不懂网络 Author: Yangbin Date:2014年2月12日 02:12:41 Description:该代码用来熟悉 ...

  7. 经典灰鸽子lcx

    方法1路由配置 在路由器配置 进入虚拟服务器 填入ip 端口 就可以了方法2内网域名解析想以前的花生客 科迈都有这项免费业务但现在基本不提供了如果那个网站还有内网解析的功能 大家一定要发上来哦方法3p ...

  8. css3_note

    css3基础 css3选择器 属性选择器 属性选择器基本上IE7+都支持,可以放心的使用,参见caniuse [attr] [attr=val] [attr*=val] [attr^=val] [at ...

  9. BZOJ 1096 [ZJOI2007]仓库建设(斜率优化DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1096 [题目大意] 有个斜坡,有n个仓库,每个仓库里面都有一些物品,物品数目为p,仓库 ...

  10. HDU 5769 Substring(后缀数组)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5769 [题目大意] 在一个串中求出包含字母的子串个数, 只要存在一个字符不相等的子串即可视为不同的 ...