如有疑问,请留言
本文只是提供一个ROTATION程序,各项参数请参考注释,经验证程序完全正确,实现了目标功能。
如需引用,细节还需斟酌,这里只是提供一种参考方法
1、开发软件:Quartus II 14.1 ,Modelsim 10.4
2、参考资料:Xinlinx FPGA数字信号处理权威指南 何宾,张艳辉 著
3、源代码:
/**********************************************************************/
//date: 2016.9.12
//engineer: Wang Dongwei
//project: cordic
//version: v1.0
/*
descriptions: anti-clockwise rotate
full circle
function: rotate
architectural: word serial
pipelining mode: none
data format: signed fraction
phase format: radians
input width: 16
output width: 16
round mode: truncate
iteration: 0
precision: 0
coarse rotation: yes
compensation scaling: lut
*/
/***********************************************************************/
module cordic(
input clk,
input rst_n,
input signed [15:0]x_in,
input signed [15:0]y_in,
input nd,
input [15:0]phase_in,
output reg signed [15:0]x_out,
output reg signed [15:0]y_out,
output reg rdy
);
reg signed [15:0]x;
reg signed [15:0]y;
reg signed [15:0]z;
reg signed [1:0]d;
reg [3:0] i;
reg signed [15:0] theta[10:0];
always@(posedge clk)
begin
theta[0] <= 16'd0;
theta[1] <= 16'd7854; //45/180*pi = 0.7854
theta[2] <= 16'd4634; //26.55505/180*pi = 0.4634
theta[3] <= 16'd2450; //14.03624/180*pi = 0.2450
theta[4] <= 16'd1244; //7.12502/180*pi = 0.1244
theta[5] <= 16'd624; //3.57633/180*pi = 0.0624
theta[6] <= 16'd312; //1.78991/180*pi = 0.0312
theta[7] <= 16'd156; //0.89517/180*pi = 0.0156
theta[8] <= 16'd78; //0.44761/180*pi = 0.0078
theta[9] <= 16'd39; //0.22381/180*pi = 0.0039
theta[10]<= 16'd19; //0.11191/180*pi = 0.0019
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
i <= 4'd0;
else if(nd)
i <= 4'd1;
else if(i == 4'd11)
i <= 4'd0;
else if(4'd0 < i < 4'd11)
i <= i + 1'b1;
else
i <= 4'd0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
x <= 16'd0;
y <= 16'd0;
z <= 16'd0;
d <= 2'd0;
x_out <= 16'd0;
y_out <= 16'd0;
end
else begin
case(i)
4'd0:begin
x <= 16'd0;
y <= 16'd0;
z <= 16'd0;
d <= 2'd0;
rdy <= 1'b0;
end
4'd1:begin
x <= x_in;
y <= y_in;
z <= phase_in;
d <= 1;
rdy <= 1'b0;
end
4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd8,4'd9,4'd10:begin
x <= x - d*(y>>(i-2));
y <= y + d*(x>>(i-2));
z <= z - d*theta[i-1];
rdy<= 1'b0;
if((z - d*theta[i-1])>= 0)
d <= 2'd1;
else
d <= -2'd1;
end
4'd11:begin
x_out <= x - d*(y>>9);
y_out <= y + d*(x>>9);
z <= z - d*theta[i-1];
rdy <= 1'b1;
end
endcase
end
end
endmodule
4、testbench
`timescale 1 ps/ 1 ps
module cordic_vlg_tst();
reg eachvec;
reg clk;
reg nd;
reg [15:0] phase_in;
reg rst_n;
reg [15:0] x_in;
reg [15:0] y_in;
// wires
wire rdy;
wire [15:0] x_out;
wire [15:0] y_out;
cordic i1 (
.clk(clk),
.nd(nd),
.phase_in(phase_in),
.rdy(rdy),
.rst_n(rst_n),
.x_in(x_in),
.x_out(x_out),
.y_in(y_in),
.y_out(y_out)
);
initial
begin
clk = 0;
rst_n = 0;
phase_in = 16'd0;
x_in = 16'd0;
y_in = 16'd0;
nd = 0;
#100 rst_n = 1;
x_in = 16'b0010_0000_0000_0000;
y_in = 16'd0;
phase_in = 16'd4014;
nd = 1;
#20 nd = 0;
$display("Running testbench");
end
always #10 clk = ~clk;
endmodule
5、测试结果
phase_in = 23/180*pi = 0.4014
输出为22.9995°
误差:0.0005°
相当精确,误差分析略过,感兴趣可以参考相关资料,比如上面那本书