编写自己的CORDIC IP CORE

来源:互联网 发布:安装win7无法连接网络 编辑:程序博客网 时间:2024/06/06 01:26

如有疑问,请留言

本文只是提供一个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°

相当精确,误差分析略过,感兴趣可以参考相关资料,比如上面那本书



0 0
原创粉丝点击