迭代16次的CORDIC算法-verilog实现 -32位迭代16次verilog代码实现
CORDIC.v
module cordic32#(
parameter DATA_WIDTH = 8'd32 , // we set data width
parameter PIPELINE = 5'd16 // Optimize waveform
)(
input clk ,
input rst_n ,
input signed [DATA_WIDTH - 1 : 0] phase ,
input ena ,
output reg signed [DATA_WIDTH - 1 : 0] sin_out ,
output reg signed [DATA_WIDTH - 1 : 0] cos_out
);
// ----------------------------------------------- \\
// next is define and parameter \\
// ------------------------------------------------- \\
reg signed [DATA_WIDTH - 1 : 0] phase_reg ;
reg signed [DATA_WIDTH - 1 : 0] phase_reg1 ;
reg signed [DATA_WIDTH - 1 : 0] X0 ;
reg signed [DATA_WIDTH - 1 : 0] Y0 ;
reg signed [DATA_WIDTH - 1 : 0] Z0 ;
wire signed [DATA_WIDTH - 1 : 0] X1 , Y1 , Z1 ;
wire signed [DATA_WIDTH - 1 : 0] X2 , Y2 , Z2 ;
wire signed [DATA_WIDTH - 1 : 0] X3 , Y3 , Z3 ;
wire signed [DATA_WIDTH - 1 : 0] X4 , Y4 , Z4 ;
wire signed [DATA_WIDTH - 1 : 0] X5 , Y5 , Z5 ;
wire signed [DATA_WIDTH - 1 : 0] X6 , Y6 , Z6 ;
wire signed [DATA_WIDTH - 1 : 0] X7 , Y7 , Z7 ;
wire signed [DATA_WIDTH - 1 : 0] X8 , Y8 , Z8 ;
wire signed [DATA_WIDTH - 1 : 0] X9 , Y9 , Z9 ;
wire signed [DATA_WIDTH - 1 : 0] X10 , Y10 , Z10 ;
wire signed [DATA_WIDTH - 1 : 0] X11 , Y11 , Z11 ;
wire signed [DATA_WIDTH - 1 : 0] X12 , Y12 , Z12 ;
wire signed [DATA_WIDTH - 1 : 0] X13 , Y13 , Z13 ;
wire signed [DATA_WIDTH - 1 : 0] X14 , Y14 , Z14 ;
wire signed [DATA_WIDTH - 1 : 0] X15 , Y15 , Z15 ;
wire signed [DATA_WIDTH - 1 : 0] X16 , Y16 , Z16 ;
reg signed [DATA_WIDTH - 1 : 0] XN15 , YN15 ;
reg [1:0] quadrant[PIPELINE : 0] ;
integer i ;
// We will convert all new angles to the first quadrant
//
always@(posedge clk or negedge rst_n)
begin
if( rst_n == 0 )
begin
phase_reg <= 0 ;
phase_reg1 <= 0 ;
end
else if( ena == 1)
begin
phase_reg1 <= phase ;
case(phase[DATA_WIDTH - 1 : DATA_WIDTH - 2])
2'b00 :
phase_reg <= phase ;
2'b01 :
phase_reg <= phase - 32'h40000000 ; // -90
2'b10 :
phase_reg <= phase - 32'h80000000 ; // -180
2'b11 :
phase_reg <= phase - 32'hC0000000 ; // -270
default :
phase_reg <= 32'h00 ;
endcase
end
end
// We begin the initialization operation
// we set 0.607253*???2^31-1???,32'h4DBA775F
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0 )
begin
X0 <= 0 ;
Y0 <= 0 ;
Z0 <= 0 ;
end
else if(ena == 1)
begin
X0 <= 32'h4DBA775F ;
Y0 <= 0 ;
Z0 <= phase_reg ;
end
end
// for instantiation - 16
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd0 ),
.ANGLE ( 32'h20000000 )
)u_INTERATION0(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X0 ),
.Y0 ( Y0 ),
.Z0 ( Z0 ),
.X1 ( X1 ),
.Y1 ( Y1 ),
.Z1 ( Z1 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd1 ),
.ANGLE ( 32'h12E4051D )
)u_INTERATION1(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X1 ),
.Y0 ( Y1 ),
.Z0 ( Z1 ),
.X1 ( X2 ),
.Y1 ( Y2 ),
.Z1 ( Z2 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd2 ),
.ANGLE ( 32'h09FB385B )
)u_INTERATION2(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X2 ),
.Y0 ( Y2 ),
.Z0 ( Z2 ),
.X1 ( X3 ),
.Y1 ( Y3 ),
.Z1 ( Z3 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd3 ),
.ANGLE ( 32'h051111D4 )
)u_INTERATION3(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X3 ),
.Y0 ( Y3 ),
.Z0 ( Z3 ),
.X1 ( X4 ),
.Y1 ( Y4 ),
.Z1 ( Z4 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd4 ),
.ANGLE ( 32'h028B0D43 )
)u_INTERATION4(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X4 ),
.Y0 ( Y4 ),
.Z0 ( Z4 ),
.X1 ( X5 ),
.Y1 ( Y5 ),
.Z1 ( Z5 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd5 ),
.ANGLE ( 32'h0145D7E1 )
)u_INTERATION5(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X5 ),
.Y0 ( Y5 ),
.Z0 ( Z5 ),
.X1 ( X6 ),
.Y1 ( Y6 ),
.Z1 ( Z6 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd6 ),
.ANGLE ( 32'h00A2F61E )
)u_INTERATION6(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X6 ),
.Y0 ( Y6 ),
.Z0 ( Z6 ),
.X1 ( X7 ),
.Y1 ( Y7 ),
.Z1 ( Z7 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd7 ),
.ANGLE ( 32'h00517C55 )
)u_INTERATION7(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X7 ),
.Y0 ( Y7 ),
.Z0 ( Z7 ),
.X1 ( X8 ),
.Y1 ( Y8 ),
.Z1 ( Z8 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd8 ),
.ANGLE ( 32'h0028BE53 )
)u_INTERATION8(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X8 ),
.Y0 ( Y8 ),
.Z0 ( Z8 ),
.X1 ( X9 ),
.Y1 ( Y9 ),
.Z1 ( Z9 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd9 ),
.ANGLE ( 32'h00145F2F )
)u_INTERATION9(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X9 ),
.Y0 ( Y9 ),
.Z0 ( Z9 ),
.X1 ( X10 ),
.Y1 ( Y10 ),
.Z1 ( Z10 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd10 ),
.ANGLE ( 32'h000A2F98 )
)u_INTERATION10(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X10 ),
.Y0 ( Y10 ),
.Z0 ( Z10 ),
.X1 ( X11 ),
.Y1 ( Y11 ),
.Z1 ( Z11 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd11 ),
.ANGLE ( 32'h000517CC )
)u_INTERATION11(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X11 ),
.Y0 ( Y11 ),
.Z0 ( Z11 ),
.X1 ( X12 ),
.Y1 ( Y12 ),
.Z1 ( Z12 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd12 ),
.ANGLE ( 32'h00028BE6 )
)u_INTERATION12(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X12 ),
.Y0 ( Y12 ),
.Z0 ( Z12 ),
.X1 ( X13 ),
.Y1 ( Y13 ),
.Z1 ( Z13 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd13 ),
.ANGLE ( 32'h000145F3 )
)u_INTERATION13(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X13 ),
.Y0 ( Y13 ),
.Z0 ( Z13 ),
.X1 ( X14 ),
.Y1 ( Y14 ),
.Z1 ( Z14 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd14 ),
.ANGLE ( 32'h0000A2FA )
)u_INTERATION14(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X14 ),
.Y0 ( Y14 ),
.Z0 ( Z14 ),
.X1 ( X15 ),
.Y1 ( Y15 ),
.Z1 ( Z15 )
);
INTERATION#(
.DATA_WIDTH ( 8'd32 ),
.shift ( 5'd15 ),
.ANGLE ( 32'h0000517D )
)u_INTERATION15(
.clk ( clk ),
.rst_n ( rst_n ),
.ena ( ena ),
.X0 ( X15 ),
.Y0 ( Y15 ),
.Z0 ( Z15 ),
.X1 ( X16 ),
.Y1 ( Y16 ),
.Z1 ( Z16 )
);
// iteration over
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0)
for(i = 0 ; i < PIPELINE ; i=i+1)
quadrant[i] <= 0 ;
else
if(ena == 1)
begin
for(i = 0 ; i < PIPELINE ; i=i+1)
quadrant[i+1] <= quadrant[i] ;
quadrant[0] <= phase_reg1[DATA_WIDTH - 1 : DATA_WIDTH - 2] ;
end
end
//------------------------------------------ \\
//------------------------------------------ \\
// Prevent overflow caused by small decimals and negative complement
//
always @(posedge clk or negedge rst_n)
if(rst_n == 0)
XN15<=0;
else if(X15[31:30] == 2'b11)//小于0
XN15<=~X15 + 1'b1;
else if(X15[31:30] == 2'b10)//大于1
XN15<=32'h80000000 - X15 + 32'h80000000;
else
XN15 <= X15;
always @(posedge clk or negedge rst_n )
if(rst_n == 0)
YN15 <=0;
else if(Y15[31:30] == 2'b11)//小于0
YN15 <=~Y15 + 1'b1;
else if(Y15[31:30] == 2'b10)//大于1
YN15 <=32'h80000000 -Y15 + 32'h80000000;
else
YN15 <=Y15;
//
// The results of different phases are also different
// phase[DATA_WIDTH -1 : DATA_WIDTH -2]
// 00 first quadrant
// 01 second quadrant
// 10 third quadrant
// 11 Fourth Quadrant
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0)
begin
cos_out <= 0 ;
sin_out <= 0 ;
end
else if( ena == 1)
begin
case(quadrant[16])
2'b00 :
begin
cos_out <= XN15 ;
sin_out <= YN15 ;
end
2'b01 :
begin
cos_out <= ~YN15 + 1'b1;
sin_out <= XN15 ;
end
2'b10 :
begin
cos_out <= ~XN15 + 1'b1 ;
sin_out <= ~YN15 + 1'b1 ;
end
2'b11 :
begin
cos_out <= YN15 ;
sin_out <= ~XN15 + 1'b1 ;
end
endcase
end
end
endmodule
ITERATION.v
module INTERATION #(
parameter DATA_WIDTH = 8'd32 ,
parameter shift = 5'd0 ,
parameter ANGLE = 32'h20000000
)(
input clk ,
input rst_n ,
input ena ,
input signed [DATA_WIDTH - 1 : 0] X0 ,
input signed [DATA_WIDTH - 1 : 0] Y0 ,
input signed [DATA_WIDTH - 1 : 0] Z0 ,
output reg signed [DATA_WIDTH - 1 : 0] X1 ,
output reg signed [DATA_WIDTH - 1 : 0] Y1 ,
output reg signed [DATA_WIDTH - 1 : 0] Z1
);
always@(posedge clk or negedge rst_n)
begin
if( rst_n == 0)
begin
X1 <= 0 ;
Y1 <= 0 ;
Z1 <= 0 ;
end
else if( ena == 1)
begin
if(Z0[DATA_WIDTH - 1] == 0 )
begin
// X1 <= X0 - {{shift{ Y0[DATA_WIDTH - 1] }} ,Y0[DATA_WIDTH - 1 : shift] } ;
// Y1 <= Y0 + {{shift{ X0[DATA_WIDTH - 1] }} ,X0[DATA_WIDTH - 1 : shift] } ;
X1 <= X0 - (Y0>>>shift);
Y1 <= Y0 + (X0>>>shift);
Z1 <= Z0 - ANGLE ;
end
else if(Z0[DATA_WIDTH - 1] == 1 )
begin
//X1 <= X0 + {{shift{ Y0[DATA_WIDTH - 1 ] }} ,Y0[DATA_WIDTH - 1 : shift] } ;
// Y1 <= Y0 - {{shift{ X0[DATA_WIDTH - 1 ] }} ,X0[DATA_WIDTH - 1 : shift] } ;
X1 <= X0 + (Y0>>>shift) ;
Y1 <= Y0 - {X0>>>shift} ;
Z1 <= Z0 + ANGLE ;
end
end
end
endmodule
CORDIC_tb.v
module cordic_tb #(
parameter DATA_WIDTH = 8'd32 , // we set data width
parameter PIPELINE = 5'd16 // Optimize waveform
);
reg clk ;
reg rst_n ;
reg [DATA_WIDTH - 1 : 0] phase ;
reg ena ;
wire [DATA_WIDTH - 1 : 0] sin_out ;
wire [DATA_WIDTH - 1 : 0] cos_out ;
integer i;
cordic32#(
.DATA_WIDTH ( DATA_WIDTH ),
.PIPELINE ( PIPELINE )
)u_cordic32(
.clk ( clk ),
.rst_n ( rst_n ),
.phase ( phase ),
.ena ( ena ),
.sin_out ( sin_out ),
.cos_out ( cos_out )
);
initial
begin
#0 clk = 1'b0;
ena = 1'b1 ;
#10 rst_n = 1'b0;
#10 rst_n = 1'b1;
#20000000 $stop;
end
initial
begin
repeat(10)
begin
#0 phase = 32'd0;
for(i=0;i<131072;i=i+1)
begin
#10;
phase <= phase + 32'h8000;
end
end
end
always #10
begin
clk = ~clk;
end
endmodule
README.md
在完成CORDIC的7次迭代之后 我在思考一个问题 8位进行了7次迭代 最后迭代至0号称没有误差了
我们是否可以通过 扩展至32位 进行多次迭代 将误差不断的缩小
本次数据参考至 网上的其他教程 我并没有自己去计算 我把结构优化一下 修改成更加便于理解使用的形式
还有一件事 是 进制 与 Π 转化的问题
对于 8位 其实我们 一开始将Π 设定为 1000_0000
那么对于 Π/4 是否就是1000_0000 的 四分之一 对于二进制 其实就是整体的数字进行移位
我们将1000_0000 移动至 0010_0000 于此
而对于 32位我们32'h8000000 就是一个Π
而 32’h2000_0000 就是四分之Π
还有一件事 说明 我在写例化的时候 将数据完全完整的例化了下来 写的很长 这样并不是很好
后面学习中 我看别人是 这么处理的
genvar die;
generate
for (die = 0; die <Pipeline; die=die+1)
begin: dieLoop
always @(posedge CLK_SYS or negedge RST_N)
if (!RST_N) begin
xn[die+1] <= 32'h0;
yn[die+1] <= 32'h0;
zn[die+1] <= 32'h0;
end
else begin
if(zn[die][31]==1'b0)//角度符号判断
begin
xn[die+1] <= xn[die] - (yn[die]>>>die);
yn[die+1] <= yn[die] + (xn[die]>>>die);
zn[die+1] <= zn[die] - rot[die];
end
else begin
xn[die+1] <= xn[die] + (yn[die]>>>die);
yn[die+1] <= yn[die] - (xn[die]>>>die);
zn[die+1] <= zn[die] + rot[die];
end
end
end
endgenerate
# 还有一件事 对于溢出的考量
我们所作溢出的考量 其实我们设定了32'h8000_0000 这既是Π的值 也是 1的设定
但是在实际的运用和计算中 我们其实永远也达不到1 嘿嘿
因为我们把最高位设计成了 符号位
那么最大 也就是1 我们约等于 32'h7fff_ffff
这里需要注意的是[31:28] 是 7 也就是0111 非常重要的一个结论 我们最高位0代表了符号位
那么对于设计到第一象限的[31:30] 的值可以取 00 01 但是 10 11我们要对其进行合适的转化
所以便有了我们 对溢出的操作
always @(posedge clk or negedge rst_n)
if(rst_n == 0)
XN15<=0;
else if(X15[31:30] == 2'b11)//小于0
XN15<=~X15 + 1'b1;
else if(X15[31:30] == 2'b10)//大于1
XN15<=32'h80000000 - X15 + 32'h80000000;
else
XN15 <= X15;
always @(posedge clk or negedge rst_n )
if(rst_n == 0)
YN15 <=0;
else if(Y15[31:30] == 2'b11)//小于0
YN15 <=~Y15 + 1'b1;
else if(Y15[31:30] == 2'b10)//大于1
YN15 <=32'h80000000 -Y15 + 32'h80000000;
else
YN15 <=Y15;
注意在设计的时候 定义成reg signed 的形式 将其设计为有符号位