学习cordic算法所得(流水线结构、Verilog标准)
最近学习cordic算法,并利用FPGA实现,在整个学习过程中,对cordic算法原理、FPGA中流水线设计、Verilog标准有了更加深刻的理解。
首先,cordic算法的基本思想是通过一系列固定的、与运算基数有关的角度的不断偏,摆以逼近所需的旋转角度。
为了避免复杂的乘法运算,用一系列微旋转来处理,第i次旋转可表示为:
由式(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
整个源码设计主要参考了aikimi7的设计,连接:http://www.cnblogs.com/aikimi7/p/3929592.html
posted on 2015-11-20 15:54 yang_jun1219 阅读(2223) 评论(0) 编辑 收藏 举报