学习cordic算法所得(流水线结构、Verilog标准)

最近学习cordic算法,并利用FPGA实现,在整个学习过程中,对cordic算法原理、FPGA中流水线设计、Verilog标准有了更加深刻的理解。

首先,cordic算法的基本思想是通过一系列固定的、与运算基数有关的角度的不断偏,摆以逼近所需的旋转角度。

yuanli1.jpg
为了避免复杂的乘法运算,用一系列微旋转来处理,第i次旋转可表示为:
yl3.jpg
yl4.jpg
yl5.jpg
yl7.jpg
yl7.jpg
由式(7)可知:xn,yn分别为输入角H的余弦和正弦值。
在Verilog实现上,主要体会到了流水线设计的重要性。流水线设计的本质是将一个时钟周期完成的较大的组合逻辑(也可理解为一个逻辑需要多个时钟周期,使得数据不能再每个时钟都有输出)通过合理的切割分由多个时钟周期完成(每个时钟都有数据输出),以n=14为例,若不采用流水线设计,则旋转一个角度就需要14个时钟周期,这样输出正余弦波的最大频率变为Fclk/(2N*14),若采用流水线设计,则输出最大频率变为Fclk/2N,N为输出数据位宽,所以流水线设计具有非常重要的意义。
在reg型变量移位过程中,也对Verilog语言标准有了更新的了解,见:http://www.cnblogs.com/tshell/p/3236476.html
module Test(clk,rst,Phase_Word,Sin_Val,Cos_Val);

input clk,rst;
input[15:0] Phase_Word;
output reg [16:0] Sin_Val,Cos_Val;

parameter Data_Width=16;  //输出数据宽度
parameter Itera_Num=14;
parameter Kn = 16'h4DBA;  //Kn为旋转后缩放比例因子系数,Kn=0.607253*2^16
`define Rot_Angle0 8192
`define Rot_Angle1 4836
`define Rot_Angle2 2555
`define Rot_Angle3 1297
`define Rot_Angle4 651
`define Rot_Angle5 326
`define Rot_Angle6 163
`define Rot_Angle7 81
`define Rot_Angle8 41
`define Rot_Angle9 20
`define Rot_Angle10 10
`define Rot_Angle11 5
`define Rot_Angle12 3
`define Rot_Angle13 1

reg  [Data_Width:0] X[Itera_Num:0];  //X轴坐标值,最终对应cos
reg  [Data_Width:0] Y[Itera_Num:0];  //Y轴坐标值,最终对应sin
reg  [Data_Width:0] Z[Itera_Num:0];  //角度累加器

reg[1:0] quadrant[Itera_Num:0];  //象限,00:第一象限;01,10,11分别为二、三、四象限

/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=0
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[0] <= 0;
     Y[0] <= 0;
     Z[0] <= 0;
  end
else
  begin
     X[0] <= {1'b0,Kn}; 
     Y[0] <= 0;
     Z[0] <= {3'b0,Phase_Word[13:0]};//相位控制在(0-Pi/2),注意Phase_word需为reg signed类型。
  end
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=1
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[1] <= 0;
     Y[1] <= 0;
     Z[1] <= 0;
  end
else
  begin
     X[1] <= X[0] - Y[0]; 
     Y[1] <= X[0] + Y[0];
     Z[1] <= Z[0] - `Rot_Angle0;//第一次默认逆时针旋转45度
  end
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=2
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[2] <= 0;
     Y[2] <= 0;
     Z[2] <= 0;
  end
else
  begin
    if(Z[1][16])
       begin
          X[2] <= X[1] + {{1{Y[1][16]}},Y[1][16:1]};
          Y[2] <= Y[1] - {{1{X[1][16]}},X[1][16:1]};
          Z[2] <= Z[1] + `Rot_Angle1;  //顺时针旋转
        end
     else
       begin
          X[2] <= X[1] - {{1{Y[1][16]}},Y[1][16:1]};
          Y[2] <= Y[1] + {{1{X[1][16]}},X[1][16:1]};
          Z[2] <= Z[1] - `Rot_Angle1;  //逆时针旋转
       end
  end
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=3
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[3] <= 0;
     Y[3] <= 0;
     Z[3] <= 0;
  end
else
  begin
    if(Z[2][16])
       begin
          X[3] <= X[2] + {{2{Y[2][16]}},Y[2][16:2]};
          Y[3] <= Y[2] - {{2{X[2][16]}},X[2][16:2]};
          Z[3] <= Z[2] + `Rot_Angle2;  //顺时针旋转
        end
     else
       begin
          X[3] <= X[2] - {{2{Y[2][16]}},Y[2][16:2]};
          Y[3] <= Y[2] + {{2{X[2][16]}},X[2][16:2]};
          Z[3] <= Z[2] - `Rot_Angle2;  //逆时针旋转
       end
  end
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=4
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[4] <= 0;
     Y[4] <= 0;
     Z[4] <= 0;
  end
else
  begin
    if(Z[3][16])
       begin
          X[4] <= X[3] + {{3{Y[3][16]}},Y[3][16:3]};
          Y[4] <= Y[3] - {{3{X[3][16]}},X[3][16:3]};
          Z[4] <= Z[3] + `Rot_Angle3;  //顺时针旋转
        end
     else
       begin
          X[4] <= X[3] - {{3{Y[3][16]}},Y[3][16:3]};
          Y[4] <= Y[3] + {{3{X[3][16]}},X[3][16:3]};
          Z[4] <= Z[3] - `Rot_Angle3;  //逆时针旋转
       end
  end
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=5
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[5] <= 0;
     Y[5] <= 0;
     Z[5] <= 0;
  end
else
  begin
    if(Z[4][16])
       begin
          X[5] <= X[4] + {{4{Y[4][16]}},Y[4][16:4]};
          Y[5] <= Y[4] - {{4{X[4][16]}},X[4][16:4]};
          Z[5] <= Z[4] + `Rot_Angle4;  //顺时针旋转
        end
     else
       begin
          X[5] <= X[4] - {{4{Y[4][16]}},Y[4][16:4]};
          Y[5] <= Y[4] + {{4{X[4][16]}},X[4][16:4]};
          Z[5] <= Z[4] - `Rot_Angle4;  //逆时针旋转
       end
  end
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=6
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[6] <= 0;
     Y[6] <= 0;
     Z[6] <= 0;
  end
else
  begin
    if(Z[5][16])
       begin
          X[6] <= X[5] + {{5{Y[5][16]}},Y[5][16:5]};
          Y[6] <= Y[5] - {{5{X[5][16]}},X[5][16:5]};
          Z[6] <= Z[5] + `Rot_Angle5;  //顺时针旋转
        end
     else
       begin
          X[6] <= X[5] - {{5{Y[5][16]}},Y[5][16:5]};
          Y[6] <= Y[5] + {{5{X[5][16]}},X[5][16:5]};
          Z[6] <= Z[5] - `Rot_Angle5;  //逆时针旋转
       end
  end
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=7
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[7] <= 0;
     Y[7] <= 0;
     Z[7] <= 0;
  end
else
  begin
    if(Z[6][16])
       begin
          X[7] <= X[6] + {{6{Y[6][16]}},Y[6][16:6]};
          Y[7] <= Y[6] - {{6{X[6][16]}},X[6][16:6]};
          Z[7] <= Z[6] + `Rot_Angle6;  //顺时针旋转
        end
     else
       begin
          X[7] <= X[6] - {{6{Y[6][16]}},Y[6][16:6]};
          Y[7] <= Y[6] + {{6{X[6][16]}},X[6][16:6]};
          Z[7] <= Z[6] - `Rot_Angle6;  //逆时针旋转
       end
  end  
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=8
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[8] <= 0;
     Y[8] <= 0;
     Z[8] <= 0;
  end
else
  begin
    if(Z[7][16])
       begin
          X[8] <= X[7] + {{7{Y[7][16]}},Y[7][16:7]};
          Y[8] <= Y[7] - {{7{X[7][16]}},X[7][16:7]};
          Z[8] <= Z[7] + `Rot_Angle7;  //顺时针旋转
        end
     else
       begin
          X[8] <= X[7] - {{7{Y[7][16]}},Y[7][16:7]};
          Y[8] <= Y[7] + {{7{X[7][16]}},X[7][16:7]};
          Z[8] <= Z[7] - `Rot_Angle7;  //逆时针旋转
       end
  end  
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=9
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[9] <= 0;
     Y[9] <= 0;
     Z[9] <= 0;
  end
else
  begin
    if(Z[8][16])
       begin
          X[9] <= X[8] + {{8{Y[8][16]}},Y[8][16:8]};
          Y[9] <= Y[8] - {{8{X[8][16]}},X[8][16:8]};
          Z[9] <= Z[8] + `Rot_Angle8;  //顺时针旋转
        end
     else
       begin
          X[9] <= X[8] - {{8{Y[8][16]}},Y[8][16:8]};
          Y[9] <= Y[8] + {{8{X[8][16]}},X[8][16:8]};
          Z[9] <= Z[8] - `Rot_Angle8;  //逆时针旋转
       end
  end  
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=10
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[10] <= 0;
     Y[10] <= 0;
     Z[10] <= 0;
  end
else
  begin
    if(Z[9][16])
       begin
          X[10] <= X[9] + {{9{Y[9][16]}},Y[9][16:9]};
          Y[10] <= Y[9] - {{9{X[9][16]}},X[9][16:9]};
          Z[10] <= Z[9] + `Rot_Angle9;  //顺时针旋转
        end
     else
       begin
          X[10] <= X[9] - {{9{Y[9][16]}},Y[9][16:9]};
          Y[10] <= Y[9] + {{9{X[9][16]}},X[9][16:9]};
          Z[10] <= Z[9] - `Rot_Angle9;  //逆时针旋转
       end
  end  
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=11
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[11] <= 0;
     Y[11] <= 0;
     Z[11] <= 0;
  end
else
  begin
    if(Z[10][16])
       begin
          X[11] <= X[10] + {{10{Y[10][16]}},Y[10][16:10]};
          Y[11] <= Y[10] - {{10{X[10][16]}},X[10][16:10]};
          Z[11] <= Z[10] + `Rot_Angle10;  //顺时针旋转
        end
     else
       begin
          X[11] <= X[10] - {{10{Y[10][16]}},Y[10][16:10]};
          Y[11] <= Y[10] + {{10{X[10][16]}},X[10][16:10]};
          Z[11] <= Z[10] - `Rot_Angle10;  //逆时针旋转
       end
  end  
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=12
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[12] <= 0;
     Y[12] <= 0;
     Z[12] <= 0;
  end
else
  begin
    if(Z[11][16])
       begin
          X[12] <= X[11] + {{11{Y[11][16]}},Y[11][16:11]};
          Y[12] <= Y[11] - {{11{X[11][16]}},X[11][16:11]};
          Z[12] <= Z[11] + `Rot_Angle11;  //顺时针旋转
        end
     else
       begin
          X[12] <= X[11] - {{11{Y[11][16]}},Y[11][16:11]};
          Y[12] <= Y[11] + {{11{X[11][16]}},X[11][16:11]};
          Z[12] <= Z[11] - `Rot_Angle11;  //逆时针旋转
       end
  end  
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=13
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[13] <= 0;
     Y[13] <= 0;
     Z[13] <= 0;
  end
else
  begin
    if(Z[12][16])
       begin
          X[13] <= X[12] + {{12{Y[12][16]}},Y[12][16:12]};
          Y[13] <= Y[12] - {{12{X[12][16]}},X[12][16:12]};
          Z[13] <= Z[12] + `Rot_Angle12;  //顺时针旋转
        end
     else
       begin
          X[13] <= X[12] - {{12{Y[12][16]}},Y[12][16:12]};
          Y[13] <= Y[12] + {{12{X[12][16]}},X[12][16:12]};
          Z[13] <= Z[12] - `Rot_Angle12;  //逆时针旋转
       end
  end  
/*****************************************************
功能:流水线实现cordic算法
说明:Itera_Num=14
*****************************************************/    
always @(posedge clk or negedge rst)
if(!rst)
  begin
     X[14] <= 0;
     Y[14] <= 0;
     Z[14] <= 0;
  end
else
  begin
    if(Z[13][16])
       begin
          X[14] <= X[13] + {{13{Y[13][16]}},Y[13][16:13]};
          Y[14] <= Y[13] - {{13{X[13][16]}},X[13][16:13]};
          Z[14] <= Z[13] + `Rot_Angle13;  //顺时针旋转
        end
     else
       begin
          X[14] <= X[13] - {{13{Y[13][16]}},Y[13][16:13]};
          Y[14] <= Y[13] + {{13{X[13][16]}},X[13][16:13]};
          Z[14] <= Z[13] - `Rot_Angle13;  //逆时针旋转
       end
  end  
/*****************************************************
功能:获取象限信息
*****************************************************/    
always @ (posedge clk or negedge rst)
begin
  if(!rst) 
    begin
       quadrant[0] <= 0;
        quadrant[1] <= 0;
        quadrant[2] <= 0;
        quadrant[3] <= 0;
        quadrant[4] <= 0;
        quadrant[5] <= 0;
        quadrant[6] <= 0;
        quadrant[7] <= 0;
        quadrant[8] <= 0;
        quadrant[9] <= 0;
        quadrant[10] <= 0;
        quadrant[11] <= 0;
        quadrant[12] <= 0;
        quadrant[13] <= 0;
        quadrant[14] <= 0;
     end
  else
    begin
          quadrant[0] <= Phase_Word[15:14];
          quadrant[1] <= quadrant[0];
          quadrant[2] <= quadrant[1];
          quadrant[3] <= quadrant[2];
          quadrant[4] <= quadrant[3];
          quadrant[5] <= quadrant[4];
          quadrant[6] <= quadrant[5];
          quadrant[7] <= quadrant[6];
          quadrant[8] <= quadrant[7];
          quadrant[9] <= quadrant[8];
          quadrant[10] <= quadrant[9];
          quadrant[11] <= quadrant[10];
          quadrant[12] <= quadrant[11];
          quadrant[13] <= quadrant[12];
          quadrant[14] <= quadrant[13];
    end
end
/*****************************************************
功能:根据象限确定输出值
说明:当角度A=theta+pi/2在(pi/2~pi)时,
     cos(theta+pi/2)=-sin(theta).其中,theta为第一象限角
      二进制中,负数等于整数取反再加一
*****************************************************/    
always @ (posedge clk or negedge rst)
begin
  if(!rst)
    begin
       Sin_Val <= 0;
        Cos_Val <= 0;
     end
  else
    begin
       case(quadrant[14])
        2'b00:begin
                    Cos_Val <= X[14];
                    Sin_Val <= Y[14];
                end
        2'b01:begin
                    Cos_Val <= ~Y[14] + 1'b1;
                    Sin_Val <= X[14];
                end
        2'b10:begin
                    Cos_Val <= ~X[14] + 1'b1;
                    Sin_Val <= ~Y[14] + 1'b1;
                end
        2'b11:begin
                    Cos_Val <= Y[14];
                    Sin_Val <= ~X[14] + 1'b1;
                end
      endcase
     end
end

  
endmodule
View Code

整个源码设计主要参考了aikimi7的设计,连接:http://www.cnblogs.com/aikimi7/p/3929592.html

 
原文地址:https://www.cnblogs.com/yangjun1219/p/4981057.html