二、CORDIC算法的FPGA实现
在采用FPGA实现CORDIC算法时,需要考虑两个方面的因素:速度和面积。以这两个因素作为出发点的有3种硬件架构:紧缩结构(Rolled)、展开结构(Unrolled)和展开流水结构(Unrolled Pipelined)。其中紧缩结构的占用的资源最少,因为对CORDIC处理单元的循环复用,也正因此使得控制单元设计略显复杂,时序控制较为繁琐,系统处理速度较低。展开结构式对紧缩结构的扩展,对每次迭代赋予了独立的CORDIc处理单元,从而不需要控制电路,只需要移位和加减操作。这是与紧缩结构中COrDIC处理单元最大的不同。显然,相较于紧缩结构,展开结构消耗的资源显著增加。为了提高系统处理的速度,对展开结构加流水寄存器,即为展开流水结构。它有效地缩短了关键路径,使得关键路径的长度由展开结构的N个CORDIC处理单元变为1个CORDIC处理单元。因此,展开流水结构具有最高的处理速度,而这时以消耗更多的资源换取的。
流水线CORDIC结构虽然占用的硬件资源比其他结构稍多,但是流水线结构可以提高数据的吞吐率,对于大多数的数字信号处理算法来说,存在很多同一指令连续处理很长一段数据的情况,此时高吞吐率更有意义。从当前FPGA的发展趋势来看,芯片内的门资源相对富裕,对流水线CORDIC的实现规模约束很小,此外,流水线CORDIC不存在迭代式CORDIC的反馈回路,使得单元结构更加规则,有利于FPGA实现。所以使用流水结构来实现CORDIC算法,如图1所示。
图2中的sgn(yi)和sgn(zi)分别表示yi和zi的符号位即最高位,根据工作模式(旋转模式还是向量模式),选择其中之一赋给di(这里为1或0)。加法器根据di确定工作模式(加法操作还是减法操作)。">>i"表示对输入数据右移i位,i由control模块控制。ROM中存放的数据为每次迭代时的旋转角度arctan(1/2^i)可以是角度表示也可以是弧度表示,统一即可。
展开结构的具体细节如图2所示。该结构非常清晰。每次迭代有独立的处理单元,在图2中,Ci为第i次的旋转角。显然,此结构所用资源与迭代次数有直接的关系。
图2 展开结构的具体细节u
展开结构中的每个CORDIC处理单元有相同的架构--移位加减蝶形单元,它由加法器和移位模块共同组成。加法器根据sgn确定工作模式。
二、Verilog硬件描述
2.1 圆坐标系下的向量模式
这种方法相当于是把矩形坐标系下坐标(x,y)变换到极坐标系下的(r,
θ),其中r,
θ分量可以根据以下公式逐次迭代得到:
经过n次迭代后得到以下公式:
那么xn/kn就是要求向量(x,y)的模r,zn就是向量(x,y)的夹角θ(当z0=0的条件下)
代码如下:
module cordic(clk,rst,x_in,y_in,r_out,phase_out);
parameter WIDTH=16;
input clk,rst;
input [WIDTH-1:0] x_in,y_in;
output reg [WIDTH-1:0] r_out,phase_out; //输入输出端口申明
reg [WIDTH-1:0] x0,y0,z0; //输入数据寄存器
reg [WIDTH-1:0] x1,y1,z1;
reg [WIDTH-1:0] x2,y2,z2;
reg [WIDTH-1:0] x3,y3,z3;
reg [WIDTH-1:0] x4,y4,z4;
reg [WIDTH-1:0] x5,y5,z5;
reg [WIDTH-1:0] x6,y6,z6;
reg [WIDTH-1:0] x7,y7,z7;
reg [WIDTH-1:0] x8,y8,z8;
reg [WIDTH-1:0] x9,y9,z9;
reg [WIDTH-1:0] x10,y10,z10;
reg [WIDTH-1:0] x11,y11,z11;
reg [WIDTH-1:0] x12,y12,z12;
reg [WIDTH-1:0] x13,y13,z13;
reg [WIDTH-1:0] x14,y14,z14;
reg [WIDTH-1:0] x15,y15,z15; //15级流水寄存器
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x0<=16'h0;
y0<=0;
z0<=0;
end
else if(x_in[15]==1'b0) begin //目标角度初处理,因为目标角度旋转范围[-99.9,99.9]
x0<=x_in;
y0<=y_in;
z0<=16'h0;
end //若(x,y)在第一、四象限,那么预旋转0度
else if(y_in[15]==0) begin
x0<=y_in;
y0<=-x_in;
z0<=16'h4000;
end //若(x,y)在第二象限,那么预旋转90度
else begin
x0<=-y_in;
y0<=x_in;
z0<=-16'h4000;
end //若(x,y)在第三象限,那么预旋转-90度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x1<=0;
y1<=0;
z1<=0;
end
else if(y0[15]==1) begin
x1<=x0-y0;
y1<=y0+x0;
z1<=z0-16'h2000;
end
else begin
x1<=x0+y0;
y1<=y0-x0;
z1<=z0+16'h2000;
end //第一次迭代,旋转45度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x2<=0;
y2<=0;
z2<=0;
end
else if(y1[15]==1) begin
x2<=x1-{y1[15],y1[15:1]};
y2<=y1+{x1[15],x1[15:1]};
z2<=z1-16'h12E4;
end
else begin
x2<=x1+{y1[15],y1[15:1]};
y2<=y1-{x1[15],x1[15:1]};
z2<=z1+16'h12E4;
end //第二次迭代,旋转26.565度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x3<=0;
y3<=0;
z3<=0;
end
else if(y2[15]==1) begin
x3<=x2-{{2{y2[15]}},y2[15:2]};
y3<=y2+{{2{x2[15]}},x2[15:2]};
z3<=z2-16'h09FB;
end
else begin
x3<=x2+{{2{y2[15]}},y2[15:2]};
y3<=y2-{{2{x2[15]}},x2[15:2]};
z3<=z2+16'h09FB;
end //第三次迭代,旋转14.036度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x4<=0;
y4<=0;
z4<=0;
end
else if(y3[15]==1) begin
x4<=x3-{{3{y3[15]}},y3[15:3]};
y4<=y3+{{3{x3[15]}},x3[15:3]};
z4<=z3-16'h0511;
end
else begin
x4<=x3+{{3{y3[15]}},y3[15:3]};
y4<=y3-{{3{x3[15]}},x3[15:3]};
z4<=z3+16'h0511;
end //第四次迭代,旋转7.125度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x5<=0;
y5<=0;
z5<=0;
end
else if(y4[15]==1) begin
x5<=x4-{{4{y4[15]}},y4[15:4]};
y5<=y4+{{4{x4[15]}},x4[15:4]};
z5<=z4-16'h028B;
end
else begin
x5<=x4+{{4{y4[15]}},y4[15:4]};
y5<=y4-{{4{x4[15]}},x4[15:4]};
z5<=z4+16'h028B;
end //第五次迭代,旋转3.5763度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x6<=0;
y6<=0;
z6<=0;
end
else if(y5[15]==1) begin
x6<=x5-{{5{y5[15]}},y5[15:5]};
y6<=y5+{{5{x5[15]}},x5[15:5]};
z6<=z5-16'h0145;
end
else begin
x6<=x5+{{5{y5[15]}},y5[15:5]};
y6<=y5-{{5{x5[15]}},x5[15:5]};
z6<=z5+16'h0145;
end //第六次迭代,旋转1.7899度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x7<=0;
y7<=0;
z7<=0;
end
else if(y6[15]==1) begin
x7<=x6-{{6{y6[15]}},y6[15:6]};
y7<=y6+{{6{x6[15]}},x6[15:6]};
z7<=z6-16'h00A2;
end
else begin
x7<=x6+{{6{y6[15]}},y6[15:6]};
y7<=y6-{{6{x6[15]}},x6[15:6]};
z7<=z6+16'h00A2;
end //第七次迭代,旋转0.8952度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x8<=0;
y8<=0;
z8<=0;
end
else if(y7[15]==1) begin
x8<=x7-{{7{y7[15]}},y7[15:7]};
y8<=y7+{{7{x7[15]}},x7[15:7]};
z8<=z7-16'h0051;
end
else begin
x8<=x7+{{7{y7[15]}},y7[15:7]};
y8<=y7-{{7{x7[15]}},x7[15:7]};
z8<=z7+16'h0051;
end //第八次迭代,旋转0.4476度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x9<=0;
y9<=0;
z9<=0;
end
else if(y8[15]==1) begin
x9<=x8-{{8{y8[15]}},y8[15:8]};
y9<=y8+{{8{x8[15]}},x8[15:8]};
z9<=z8-16'h0028;
end
else begin
x9<=x8+{{8{y8[15]}},y8[15:8]};
y9<=y8-{{8{x8[15]}},x8[15:8]};
z9<=z8+16'h0028;
end //第九次迭代,旋转0.2238度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x10<=0;
y10<=0;
z10<=0;
end
else if(y9[15]==1) begin
x10<=x9-{{9{y9[15]}},y9[15:9]};
y10<=y9+{{9{x9[15]}},x9[15:9]};
z10<=z9-16'h0014;
end
else begin
x10<=x9+{{9{y9[15]}},y9[15:9]};
y10<=y9-{{9{x9[15]}},x9[15:9]};
z10<=z9+16'h0014;
end //第十次迭代,旋转0.1119度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x11<=0;
y11<=0;
z11<=0;
end
else if(y10[15]==1) begin
x11<=x10-{{10{y10[15]}},y10[15:10]};
y11<=y10+{{10{x10[15]}},x10[15:10]};
z11<=z10-16'h000C;
end
else begin
x11<=x10+{{10{y10[15]}},y10[15:10]};
y11<=y10-{{10{x10[15]}},x10[15:10]};
z11<=z10+16'h000C;
end //第十一次迭代,旋转0.05595度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x12<=0;
y12<=0;
z12<=0;
end
else if(y11[15]==1) begin
x12<=x11-{{11{y11[15]}},y11[15:11]};
y12<=y11+{{11{x11[15]}},x11[15:11]};
z12<=z11-16'h0005;
end
else begin
x12<=x11+{{11{y11[15]}},y11[15:11]};
y12<=y11-{{11{x11[15]}},x11[15:11]};
z12<=z11+16'h0005;
end //第十二次迭代,旋转0.02798度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x13<=0;
y13<=0;
z13<=0;
end
else if(y12[15]==1) begin
x13<=x12-{{12{y12[15]}},y12[15:12]};
y13<=y12+{{12{x12[15]}},x12[15:12]};
z13<=z12-16'h0002;
end
else begin
x13<=x12+{{12{y12[15]}},y12[15:12]};
y13<=y12-{{12{x12[15]}},x12[15:12]};
z13<=z12+16'h0002;
end //第十三次迭代,旋转0.01399度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x14<=0;
y14<=0;
z14<=0;
end
else if(y13[15]==1) begin
x14<=x13-{{13{y13[15]}},y13[15:13]};
y14<=y13+{{13{x13[15]}},x13[15:13]};
z14<=z13-16'h0001;
end
else begin
x14<=x13+{{13{y13[15]}},y13[15:13]};
y14<=y13-{{13{x13[15]}},x13[15:13]};
z14<=z13+16'h0001;
end //第十四次迭代,旋转0.00699度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
x15<=0;
y15<=0;
z15<=0;
end
else if(y14[15]==1) begin
x15<=x14-{{14{y14[15]}},y14[15:14]};
y15<=y14+{{14{x14[15]}},x14[15:14]};
z15<=z14-16'h0;
end
else begin
x15<=x14+{{14{y14[15]}},y14[15:14]};
y15<=y14-{{14{x14[15]}},x14[15:14]};
z15<=z14+16'h0;
end //第十五次迭代,旋转0.00349度
end
always @(posedge clk or negedge rst)
begin
if(~rst) begin
r_out<=0;
phase_out<=0;
end
else begin
r_out<=x15;
phase_out<=z15;
end
end
endmodule
2.2 仿真结果如下
角度分辨率可以达到0.00349,角度误差约为千分之一,满足精度要求。