CORDIC算法的FPGA实现

来源:互联网 发布:淘宝大尺度 编辑:程序博客网 时间:2024/04/30 02:31

二、CORDIC算法的FPGA实现
在采用FPGA实现CORDIC算法时,需要考虑两个方面的因素:速度和面积。以这两个因素作为出发点的有3种硬件架构:紧缩结构(Rolled)、展开结构(Unrolled)和展开流水结构(Unrolled Pipelined)。其中紧缩结构的占用的资源最少,因为对CORDIC处理单元的循环复用,也正因此使得控制单元设计略显复杂,时序控制较为繁琐,系统处理速度较低。展开结构式对紧缩结构的扩展,对每次迭代赋予了独立的CORDIc处理单元,从而不需要控制电路,只需要移位和加减操作。这是与紧缩结构中COrDIC处理单元最大的不同。显然,相较于紧缩结构,展开结构消耗的资源显著增加。为了提高系统处理的速度,对展开结构加流水寄存器,即为展开流水结构。它有效地缩短了关键路径,使得关键路径的长度由展开结构的N个CORDIC处理单元变为1个CORDIC处理单元。因此,展开流水结构具有最高的处理速度,而这时以消耗更多的资源换取的。
流水线CORDIC结构虽然占用的硬件资源比其他结构稍多,但是流水线结构可以提高数据的吞吐率,对于大多数的数字信号处理算法来说,存在很多同一指令连续处理很长一段数据的情况,此时高吞吐率更有意义。从当前FPGA的发展趋势来看,芯片内的门资源相对富裕,对流水线CORDIC的实现规模约束很小,此外,流水线CORDIC不存在迭代式CORDIC的反馈回路,使得单元结构更加规则,有利于FPGA实现。所以使用流水结构来实现CORDIC算法,如图1所示。   Cordic算法的FPGA实现之流水结构     图2中的sgn(yi)和sgn(zi)分别表示yi和zi的符号位即最高位,根据工作模式(旋转模式还是向量模式),选择其中之一赋给di(这里为1或0)。加法器根据di确定工作模式(加法操作还是减法操作)。">>i"表示对输入数据右移i位,i由control模块控制。ROM中存放的数据为每次迭代时的旋转角度arctan(1/2^i)可以是角度表示也可以是弧度表示,统一即可。
展开结构的具体细节如图2所示。该结构非常清晰。每次迭代有独立的处理单元,在图2中,Ci为第i次的旋转角。显然,此结构所用资源与迭代次数有直接的关系。Cordic算法的FPGA实现之流水结构                                         图2  展开结构的具体细节u
展开结构中的每个CORDIC处理单元有相同的架构--移位加减蝶形单元,它由加法器和移位模块共同组成。加法器根据sgn确定工作模式。
 
二、Verilog硬件描述
2.1 圆坐标系下的向量模式
    这种方法相当于是把矩形坐标系下坐标(x,y)变换到极坐标系下的(r,θ),其中r,θ分量可以根据以下公式逐次迭代得到:
   Cordic算法的FPGA实现之流水结构   经过n次迭代后得到以下公式:
Cordic算法的FPGA实现之流水结构    那么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,角度误差约为千分之一,满足精度要求。Cordic算法的FPGA实现之流水结构




0 0
原创粉丝点击