赞
踩
发布时间:2021/11/25
发布版本:2021-02
一、cordic算法原理
cordic算法主要应用于三角函数计算,尽管现在随着大规模存储器的普及,设计人员可以将所需三角函数值全部存储在存储器件上,需要用时直接读取即可,但cordic算法能直击运算函数值。
二、verilog实现,已经验证过
/*
1、计算0-90度范围内的sin,cos值
2、采用13级流水线,最小角度为0.1度
3、缩放因子为0.60725
4、计算其它象限的角度值可以移到第一象限来计算
正负号有区别
5、用这样的值计算正弦、余弦值存在一定误差,尤其是
0度,90度这类端点一定要注意
6、angle_13为0时,sin_out和cos_out除值以10000即为计算值
*/
module cordic(
//input signal
input sys_clk ,
input sys_clk_rst_n ,
input valid_in ,
input [14:0] angle , //0-90度,即0-9000(14’h2328),算上符号位
output valid_out , //output signal
output [14:0] sin_out , //0-10000,算上符号位,15bit
output [14:0]cos_out
);
//parameter
//angle 0:15’h0,90:15’h2328(16’d9000)
//MSB is symbol bit
parameter angle_step_1 = 15’h1194;//4500
parameter angle_step_2 = 15’hA61 ;//2657
parameter angle_step_3 = 15’h57B ;//1403
parameter angle_step_4 = 15’h2C9 ;//713
parameter angle_step_5 = 15’h166 ;//358
parameter angle_step_6 = 15’hB3 ;//179
parameter angle_step_7 = 15’h5A ;//90
parameter angle_step_8 = 15’h2D ;//45
parameter angle_step_9 = 15’h16 ;//22
parameter angle_step_10 = 15’hB ;//11
parameter angle_step_11 = 15’h6 ;//6
parameter angle_step_12 = 15’h3 ;//3
parameter angle_step_13 = 15’h1 ;//1
//由于迭代累加会导致x,y可能不断增大,增加1bit
parameter x0 = 16’h2710;//10000
parameter y0 = 16’h0 ;//0
//60725*0.65536 = 39796.736.由于Kn已确定且为正数,无须符号位
//parameter Kn = 16’h9b74;//0.60725
//wire
//reg
reg valid_1 ;
reg valid_2 ;
reg valid_3 ;
reg valid_4 ;
reg valid_5 ;
reg valid_6 ;
reg valid_7 ;
reg valid_8 ;
reg valid_9 ;
reg valid_10 ;
reg valid_11 ;
reg valid_12 ;
reg valid_13 ;
reg [15:0] x1 ;
reg [15:0] x2 ;
reg [15:0] x3 ;
reg [15:0] x4 ;
reg [15:0] x5 ;
reg [15:0] x6 ;
reg [15:0] x7 ;
reg [15:0] x8 ;
reg [15:0] x9 ;
reg [15:0] x10 ;
reg [15:0] x11 ;
reg [15:0] x12 ;
reg [15:0] x13 ;
reg [15:0] y1 ;
reg [15:0] y2 ;
reg [15:0] y3 ;
reg [15:0] y4 ;
reg [15:0] y5 ;
reg [15:0] y6 ;
reg [15:0] y7 ;
reg [15:0] y8 ;
reg [15:0] y9 ;
reg [15:0] y10 ;
reg [15:0] y11 ;
reg [15:0] y12 ;
reg [15:0] y13 ;
reg [13:0] angle_1 ;
reg [13:0] angle_2 ;
reg [13:0] angle_3 ;
reg [13:0] angle_4 ;
reg [13:0] angle_5 ;
reg [13:0] angle_6 ;
reg [13:0] angle_7 ;
reg [13:0] angle_8 ;
reg [13:0] angle_9 ;
reg [13:0] angle_10 ;
reg [13:0] angle_11 ;
reg [13:0] angle_12 ;
reg [13:0] angle_13 ;
//------------contrl state machine--------------------
//1step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_1 <= 1’b0 ;
x1 <= 16’h0;
y1 <= 16’h0;
angle_1 <= 14’h0;
end
else begin
valid_1 <= valid_in ;
x1 <= x0 - y0 ;
y1 <= y0 + x0 ;
angle_1 <= angle - angle_step_1;
end
end
//2step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_2 <= 1’b0 ;
x2 <= 16’h0;
y2 <= 16’h0;
angle_2 <= 14’h0;
end
else begin
if(angle_1[13] == 1’b0) begin//判断正负数
valid_2 <= valid_1 ;
x2 <= x1 - {y1[15],y1[15:1]} ;
y2 <= y1 + {x1[15],x1[15:1]} ;
angle_2 <= angle_1 - angle_step_2 ;
end else begin
valid_2 <= valid_1 ;
x2 <= x1 + {y1[15],y1[15:1]} ;
y2 <= y1 - {x1[15],x1[15:1]} ;
angle_2 <= angle_1 + angle_step_2 ;
end
end
end
//3step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_3 <= 1’b0 ;
x3 <= 16’h0;
y3 <= 16’h0;
angle_3 <= 14’h0;
end
else begin
if(angle_2[13] == 1’b0) begin
valid_3 <= valid_2 ;
x3 <= x2 - {{2{y2[15]}},y2[15:2]} ;
y3 <= y2 + {{2{x2[15]}},x2[15:2]} ;
angle_3 <= angle_2 - angle_step_3 ;
end else begin
valid_3 <= valid_2 ;
x3 <= x2 + {{2{y2[15]}},y2[15:2]} ;
y3 <= y2 - {{2{x2[15]}},x2[15:2]} ;
angle_3 <= angle_2 + angle_step_3 ;
end
end
end
//4step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_4 <= 1’b0 ;
x4 <= 16’h0;
y4 <= 16’h0;
angle_4 <= 14’h0;
end
else begin
if(angle_3[13] == 1’b0) begin
valid_4 <= valid_3 ;
x4 <= x3 - {{3{y3[15]}},y3[15:3]} ;
y4 <= y3 + {{3{x3[15]}},x3[15:3]} ;
angle_4 <= angle_3 - angle_step_4 ;
end else begin
valid_4 <= valid_3 ;
x4 <= x3 + {{3{y3[15]}},y3[15:3]} ;
y4 <= y3 - {{3{x3[15]}},x3[15:3]} ;
angle_4 <= angle_3 + angle_step_4 ;
end
end
end
//5step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_5 <= 1’b0 ;
x5 <= 16’h0;
y5 <= 16’h0;
angle_5 <= 14’h0;
end
else begin
if(angle_4[13] == 1’b0) begin
valid_5 <= valid_4 ;
x5 <= x4 - {{4{y4[15]}},y4[15:4]} ;
y5 <= y4 + {{4{x4[15]}},x4[15:4]} ;
angle_5 <= angle_4 - angle_step_5 ;
end else begin
valid_5 <= valid_4 ;
x5 <= x4 + {{4{y4[15]}},y4[15:4]} ;
y5 <= y4 - {{4{x4[15]}},x4[15:4]} ;
angle_5 <= angle_4 + angle_step_5 ;
end
end
end
//6step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_6 <= 1’b0 ;
x6 <= 16’h0;
y6 <= 16’h0;
angle_6 <= 14’h0;
end
else begin
if(angle_5[13] == 1’b0) begin
valid_6 <= valid_5 ;
x6 <= x5 - {{5{y5[15]}},y5[15:5]} ;
y6 <= y5 + {{5{x5[15]}},x5[15:5]} ;
angle_6 <= angle_5 - angle_step_6 ;
end else begin
valid_6 <= valid_5 ;
x6 <= x5 + {{5{y5[15]}},y5[15:5]} ;
y6 <= y5 - {{5{x5[15]}},x5[15:5]} ;
angle_6 <= angle_5 + angle_step_6 ;
end
end
end
//7step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_7 <= 1’b0 ;
x7 <= 16’h0;
y7 <= 16’h0;
angle_7 <= 14’h0;
end
else begin
if(angle_6[13] == 1’b0) begin
valid_7 <= valid_6 ;
x7 <= x6 - {{6{y6[15]}},y6[15:6]} ;
y7 <= y6 + {{6{x6[15]}},x6[15:6]} ;
angle_7 <= angle_6 - angle_step_7 ;
end else begin
valid_7 <= valid_6 ;
x7 <= x6 + {{6{y6[15]}},y6[15:6]} ;
y7 <= y6 - {{6{x6[15]}},x6[15:6]} ;
angle_7 <= angle_6 + angle_step_7 ;
end
end
end
//8step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_8 <= 1’b0 ;
x8 <= 16’h0;
y8 <= 16’h0;
angle_8 <= 14’h0;
end
else begin
if(angle_7[13] == 1’b0) begin
valid_8 <= valid_7 ;
x8 <= x7 - {{7{y7[15]}},y7[15:7]} ;
y8 <= y7 + {{7{x7[15]}},x7[15:7]} ;
angle_8 <= angle_7 - angle_step_8 ;
end else begin
valid_8 <= valid_7 ;
x8 <= x7 + {{7{y7[15]}},y7[15:7]} ;
y8 <= y7 - {{7{x7[15]}},x7[15:7]} ;
angle_8 <= angle_7 + angle_step_8 ;
end
end
end
//9step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_9 <= 1’b0 ;
x9 <= 16’h0;
y9 <= 16’h0;
angle_9 <= 14’h0;
end
else begin
if(angle_8[13] == 1’b0) begin
valid_9 <= valid_8 ;
x9 <= x8 - {{8{y8[15]}},y8[15:8]} ;
y9 <= y8 + {{8{x8[15]}},x8[15:8]} ;
angle_9 <= angle_8 - angle_step_9 ;
end else begin
valid_9 <= valid_8 ;
x9 <= x8 + {{8{y8[15]}},y8[15:8]} ;
y9 <= y8 - {{8{x8[15]}},x8[15:8]} ;
angle_9 <= angle_8 + angle_step_9 ;
end
end
end
//10step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_10 <= 1’b0 ;
x10 <= 16’h0;
y10 <= 16’h0;
angle_10 <= 14’h0;
end
else begin
if(angle_9[13] == 1’b0) begin
valid_10 <= valid_9 ;
x10 <= x9 - {{9{y9[15]}},y9[15:9]} ;
y10 <= y9 + {{9{x9[15]}},x9[15:9]} ;
angle_10 <= angle_9 - angle_step_10 ;
end else begin
valid_10 <= valid_9 ;
x10 <= x9 + {{9{y9[15]}},y9[15:9]} ;
y10 <= y9 - {{9{x9[15]}},x9[15:9]} ;
angle_10 <= angle_9 + angle_step_10 ;
end
end
end
//11step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_11 <= 1’b0 ;
x11 <= 16’h0;
y11 <= 16’h0;
angle_11 <= 14’h0;
end
else begin
if(angle_10[13] == 1’b0) begin
valid_11 <= valid_10 ;
x11 <= x10 - {{10{y10[15]}},y10[15:10]} ;
y11 <= y10 + {{10{x10[15]}},x10[15:10]} ;
angle_11 <= angle_10 - angle_step_11 ;
end else begin
valid_11 <= valid_10 ;
x11 <= x10 + {{10{y10[15]}},y10[15:10]} ;
y11 <= y10 - {{10{x10[15]}},x10[15:10]} ;
angle_11 <= angle_10 + angle_step_11 ;
end
end
end
//12step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_12 <= 1’b0 ;
x12 <= 16’h0;
y12 <= 16’h0;
angle_12 <= 14’h0;
end
else begin
if(angle_11[13] == 1’b0) begin
valid_12 <= valid_11 ;
x12 <= x11 - {{11{y11[15]}},y11[15:11]} ;
y12 <= y11 + {{11{x11[15]}},x11[15:11]} ;
angle_12 <= angle_11 - angle_step_12 ;
end else begin
valid_12 <= valid_11 ;
x12 <= x11 + {{11{y11[15]}},y11[15:11]} ;
y12 <= y11 - {{11{x11[15]}},x11[15:11]} ;
angle_12 <= angle_11 + angle_step_12 ;
end
end
end
//13step
always @ (posedge sys_clk)
begin
if(!sys_clk_rst_n) begin
valid_13 <= 1’b0 ;
x13 <= 16’h0;
y13 <= 16’h0;
angle_13 <= 14’h0;
end
else begin
if(angle_12[13] == 1’b0) begin
valid_13 <= valid_12 ;
x13 <= x12 - {{12{y12[15]}},y12[15:12]} ;
y13 <= y12 + {{12{x12[15]}},x12[15:12]} ;
angle_13 <= angle_12 - angle_step_13 ;
end else begin
valid_13 <= valid_12 ;
x13 <= x12 + {{12{y12[15]}},y12[15:12]} ;
y13 <= y12 - {{12{x12[15]}},x12[15:12]} ;
angle_13 <= angle_12 + angle_step_13 ;
end
end
end
multi_kn u_multi_kn(
.sys_clk (sys_clk ),
.sys_clk_rst_n (sys_clk_rst_n ),
.valid_in (valid_13 ),
.sin_in (y13 ),
.cos_in (x13 ),
.valid_out (valid_out ),
.sin_out (sin_out ),
.cos_out (cos_out )
);
endmodule
/*
1、1616乘法器
2、被乘数固定为Kn(缩放因子0.60725),Kn = 16’h9b74
// = 16’b1001_1011_0111_0100
//607250.65536 =39796.736
3、乘完后只保留15位(30-16bit),除掉2的16次方(65536)
得到真实值
*/
module multi_kn(
input sys_clk ,
input sys_clk_rst_n,
input valid_in ,
input [15:0] sin_in ,
input [15:0] cos_in ,
output valid_out ,
output [14:0] sin_out ,
output [14:0] cos_out
);
//reg
reg valid_1 ;
reg [31:0] sin_1 ;//bit2 bit4 bit5
reg [31:0] sin_2 ;//bit6 bit8 bit9
reg [31:0] sin_3 ;//bit11 bit12 bit15
reg [31:0] cos_1 ;//bit2 bit4 bit5
reg [31:0] cos_2 ;//bit6 bit8 bit9
reg [31:0] cos_3 ;//bit11 bit12 bit15
reg valid_2 ;
reg [31:0] sin_4 ;
reg [31:0] cos_4 ;
//-----------combination circuit-------------------
assign valid_out = valid_2 ;
assign sin_out = sin_4[30:16] ;
assign cos_out = cos_4[30:16] ;
//-----------control state machine------------------
//1step
//Kn = 16’h9b74
// = 16’b1001_1011_0111_0100
//sin_n = sin_inKn
//cos_n = cos_inKn
always @ (posedge sys_clk)
begin
if(~sys_clk_rst_n)
begin
valid_1 <= 1’b0 ;
sin_1 <= 32’b0;
sin_2 <= 32’b0;
sin_3 <= 32’b0;
cos_1 <= 32’b0;
cos_2 <= 32’b0;
cos_3 <= 32’b0;
end else begin
valid_1 <= valid_in;
sin_1 <= {{14{sin_in[15]}},sin_in[15:0],2’h0}
+ {{12{sin_in[15]}},sin_in[15:0],4’h0}
+ {{11{sin_in[15]}},sin_in[15:0],6’h0};
sin_2 <= {{10{sin_in[15]}},sin_in[15:0],6’h0}
+ {{8 {sin_in[15]}},sin_in[15:0],8’h0}
+ {{7 {sin_in[15]}},sin_in[15:0],9’h0};
sin_3 <= {{5 {sin_in[15]}},sin_in[15:0],11’h0}
+ {{4 {sin_in[15]}},sin_in[15:0],12’h0}
+ {{1 {sin_in[15]}},sin_in[15:0],15’h0};
cos_1 <= {{14{cos_in[15]}},cos_in[15:0],2’h0}
+ {{12{cos_in[15]}},cos_in[15:0],4’h0}
+ {{11{cos_in[15]}},cos_in[15:0],6’h0};
cos_2 <= {{10{cos_in[15]}},cos_in[15:0],6’h0}
+ {{8 {cos_in[15]}},cos_in[15:0],8’h0}
+ {{7 {cos_in[15]}},cos_in[15:0],9’h0};
cos_3 <= {{5 {cos_in[15]}},cos_in[15:0],11’h0}
+ {{4 {cos_in[15]}},cos_in[15:0],12’h0}
+ {{1 {cos_in[15]}},cos_in[15:0],15’h0};
end
end
//2step
always @ (posedge sys_clk)
begin
if(~sys_clk_rst_n) begin
valid_2 <= 1’b0 ;
sin_4 <= 32’b0;
cos_4 <= 32’b0;
end else begin
valid_2 <= valid_1 ;
sin_4 <= sin_1 + sin_2 + sin_3 ;
cos_4 <= cos_1 + cos_2 + cos_3;
end
end
endmodule
//仿真文件
module cordic_tb();
reg sys_clk ;
reg sys_clk_rst_n ;
reg valid_in ;
reg [14:0] angle ; //0-90度,即0-9000(14’h2328),算上符号位
wire valid_out ; //output signal
wire [14:0] sin_out ; //0-10000,算上符号位,15bit
wire [14:0] cos_out ;
cordic u_cordic(
.sys_clk (sys_clk ),
.sys_clk_rst_n (sys_clk_rst_n ),
.valid_in (valid_in ),
.angle (angle ),
.valid_out (valid_out ),
.sin_out (sin_out ),
.cos_out (cos_out )
);
always #10 sys_clk = ~sys_clk;
initial
begin
sys_clk = 1’b1 ;
valid_in = 1’b0 ;
angle = 16’d0 ;
sys_clk_rst_n = 1’b0 ;
#100
sys_clk_rst_n = 1’b1 ;
#20 valid_in = 1’b1 ;
angle = 15’d3000;
#20 angle = 15’d6000;
#20 angle = 15’d9000;
#20 valid_in = 1’b0 ;
angle = 15’d0 ;
#5000 $stop ;
end
endmodule
三、仿真截图
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。