当前位置: 首页 > article >正文

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

分享个人写的 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) 
begin
	if (i_rst) begin
		r_x <= 65536;
		r_y <= 65536;
	end else if (w_ready && r_valid) begin
		r_x <= r_x + 65536;
		r_y <= r_y + 65536;		
	end else begin
		r_x <= r_x;
		r_y <= r_y;
	end
end */

//测试 tan1 ~ 10 ~ 
/*  always @ (posedge i_clk or posedge i_rst) 
begin
	if (i_rst) begin
		r_x <= 65536;
		r_y <= 65536;
	end else if (w_ready && r_valid) begin
		r_x <= 65536;
		r_y <= r_y + 65536;		
	end else begin
		r_x <= r_x;
		r_y <= r_y;
	end
end  */

/*  always @ (posedge i_clk or posedge i_rst) 
begin
	if (i_rst) begin
		r_x <= 65536;
		r_y <= 65536;
	end else if (w_ready && r_valid) begin
		r_x <= r_x + 65536;
		r_y <= 65536;		
	end else begin
		r_x <= r_x;
		r_y <= r_y;
	end
end  */

// 测试 随机产生的 x、 y值 
 always @ (posedge i_clk or posedge i_rst) 
begin
	if (i_rst) begin
		r_x <= 65536;
		r_y <= 65536;
	end else if (w_ready && r_valid) begin
		r_x <= {$random} % 3284721; // 取 0~50 以内的数值
		r_y <= {$random} % 3284721;		
	end else begin
		r_x <= r_x;
		r_y <= r_y;
	end
end 

always @ (posedge i_clk or posedge i_rst) 
begin
	if (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;	
end

endmodule
//运算公式:
//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) 
begin
	if (i_valid) begin
		r_setx <= i_setx;
		r_sety <= i_sety;
	end
	else if (r_run_cal && r_di ) begin
		r_setx <= r_setx + (r_sety >>> r_count);
		r_sety <= r_sety - (r_setx >>> r_count);		
	end else if (r_run_cal && !r_di) begin
		r_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) 
begin
	if (i_rst) begin
		r_count <= 0;
	end else if (r_count == i_iteration_count -1) begin
		r_count <= 0;
	end
	else if (r_run_cal) begin
		r_count <= r_count + 1;
	end
end

always @ (posedge i_clk or negedge i_rst)
begin
	if (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) 
begin
	if (i_rst) begin
		r_run_cal <= 0;
	end
	else if (r_count == i_iteration_count -1) begin
		r_run_cal <= 0;	
	end
	else if(i_valid) begin
		r_run_cal <= 1;		
	end
	else begin
		r_run_cal <= r_run_cal;	
	end
end

always @ (posedge i_clk or posedge i_rst) 
begin
	if (i_rst) begin
		ro_ready <= 1;
	end
	else if (i_valid || r_run_cal) begin
		ro_ready <= 0;		
	end else begin
		ro_ready <= 1;
	end
end

//最终输出的 sin cos valid 信号
always @ (posedge i_clk or posedge i_rst) 
begin
	if (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) 
begin
	if (i_rst) begin
		ro_xmod  <= 0;
		ro_angle <= 0;
	end
	else if (r_count == i_iteration_count -1) begin
		ro_xmod  <= r_setx * K_p;
		ro_angle <= r_angle;		
	end
end

endmodule


module tb_cordic();

reg i_clk;
reg i_rst;

initial begin 
	i_clk = 0;
	i_rst = 1;
	#100
	@(posedge i_clk)
	i_rst =0;
end

always #10 i_clk = ~i_clk;

test_my_cordic_vec inst_test_my_cordic (.i_clk(i_clk), .i_rst(i_rst));

endmodule

http://www.kler.cn/a/542422.html

相关文章:

  • XZ_Mac电脑上本地化部署DeepSeek的详细步骤
  • 自学人工智能大模型,满足7B模型的训练和微调以及推理,预算3万,如何选购电脑
  • RAG 在智能答疑中的探索
  • 算法跟练第十弹——栈与队列
  • RabbitMQ 延迟队列
  • Vue3(1)
  • FAST_LIVO2初次安装编译
  • STM32 HAL库 SPI通讯(C语言)
  • 阿里云百炼初探DeepSeek模型调用
  • 【Pytorch实战教程】深入了解 PyTorch 中的 SummaryWriter
  • ES 索引结构
  • 32单片机学习记录0之前导
  • ubuntu部署postgresql+timescaladb时序数据库
  • 深度学习|表示学习|Instance Normalization 全面总结|26
  • 互联网大厂面试高频题-操作系统部分
  • Node.js开发属于自己的npm包(发布到npm官网)
  • deepseek+kimi一键生成PPT
  • 爬取豆瓣电影 Top250 数据的脚本及调整方法
  • 怎么保证设计的API是安全的
  • 车载DoIP框架 --- 怎么样给 tester 定义特定 TCP 源端口
  • DeepSeek与ChatGPT正在改写学历规则?2025教育革命深度解析
  • 接口测试Day12-持续集成、git简介和安装、Gitee远程仓库、jenkins集成
  • react项目引入tailwindcss不生效解决方案
  • 2.11-背包问题
  • flink cdc2.2.1同步postgresql表
  • k8s中Network Policy的设计原理和实现方式?