迭代七次的CORDIC算法-Verilog实现求解正弦余弦函数
COEDIC.v
module CORDIC #(parameter DATA_WIDTH = 4'd8 , // we set data widthparameter PIPELINE = 4'd8)(input clk ,input rst_n ,input [DATA_WIDTH - 1 : 0] phase ,input ena ,output reg [DATA_WIDTH - 1 : 0] sin_out ,output reg [DATA_WIDTH - 1 : 0] cos_out);// ------------------------------------------------ \\// next is define and parameter \\// -------------------------------------------------\\
reg [DATA_WIDTH - 1 : 0] phase_reg ;reg [DATA_WIDTH - 1 : 0] X0 ;reg [DATA_WIDTH - 1 : 0] Y0 ;reg [DATA_WIDTH - 1 : 0] Z0 ;wire [DATA_WIDTH - 1 : 0] X1 , Y1 , Z1 ;wire [DATA_WIDTH - 1 : 0] X2 , Y2 , Z2 ;wire [DATA_WIDTH - 1 : 0] X3 , Y3 , Z3 ;wire [DATA_WIDTH - 1 : 0] X4 , Y4 , Z4 ;wire [DATA_WIDTH - 1 : 0] X5 , Y5 , Z5 ;wire [DATA_WIDTH - 1 : 0] X6 , Y6 , Z6 ;wire [DATA_WIDTH - 1 : 0] X7 , Y7 , Z7 ;reg [1:0] quadrant[PIPELINE : 0] ;integer i ;always@(posedge clk or negedge rst_n)beginif(rst_n == 0)for(i = 0 ; i <= PIPELINE ; i=i+1)quadrant[i] <= 0 ;elseif(ena == 1)beginfor(i = 0 ; i <= PIPELINE ; i=i+1)quadrant[i+1] <= quadrant[i] ;quadrant[0] <= phase[DATA_WIDTH - 1 : DATA_WIDTH - 2] ;endend// we set a new phase to Unify the phase in the first quadrant// we set 8'h 0010 0000 => 45度 and 1000 0000 => 180度always@(posedge clk or negedge rst_n)beginif(rst_n == 0)beginphase_reg <= 0 ;endelse if(ena == 1)begincase(phase[DATA_WIDTH -1 : DATA_WIDTH -2])2'b00 :phase_reg <= phase ;2'b01 :phase_reg <= phase - 8'h40 ; // subtract 902'b10 :phase_reg <= phase - 8'h80 ; // subtract 1802'b11 :phase_reg <= phase - 8'hC0 ; // subtract 270default :;endcaseendend// start to calculate// we should set x0= 0.607252935 y0= 0 z0always@(posedge clk or negedge rst_n )beginif( rst_n == 0)beginX0 <= 0 ;Y0 <= 0 ;Z0 <= 0 ;endelse if(ena == 1 )beginX0 <= 8'h4D ;Y0 <= 0 ;Z0 <= phase_reg ;endend// next is iterationINTERATION#(.DATA_WIDTH ( 4'd8 ),.shift ( 4'd0 ),.ANGLE ( 8'h20 ))u_INTERATION0(.clk ( clk ),.rst_n ( rst_n ),.ena ( ena ),.X0 ( X0 ),.Y0 ( Y0 ),.Z0 ( Z0 ),.X1 ( X1 ),.Y1 ( Y1 ),.Z1 ( Z1 ));INTERATION#(.DATA_WIDTH ( 4'd8 ),.shift ( 4'd1 ),.ANGLE ( 8'h12 ))u_INTERATION1(.clk ( clk ),.rst_n ( rst_n ),.ena ( ena ),.X0 ( X1 ),.Y0 ( Y1 ),.Z0 ( Z1 ),.X1 ( X2 ),.Y1 ( Y2 ),.Z1 ( Z2 ));INTERATION#(.DATA_WIDTH ( 4'd8 ),.shift ( 4'd2 ),.ANGLE ( 8'h09 ))u_INTERATION2(.clk ( clk ),.rst_n ( rst_n ),.ena ( ena ),.X0 ( X2 ),.Y0 ( Y2 ),.Z0 ( Z2 ),.X1 ( X3 ),.Y1 ( Y3 ),.Z1 ( Z3 ));INTERATION#(.DATA_WIDTH ( 4'd8 ),.shift ( 4'd3 ),.ANGLE ( 8'h04 ))u_INTERATION3(.clk ( clk ),.rst_n ( rst_n ),.ena ( ena ),.X0 ( X3 ),.Y0 ( Y3 ),.Z0 ( Z3 ),.X1 ( X4 ),.Y1 ( Y4 ),.Z1 ( Z4 ));INTERATION#(.DATA_WIDTH ( 4'd8 ),.shift ( 4'd4 ),.ANGLE ( 8'h02 ))u_INTERATION4(.clk ( clk ),.rst_n ( rst_n ),.ena ( ena ),.X0 ( X4 ),.Y0 ( Y4 ),.Z0 ( Z4 ),.X1 ( X5 ),.Y1 ( Y5 ),.Z1 ( Z5 ));INTERATION#(.DATA_WIDTH ( 4'd8 ),.shift ( 4'd5 ),.ANGLE ( 8'h01 ))u_INTERATION5(.clk ( clk ),.rst_n ( rst_n ),.ena ( ena ),.X0 ( X5 ),.Y0 ( Y5 ),.Z0 ( Z5 ),.X1 ( X6 ),.Y1 ( Y6 ),.Z1 ( Z6 ));INTERATION#(.DATA_WIDTH ( 4'd8 ),.shift ( 4'd6 ),.ANGLE ( 8'h00 ))u_INTERATION6(.clk ( clk ),.rst_n ( rst_n ),.ena ( ena ),.X0 ( X6 ),.Y0 ( Y6 ),.Z0 ( Z6 ),.X1 ( X7 ),.Y1 ( Y7 ),.Z1 ( Z7 ));// The results of different phases are also different// phase[DATA_WIDTH -1 : DATA_WIDTH -2]// 00 first quadrant// 01 second quadrant// 10 third quadrant// 11 Fourth Quadrantalways@(posedge clk or negedge rst_n)beginif(rst_n == 0)begincos_out <= 0 ;sin_out <= 0 ;endelse if( ena == 1)begincase(quadrant[7])2'b00 :begincos_out <= X6 ;sin_out <= Y6 ;end2'b01 :begincos_out <= ~(Y6) + 1 ;sin_out <= X6 ;end2'b10 :begincos_out <= ~(X6) + 1 ;sin_out <= ~(Y6) + 1 ;end2'b11 :begincos_out <= Y6 ;sin_out <= ~(X6) + 1 ;enddefault:;endcaseendend
endmodule
Interation.v
module INTERATION #(parameter DATA_WIDTH = 4'd8 ,parameter shift = 4'd0 ,parameter ANGLE = 8'h20)(input clk ,input rst_n ,input ena ,input [DATA_WIDTH - 1 : 0] X0 ,input [DATA_WIDTH - 1 : 0] Y0 ,input [DATA_WIDTH - 1 : 0] Z0 ,output reg [DATA_WIDTH - 1 : 0] X1 ,output reg [DATA_WIDTH - 1 : 0] Y1 ,output reg [DATA_WIDTH - 1 : 0] Z1);always@(posedge clk or negedge rst_n)beginif( rst_n == 0)beginX1 <= 0 ;Y1 <= 0 ;Z1 <= 0 ;endelse if( ena == 1)beginif(Z0[DATA_WIDTH - 1] == 0 )beginX1 <= X0 - {{shift{ Y0[DATA_WIDTH - 1] }} ,Y0[DATA_WIDTH - 1 : shift] } ;Y1 <= Y0 + {{shift{ X0[DATA_WIDTH - 1] }} ,X0[DATA_WIDTH - 1 : shift] } ;Z1 <= Z0 - ANGLE ;endelse if(Z0[DATA_WIDTH - 1] == 1 )beginX1 <= X0 + {{shift{ Y0[DATA_WIDTH - 1 ] }} ,Y0[DATA_WIDTH - 1 : shift] } ;Y1 <= Y0 - {{shift{ X0[DATA_WIDTH - 1 ] }} ,X0[DATA_WIDTH - 1 : shift] } ;Z1 <= Z0 + ANGLE ;endendendendmodule
cordic_tb.v
module cordic_tb #(parameter DATA_WIDTH = 4'd8
);
reg clk ;
reg rst_n ;
reg [DATA_WIDTH - 1 : 0] phase ;
reg ena ;
wire [DATA_WIDTH - 1 : 0] sin_out ;
wire [DATA_WIDTH - 1 : 0] cos_out ;CORDIC#(.DATA_WIDTH ( DATA_WIDTH )
)u_CORDIC(.clk ( clk ),.rst_n ( rst_n ),.phase ( phase ),.ena ( ena ),.sin_out ( sin_out ),.cos_out ( cos_out )
);always #5 clk = ~clk ;initial
begin clk = 0 ;rst_n = 0 ; ena = 1 ;phase = 8'h00 ;#10rst_n = 1 ;
end
always #10
phase = phase + 1 ; endmodule
README.md
# 本文参考自 西电的verilog 课程实验 还有网上的 CORDIC算法详解
对于CORDIC的算法 关键是学会迭代和 掌握自 不同象限角度的换算
我在参阅网上资料的时候 发现有些角度的换算存在了错误这里我再写入一下
| 第一象限 | 第二象限 | 第三象限 | 第四象限 |
| --------| --------| --------| --------|
| (x,y) | (x,y) | (x,y) | (x,y) |
| (x,y) | (-y,x) | (-x ,-y) | (y , -x) |最关键的是在于理清如何计算的 实际操作起来的 圆周旋转求旋转模式下的正余弦
并不用考虑太多的 角度旋转 选取初始值之后 直接迭代开干
## 波形很奇怪 我也不懂为什么做不到像其他人的这么顺滑 但是应该没错吧
纠正一下 把进制改成 Signed Decimal 就可以得到顺滑的常规正弦函数波形