Advertisement

CORDIC arithmetic

阅读量:

传统CORDIC算法code

Verilog代码:
时钟为50Mhz;
输出设置均设置为有符号数,主要是因为计算CORDIC算法时,需要判断Z通道的符号,来得到迭代过程中旋转方向。
在这里插入图片描述
然后根据缩放因子和arctan 2^-n 的预定义并乘以2^16 来进行后续计算,根据迭代方程写出代码;最后将(0度到90度)中正弦值与余弦值来扩大至(0度至360度)的正弦值与余弦值。

复制代码
    module cordic(
    	input clk_50M,
    	input rst,
    	input [31:0] angle,
    	output reg signed [31:0] sin,
    	output reg signed [31:0] cos,
    	output reg signed [31:0] error);
    `define rot0 32'd2949_120
    `define rot1 32'd1740_967
    `define rot2 32'd9198_79
    `define rot3 32'd4669_45
    `define rot4 32'd2343_78
    `define rot5 32'd1173_04
    `define rot6 32'd5866_6
    `define rot7 32'd2933_4
    `define rot8 32'd1466_8
    `define rot9 32'd7334
    `define rot10 32'd3667
    `define rot11 32'd1833
    `define rot12 32'd917
    `define rot13 32'd458
    `define rot14 32'd229
    `define rot15 32'd115
    
    parameter pipeline =16;
    parameter k=32'd39797;
    
    reg signed [31:0] x0,y0,z0;
    reg signed [31:0] x1,y1,z1;
    reg signed [31:0] x2,y2,z2;
    reg signed [31:0] x3,y3,z3;
    reg signed [31:0] x4,y4,z4;
    reg signed [31:0] x5,y5,z5;
    reg signed [31:0] x6,y6,z6;
    reg signed [31:0] x7,y7,z7;
    reg signed [31:0] x8,y8,z8;
    reg signed [31:0] x9,y9,z9;
    reg signed [31:0] x10,y10,z10;
    reg signed [31:0] x11,y11,z11;
    reg signed [31:0] x12,y12,z12;
    reg signed [31:0] x13,y13,z13;
    reg signed [31:0] x14,y14,z14;
    reg signed [31:0] x15,y15,z15;
    reg signed [31:0] x16,y16,z16;
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x0<=0;
    		y0<=0;
    		z0<=0;
    	end
    	else
    	begin
    		x0<=k;
    		y0<=0;
    		z0<=angle[15:0]<<16;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x1<=0;
    		y1<=0;
    		z1<=0;
    	end
    	else if(z0[31])
    	begin
    		x1<=x0+(y0>>0);
    		y1<=y0-(x0>>0);
    		z1<=z0+`rot0;
    	end
    	else 
    	begin
    		x1<=x0-(y0>>0);
    		y1<=y0+(x0>>0);
    		z1<=z0-`rot0;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x2<=0;
    		y2<=0;
    		z2<=0;
    	end
    	else if(z1[31])
    	begin
    		x2<=x1+(y1>>1);
    		y2<=y1-(x1>>1);
    		z2<=z1+`rot1;
    	end
    	else
    	begin
    		x2<=x1-(y1>>1);
    		y2<=y1+(x1>>1);
    		z2<=z1-`rot1;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x3<=0;
    		y3<=0;
    		z3<=0;
    	end
    	else if(z2[31])
    	begin
    		x3<=x2+(y2>>2);
    		y3<=y2-(x2>>2);
    		z3<=z2+`rot2;
    	end
    	else
    	begin
    		x3<=x2-(y2>>2);
    		y3<=y2+(x2>>2);
    		z3<=z2-`rot2;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x4<=0;
    		y4<=0;
    		z4<=0;
    	end
    	else if(z3[31])
    	begin
    		x4<=x3+(y3>>3);
    		y4<=y3-(x3>>3);
    		z4<=z3+`rot3;
    	end
    	else
    	begin
    		x4<=x3-(y3>>3);
    		y4<=y3+(x3>>3);
    		z4<=z3-`rot3;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x5<=0;
    		y5<=0;
    		z5<=0;
    	end
    	else if(z4[31])
    	begin
    		x5<=x4+(y4>>4);
    		y5<=y4-(x4>>4);
    		z5<=z4+`rot4;
    	end
    	else
    	begin
    		x5<=x4-(y4>>4);
    		y5<=y4+(x4>>4);
    		z5<=z4-`rot4;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x6<=0;
    		y6<=0;
    		z6<=0;
    	end
    	else if(z5[31])
    	begin
    		x6<=x5+(y5>>5);
    		y6<=y5-(x5>>5);
    		z6<=z5+`rot5;
    	end
    	else
    	begin
    		x6<=x5-(y5>>5);
    		y6<=y5+(x5>>5);
    		z6<=z5-`rot5;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x7<=0;
    		y7<=0;
    		z7<=0;
    	end
    	else if(z6[31])
    	begin
    		x7<=x6+(y6>>6);
    		y7<=y6-(x6>>6);
    		z7<=z6+`rot6;
    	end
    	else
    	begin
    		x7<=x6-(y6>>6);
    		y7<=y6+(x6>>6);
    		z7<=z6-`rot6;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x8<=0;
    		y8<=0;
    		z8<=0;
    	end
    	else if(z7[31])
    	begin
    		x8<=x7+(y7>>7);
    		y8<=y7-(x7>>7);
    		z8<=z7+`rot7;
    	end
    	else
    	begin
    		x8<=x7-(y7>>7);
    		y8<=y7+(x7>>7);
    		z8<=z7-`rot7;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x9<=0;
    		y9<=0;
    		z9<=0;
    	end
    	else if(z8[31])
    	begin
    		x9<=x8+(y8>>8);
    		y9<=y8-(x8>>8);
    		z9<=z8+`rot8;
    	end
    	else 
    	begin
    		x9<=x8-(y8>>8);
    		x9<=y8+(x8>>8);
    		z9<=z8-`rot8;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x10<=0;
    		y10<=0;
    		z10<=0;
    	end
    	else if(z9[31])
    	begin
    		x10<=x9+(y9>>9);
    		y10<=y9-(x9>>9);
    		z10<=z9+`rot9;
    	end
    	else
    	begin
    		x10<=x9-(y9>>9);
    		y10<=y9+(x9>>9);
    		z10<=z9-`rot9;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x11<=0;
    		y11<=0;
    		z11<=0;
    	end
    	else if(z10[31])
    	begin
    		x11<=x10+(y10>>10);
    		y11<=y10-(x10>>10);
    		z11<=z10+`rot10;
    	end
    	else
    	begin
    		x11<=x10-(y10>>10);
    		y11<=y10+(x10>>10);
    		z11<=z10-`rot10;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x12<=0;
    		y12<=0;
    		z12<=0;
    	end
    	else if(z11[31])
    	begin
    		x12<=x11+(y11>>11);
    		y12<=y11-(x11>>11);
    		z12<=z11+`rot11;
    	end
    	else
    	begin
    		x12<=x11-(y11>>11);
    		y12<=y11+(x11>>11);
    		z12<=z11-`rot11;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x13<=0;
    		y13<=0;
    		z13<=0;
    	end
    	else if(z12[31])
    	begin
    		x13<=x12+(y12>>12);
    		y13<=y12-(x12>>12);
    		z13<=z12+`rot12;
    	end
    	else
    	begin
    		x13<=x12-(y12>>12);
    		y13<=y12+(x12>>12);
    		z13<=z12-`rot12;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x14<=0;
    		y14<=0;
    		z14<=0;
    	end
    	else if(z13[31])
    	begin
    		x14<=x13+(y13>>13);
    		y14<=y13-(x13>>13);
    		z14<=z13+`rot13;
    	end
    	else
    	begin
    		x14<=x13-(y13>>13);
    		y14<=y13+(x13>>13);
    		z14<=z13-`rot13;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x15<=0;
    		y15<=0;
    		z15<=0;
    	end
    	else if(z14[31])
    	begin
    		x15<=x14+(y14>>14);
    		y15<=y14-(x14>>14);
    		z15<=z14+`rot14;
    	end
    	else
    	begin
    		x15<=x14-(y14>>14);
    		y15<=y14+(x14>>14);
    		z15<=z14-`rot14;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		x16<=0;
    		y16<=0;
    		z16<=0;
    	end
    	else if(z15[31])
    	begin
    		x16<=x15+(y15>>15);
    		y16<=y15-(x15>>15);
    		z16<=z15+`rot15;
    	end
    	else
    	begin
    		x16<=x15-(y15>>15);
    		y16<=y15+(x15>>15);
    		z16<=z15-`rot15;
    	end
    end
    
    always@(posedge clk_50M or negedge rst)
    begin
    	if(!rst)
    	begin
    		sin<=0;
    		cos<=0;
    		error<=0;
    	end
    	else if(0<=angle<=31'd90)
    	begin
    		sin<=y16;
    		cos<=x16;
    	end
    	else if(31'd90<=angle<=31'd180)
    	begin
    		cos<=~(y16)+1;
    		sin<=x16;
    	end
    	else if(31'd180<=angle<=31'd270)
    	begin
    		cos<=~(x16)+1;
    		sin<=~(y16)+1;
    	end
    	else if(31'd270<=angle<=31'd360)
    	begin
    		cos<=y16;
    		sin<=~x16+1;
    	end
    	else
    	begin
    		sin<=0;
    		cos<=0;
    		error<=0;
    	end
    end
    endmodule
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-17/7efiSrC4QpF29scyLzdItP1oDnEa.png)

编写的tb文件如下:

复制代码
    module tb();
    reg clk_50M;
    reg rst;
    reg [31:0] angle;
    wire [31:0] sin;
    wire [31:0] cos;
    wire [31:0] error;
    
    parameter period=20;
    
    initial
    begin
    clk_50M=0;
    forever #(period/2) clk_50M=~clk_50M;
    end
    
    task rst_n;
    	input [31:0] rst_time;
    	begin
    		rst=0;
    		#(rst_time) rst=1;
    	end
    endtask
    
    
    
    initial
    begin
    	rst_n(60);
    	angle=31'd46;
    end 
    
    cordic u1(
    	.clk_50M(clk_50M),
    	.rst(rst),
    	.angle(angle),
    	.sin(sin),
    	.cos(cos),
    	.error(error));
    
    endmodule
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-17/v7DVeYJj9zlE1QnBi48Z0AXSsr2G.png)

最终使用VCS 检查输入角度为46度时,输出的结果是否正确;将结果除以2^16可以得出最终结果,由于sin46=0.7193398 而仿真结果为0.7193909
而cos46=0.69465839,而仿真结果为0.694641113;误差率大于在10^-5
在这里插入图片描述

全部评论 (0)

还没有任何评论哟~