使用verilog 实现cordic 算法 ---- 向量模式

embedded/2025/2/13 15:32:39/

分享个人写的 coridic 向量模式的RTL:

cordic 算法向量模式主要作用是求出向量的模值以及 arctan (x/y) 值;

首先从仿真图去了解cordic 算法向量模式的 作用,不同数据测试;

后续拓展:将旋转模式和向量模式在同一个module封装使用起来。

1 . 展示仿真图:

a.下面是改变 x,y坐标得出的 arctan(y/x)值,以及这个坐标构成向量的模值
在这里插入图片描述

b.测试 tan1~10…
在这里插入图片描述

c.测试 tan1 、 tan0.5 、tan0.33 …
在这里插入图片描述

d. 测试 随机产生的 x y 值 ,利用 random函数
在这里插入图片描述

2 . RTL

module test_my_cordic_vec(input i_clk,input i_rst);reg signed	[31:0]	r_angle ;
reg					r_valid ;
reg signed  [31:0]  r_x     ;
reg signed  [31:0]  r_y     ;wire				w_ready;(*dont_touch = "true"*)
my_cordic_vec inst_my_cordic
(.i_clk             (i_clk   ),.i_rst             (i_rst   ),.i_iteration_count (16      ), //设置迭代次数 ,最大16次.i_setx            (r_x     ),.i_sety            (r_y     ),.i_set_angle       (0       ),.i_valid           (r_valid ),.o_xmod            (        ),.o_angle           (        ),.o_valid           (        ),.o_ready           (w_ready )
);//测试 45°
/* always @ (posedge i_clk or posedge i_rst) 
beginif (i_rst) beginr_x <= 65536;r_y <= 65536;end else if (w_ready && r_valid) beginr_x <= r_x + 65536;r_y <= r_y + 65536;		end else beginr_x <= r_x;r_y <= r_y;end
end *///测试 tan1 ~ 10 ~ 
/*  always @ (posedge i_clk or posedge i_rst) 
beginif (i_rst) beginr_x <= 65536;r_y <= 65536;end else if (w_ready && r_valid) beginr_x <= 65536;r_y <= r_y + 65536;		end else beginr_x <= r_x;r_y <= r_y;end
end  *//*  always @ (posedge i_clk or posedge i_rst) 
beginif (i_rst) beginr_x <= 65536;r_y <= 65536;end else if (w_ready && r_valid) beginr_x <= r_x + 65536;r_y <= 65536;		end else beginr_x <= r_x;r_y <= r_y;end
end  */// 测试 随机产生的 x、 y值 always @ (posedge i_clk or posedge i_rst) 
beginif (i_rst) beginr_x <= 65536;r_y <= 65536;end else if (w_ready && r_valid) beginr_x <= {$random} % 3284721; // 取 0~50 以内的数值r_y <= {$random} % 3284721;		end else beginr_x <= r_x;r_y <= r_y;end
end always @ (posedge i_clk or posedge i_rst) 
beginif (i_rst) r_valid <= 0;else if (w_ready && r_valid)r_valid <= 0;else if  (w_ready)r_valid <= 1;			else r_valid <= 0;	
endendmodule
//运算公式:
//x(i+1) = x(i) + y(i) * di * 2^(-i)
//y(i+1) = y(i) - x(i) * di * 2^(-i)
//z(i+1) = z(i) + arctan(di * 2^(-i))
//author : 技术小白爱FPGA
//备注:cordic 算法,向量模式,迭代次数固定 16次,可以自己任意设置,最大16次module my_cordic_vec (input                    i_clk                   ,input                    i_rst                   ,input [4:0]              i_iteration_count       ,input  signed [31:0]     i_setx                  ,input  signed [31:0]     i_sety                  ,input  signed [31:0]     i_set_angle             ,input                    i_valid                 ,output   signed [63:0]   o_xmod                  ,output   signed [31:0]   o_angle                 ,output                   o_valid                 ,output                   o_ready    );wire signed [31:0]  K_p = 39796    ;
wire signed	[31:0]	r_arctan [0:15];
wire				r_di           ;reg signed	[31:0]	r_setx         ;
reg signed	[31:0]	r_sety         ;
reg					ro_valid       ;
reg					ro_ready       ;
reg   signed [63:0] ro_xmod        ;
reg   signed [31:0] ro_angle       ;
reg	[4:0]			r_count        ;
reg					r_run_cal      ;
reg signed	[31:0]	r_angle        ;//存储 arctan 值,整体表示-----扩大2^16倍数,相当于将小数点定在16bit位置上
assign	r_arctan[0] = 2949120      ;
assign	r_arctan[1] = 1740967      ;
assign	r_arctan[2] = 919879       ;
assign	r_arctan[3] = 466945       ;
assign	r_arctan[4] = 234378       ;
assign	r_arctan[5] = 117303       ;
assign	r_arctan[6] = 58666        ;
assign	r_arctan[7] = 29334        ;
assign	r_arctan[8] = 14667        ;
assign	r_arctan[9] = 7333         ;
assign	r_arctan[10]= 3666         ;
assign	r_arctan[11]= 1833         ;
assign	r_arctan[12]= 916          ;
assign	r_arctan[13]= 458          ;
assign	r_arctan[14]= 229          ;
assign	r_arctan[15]= 114          ;//判断旋转的方向
assign r_di = (r_sety > 0 && r_run_cal)?1:0;assign o_xmod  = ro_xmod ;
assign o_angle = ro_angle;
assign o_ready = ro_ready;
assign o_valid = ro_valid;//运算迭代  >>>  --- > 算数右移,不改变符号位; 如果使用 >> ,移位,高位补0;
always @ (posedge i_clk) 
beginif (i_valid) beginr_setx <= i_setx;r_sety <= i_sety;endelse if (r_run_cal && r_di ) beginr_setx <= r_setx + (r_sety >>> r_count);r_sety <= r_sety - (r_setx >>> r_count);		end else if (r_run_cal && !r_di) beginr_setx <= r_setx - (r_sety >>> r_count);r_sety <= r_sety + (r_setx >>> r_count);	end
end//迭代运算次数
always @ (posedge i_clk or posedge i_rst) 
beginif (i_rst) beginr_count <= 0;end else if (r_count == i_iteration_count -1) beginr_count <= 0;endelse if (r_run_cal) beginr_count <= r_count + 1;end
endalways @ (posedge i_clk or negedge i_rst)
beginif (i_rst)r_angle <= 0;else if (i_valid)r_angle <= i_set_angle;		else if (r_di && r_run_cal)r_angle <= r_angle + r_arctan[r_count];else if (!r_di && r_run_cal)r_angle <= r_angle - r_arctan[r_count];else r_angle <= r_angle;
end//迭代运算标志
always @ (posedge i_clk or posedge i_rst) 
beginif (i_rst) beginr_run_cal <= 0;endelse if (r_count == i_iteration_count -1) beginr_run_cal <= 0;	endelse if(i_valid) beginr_run_cal <= 1;		endelse beginr_run_cal <= r_run_cal;	end
endalways @ (posedge i_clk or posedge i_rst) 
beginif (i_rst) beginro_ready <= 1;endelse if (i_valid || r_run_cal) beginro_ready <= 0;		end else beginro_ready <= 1;end
end//最终输出的 sin cos valid 信号
always @ (posedge i_clk or posedge i_rst) 
beginif (i_rst) ro_valid <= 0;else if (r_count == i_iteration_count -1)ro_valid <= 1;		else ro_valid <= 0;	
end//最终输出的 xmod angle 值
always @ (posedge i_clk or posedge i_rst) 
beginif (i_rst) beginro_xmod  <= 0;ro_angle <= 0;endelse if (r_count == i_iteration_count -1) beginro_xmod  <= r_setx * K_p;ro_angle <= r_angle;		end
endendmodule
module tb_cordic();reg i_clk;
reg i_rst;initial begin i_clk = 0;i_rst = 1;#100@(posedge i_clk)i_rst =0;
endalways #10 i_clk = ~i_clk;test_my_cordic_vec inst_test_my_cordic (.i_clk(i_clk), .i_rst(i_rst));endmodule

http://www.ppmy.cn/embedded/161898.html

相关文章

【Elasticsearch】bucket_sort

Elasticsearch 的bucket_sort聚合是一种管道聚合&#xff0c;用于对父多桶聚合&#xff08;如terms、date_histogram、histogram等&#xff09;的桶进行排序。以下是关于bucket_sort的详细说明&#xff1a; 1.基本功能 bucket_sort聚合可以对父聚合返回的桶进行排序&#xff…

基于 openEuler 构建 LVS-DR 群集。

1. 对比 LVS 负载均衡群集的 NAT 模式和 DR 模式&#xff0c;比较其各自的优势 。 2. 基于 openEuler 构建 LVS-DR 群集。 1.LVS&#xff08;Linux Virtual Server&#xff09;负载均衡群集的NAT模式和DR模式各有优势&#xff0c;具体如下&#xff1a; NAT模式优势 - 部署…

ollama部署deepseek实操记录

1. 安装 ollama 1.1 下载并安装 官网 https://ollama.com/ Linux安装命令 https://ollama.com/download/linux curl -fsSL https://ollama.com/install.sh | sh安装成功截图 3. 开放外网访问 1、首先停止ollama服务&#xff1a;systemctl stop ollama 2、修改ollama的servic…

如何通过 bugreport 分析 Android 系统日志?

&#x1f4e2; 1. 职业规划篇 来聊聊安卓职业规划&#xff1f;整机开发大专能做么&#xff1f; &#x1f4e2; 2.基础篇 基础篇.前言 基础篇.编译环境搭建 基础篇.源码目录简介 基础篇.系统 mk_bp 讲解 基础篇.开机动画定制 基础篇.定制桌面壁纸、导航方式 基础篇.系统属性、ap…

Java进阶:Dubbo

分布式RPC框架Apache Dubbo 1. 软件架构的演进过程 软件架构的发展经历了由单体架构、垂直架构、SOA架构到微服务架构的演进过程&#xff0c;下面我们分别了解一下这几个架构。 1.1 单体架构 架构说明&#xff1a; 全部功能集中在一个项目内&#xff08;All in one&#xf…

问题:通过策略模式+工厂模式+模板方法模式实现ifelse优化

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 示例&#xff1a;商城系统有会员系统&#xff0c;不同会员有不同优惠程度&#xff0c;普通会员不优惠&#xff1b;黄金会员打8折&#xff1b;白金会员优惠50元&#xff0c;再打7折&#xff1b; 问题描…

MT6835 21位 磁编码器 SPI 平台无关通用驱动框架 STM32

MT6835 21位 磁编码器 SPI 平台无关通用驱动框架 STM32 1. 获取代码&#xff1a;2. 加入你的项目2.1 以 STM32 为例:2.2 以 ESP-IDF 为例: 3. 对接 API3.1 以 STM32 为例&#xff1a; 4. 更多函数说明5. 写入 EEPROM 示例 MT6835 Framework 纯C语言实现&#xff0c;跨平台&…

【2024最新Java面试宝典】—— SpringBoot面试题(44道含答案)_java spingboot 面试题

37. 如何重新加载 Spring Boot 上的更改&#xff0c;而无需重新启动服务器&#xff1f;Spring Boot项目如何热部署&#xff1f;38. SpringBoot微服务中如何实现 session 共享 ?39. 您使用了哪些 starter maven 依赖项&#xff1f;40. Spring Boot 中的 starter 到底是什么 ?4…