CORDIC算法--流水线结构
cordic算法的Verilog实现
module cordic #(parameter DATA_WIDTH=8) ( input clk, input rst_n, input ena, input [DATA_WIDTH-1:0] phase_in, output reg [DATA_WIDTH-1:0] sin_out, output reg [DATA_WIDTH-1:0] cos_out, output reg [DATA_WIDTH-1:0] eps ); localparam PIPELINE=8; reg [DATA_WIDTH-1:0] phase_in_reg; reg [DATA_WIDTH-1:0] x0,y0,z0; reg [DATA_WIDTH-1:0] x1,y1,z1; reg [DATA_WIDTH-1:0] x2,y2,z2; reg [DATA_WIDTH-1:0] x3,y3,z3; reg [DATA_WIDTH-1:0] x4,y4,z4; reg [DATA_WIDTH-1:0] x5,y5,z5; reg [DATA_WIDTH-1:0] x6,y6,z6; reg [DATA_WIDTH-1:0] x7,y7,z7; reg [1:0] quadrant [PIPELINE:0]; integer i; always @(posedge clk,negedge rst_n) begin if(!rst_n) phase_in_reg <= 8'b0; else if(ena) begin case(phase_in[7:6]) 2'b00: phase_in_reg <= phase_in; 2'b01: phase_in_reg <= phase_in-8'h40; 2'b10: phase_in_reg <= phase_in-8'h80; 2'b11: phase_in_reg <= phase_in-8'hc0; default:; endcase end end always @ (posedge clk,negedge rst_n) begin if(!rst_n) begin x0<=8'b0; y0<=8'b0; z0<=8'b0; end else if(ena) begin x0 <= 8'h4D; //0.60725*2^7 y0 <= 8'h00; z0 <= phase_in_reg; end end //level 1 always @ (posedge clk,negedge rst_n) begin if(!rst_n) begin x1 <=8'b0; y1 <=8'b0; z1 <=8'b0; end else if(ena) if(z0[7]==1'b0) begin x1 <= x0-y0; y1 <= y0+x0; z1 <=z0-8'h20;//45deg end else begin x1<=x0+y0; y1<=y0-x0; z1<=z0+8'h20; end end //level 2 always @ (posedge clk,negedge rst_n) begin if(!rst_n) begin x2 <=8'b0; y2 <=8'b0; z2 <=8'b0; end else if(ena) if(z1[7]==1'b0) begin x2 <= x1-{y1[DATA_WIDTH-1],y1[DATA_WIDTH-1:1]}; y2 <= y1+{x1[DATA_WIDTH-1],x1[DATA_WIDTH-1:1]}; z2 <=z1-8'h12;//26deg end else begin x2<= x1+{y1[DATA_WIDTH-1],y1[DATA_WIDTH-1:1]}; y2<= y1-{x1[DATA_WIDTH-1],x1[DATA_WIDTH-1:1]}; z2<= z1+8'h12; end end //level 3 always @ (posedge clk,negedge rst_n) begin if(!rst_n) begin x3 <=8'b0; y3 <=8'b0; z3 <=8'b0; end else if(ena) if(z2[7]==1'b0) begin x3 <= x2-{{2{y2[DATA_WIDTH-1]}},y2[DATA_WIDTH-1:2]}; y3 <= y2+{{2{x2[DATA_WIDTH-1]}},x2[DATA_WIDTH-1:2]}; z3 <=z2-8'h09;//14deg end else begin x3<= x2+{{2{y2[DATA_WIDTH-1]}},y2[DATA_WIDTH-1:2]}; y3<= y2-{{2{x2[DATA_WIDTH-1]}},x2[DATA_WIDTH-1:2]}; z3<= z2+8'h09; end end //level 4 always @ (posedge clk,negedge rst_n) begin if(!rst_n) begin x4 <=8'b0; y4 <=8'b0; z4 <=8'b0; end else if(ena) if(z3[7]==1'b0) begin x4 <= x3-{{3{y3[DATA_WIDTH-1]}},y3[DATA_WIDTH-1:3]}; y4 <= y3+{{3{x3[DATA_WIDTH-1]}},x3[DATA_WIDTH-1:3]}; z4 <= z3-8'h04;//7deg end else begin x4<= x3+{{3{y3[DATA_WIDTH-1]}},y3[DATA_WIDTH-1:3]}; y4<= y3-{{3{x3[DATA_WIDTH-1]}},x3[DATA_WIDTH-1:3]}; z4<= z3+8'h04; end end //level 5 always @ (posedge clk,negedge rst_n) begin if(!rst_n) begin x5 <=8'b0; y5 <=8'b0; z5 <=8'b0; end else if(ena) if(z4[7]==1'b0) begin x5 <= x4-{{4{y4[DATA_WIDTH-1]}},y4[DATA_WIDTH-1:4]}; y5 <= y4+{{4{x4[DATA_WIDTH-1]}},x4[DATA_WIDTH-1:4]}; z5 <= z4-8'h02;//4deg end else begin x5<= x4+{{4{y4[DATA_WIDTH-1]}},y4[DATA_WIDTH-1:4]}; y5<= y4-{{4{x4[DATA_WIDTH-1]}},x4[DATA_WIDTH-1:4]}; z5<= z4+8'h02; end end //level 6 always @ (posedge clk,negedge rst_n) begin if(!rst_n) begin x6 <=8'b0; y6 <=8'b0; z6 <=8'b0; end else if(ena) if(z5[7]==1'b0) begin x6 <= x5-{{5{y5[DATA_WIDTH-1]}},y5[DATA_WIDTH-1:5]}; y6 <= y5+{{5{x5[DATA_WIDTH-1]}},x5[DATA_WIDTH-1:5]}; z6 <= z5-8'h01;//2deg end else begin x6<= x5+{{5{y5[DATA_WIDTH-1]}},y5[DATA_WIDTH-1:5]}; y6<= y5-{{5{x5[DATA_WIDTH-1]}},x5[DATA_WIDTH-1:5]}; z6<= z5+8'h01; end end //level 7 always @ (posedge clk,negedge rst_n) begin if(!rst_n) begin x7 <=8'b0; y7 <=8'b0; z7 <=8'b0; end else if(ena) if(z6[7]==1'b0) begin x7 <= x6-{{6{y6[DATA_WIDTH-1]}},y6[DATA_WIDTH-1:6]}; y7 <= y6+{{6{x6[DATA_WIDTH-1]}},x6[DATA_WIDTH-1:6]}; z7 <= z6-8'h00;//2deg end else begin x7<= x6+{{6{y6[DATA_WIDTH-1]}},y6[DATA_WIDTH-1:6]}; y7<= y6-{{6{x6[DATA_WIDTH-1]}},x6[DATA_WIDTH-1:6]}; z7<= z6+8'h00; end end //------- always @ (posedge clk,negedge rst_n) begin if(!rst_n) for(i=0;i<=PIPELINE;i=i+1) quadrant[i]<=2'b00; else if(ena) begin for(i=0;i<PIPELINE;i=i+1) quadrant[i+1]<=quadrant[i]; quadrant[0]<=phase_in[7:6]; end end //------------ always @ (posedge clk,negedge rst_n) begin if(!rst_n) begin sin_out <= 8'b0; cos_out <= 8'b0; eps <= 8'b0; end else if(ena) case(quadrant[7]) 2'b00: begin sin_out <= y6; cos_out <= x6; eps <= z6; end 2'b01: begin sin_out <= x6; cos_out <= ~(y6)+1'b1; eps <= z6; end 2'b10: begin sin_out <= ~(y6)+1'b1; cos_out <= ~(x6)+1'b1; eps <= z6; end 2'b11: begin sin_out <= ~(x6)+1'b1; cos_out <= y6; eps <= z6; end endcase end endmodule
测试文件cordic_tb.v
// Generated on "05/21/2010 10:09:04" // Verilog Test Bench template for design : cordic // // Simulation tool : ModelSim (Verilog) // `timescale 1 ps/ 1 ps module cordic_tb; // test vector input registers reg arst; reg clk; reg clken; reg [7:0] phase; // wires wire [7:0] cosine_out; wire [7:0] eps_out; wire [7:0] sine_out; // localparam coef=1000; // assign statements (if any) cordic i1 ( // port map - connection between master ports and signals/registers .rst_n(arst), .clk(clk), .ena(clken), .cos_out(cosine_out), .eps(eps_out), .phase_in(phase), .sin_out(sine_out) ); initial begin clk=0; clken=1; arst=0; #(30*coef) arst=1; #(10000*coef) $stop; end always #(5*coef) clk=~clk; // always @(negedge clk) begin if(!arst) phase=0; else phase=phase+8'b00011001;; end endmodule
路漫漫其修远兮,吾将上下而求索