2019年10月6日19:10:11
原理不再赘述,MATLAB:
function [pha, amp] = cordic(x, y) %仅以第一象限为例 K = 0.607253; atanTable = atand(2.^([0:-1:-15]))/180; len = length(atanTable); pha = 0; for i = 0:len-1 if (y>0) x_new = x + y*2^-i;%此处移位寄存器实现 y_new = y - x*2^-i;%此处移位寄存器实现 x = x_new; y = y_new; pha = pha + atanTable(i+1); else x_new = x-y*2^-i;%此处移位寄存器实现 y_new = y+x*2^-i;%此处移位寄存器实现 x = x_new; y = y_new; pha = pha-atanTable(i+1); end end amp = K * x;
实现思路与除法CORDIC类似,对应FPGA代码:
tb
`timescale 1ns / 1ps module tb; /************* PARAMETER ******************/ parameter LOOPS = 26; parameter DATWIDTH = 26; //parameter RESWIDTH = 12; parameter PHAWIDTH = 26; parameter AMPWIDTH = 26; /**************** INPUT OUTOUT ************/ logic signed [DATWIDTH - 1:0] fracDown; logic signed [DATWIDTH - 1:0] fracUp; logic signed [AMPWIDTH - 1:0] amp; logic signed [PHAWIDTH - 1:0] pha; //logic signed [RESWIDTH - 1:0] divRes; /**************** INITIAL *****************/ logic clk; logic rst; initial begin clk = 0; rst = 1'b1; fracDown = 0; fracUp = 0; #20 rst = 1'b0; #200 fracDown = 26'd2000; fracUp = 26'd2000; #200 fracDown = 26'd4000; fracUp = 26'd5000; #200 fracDown = 26'd5000; fracUp = 26'd4000; #200 fracDown = 26'd5000; fracUp = 26'd5000; #1000 $stop; end always #2 clk = !clk; /**************** CORDIC AMP PHA *********************/ cordicAmpPha UcordicAmpPha( .clk(clk), .rst(rst), .dataReal(fracDown), .dataImag(fracUp), .amp(amp), .pha(pha) ); /**************** CORDIV ******************/ /* cordic_div #( .LOOPS(LOOPS), .DATWIDTH(DATWIDTH), .RESWIDTH(RESWIDTH) ) Ucordic_div( .clk(clk), .rst(rst), .fracDown(fracDown), .fracUp(fracUp), .divRes(divRes) ); */ glbl glbl(); endmodule
cordicAmpPha
`timescale 1ns / 1ps module cordicAmpPha(clk, rst, dataReal, dataImag, amp, pha); /****************** PARAMETER *********************/ parameter DATAWIDTH = 26; parameter AMPWIDTH = 26; parameter PHAWIDTH = 26; parameter LOOP = 26; //localparam K = 12'h4DC; wire [0:LOOP - 1][PHAWIDTH - 1:0] atanTable = { 26'h800000, 26'h4B9014, 26'h27ECE1, 26'h144447, 26'h0A2C35, 26'h051760, 26'h028BD8, 26'h0145F1, 26'h00A2F9, 26'h00517D, 26'h0028BE, 26'h00145F, 26'h000A30, 26'h000518, 26'h00028C, 26'h000146, 26'h0000A3, 26'h000051, 26'h000029, 26'h000014, 26'h00000A, 26'h000005, 26'h000003, 26'h000001, 26'h000001, 26'h000000 }; /****************** INPUT OUTPUT ******************/ input clk; input rst; input signed [DATAWIDTH - 1:0] dataReal; input signed [DATAWIDTH - 1:0] dataImag; output signed [AMPWIDTH - 1:0] amp; output signed [PHAWIDTH - 1:0] pha; /****************** CORDIC ******************/ wire signed [LOOP:0][DATAWIDTH - 1:0] datasReal; wire signed [LOOP:0][DATAWIDTH - 1:0] datasImag; wire signed [LOOP:0][PHAWIDTH - 1:0] phas; //reg signed [2*AMPWIDTH - 1:0] amp1; assign datasReal[0] = dataReal; assign datasImag[0] = dataImag; assign phas[0] = {PHAWIDTH{1'b0}}; genvar ii; generate for (ii = 0; ii < LOOP; ii = ii + 1) begin:cordic_ii cordicAmpPhaUnit #( .DATAWIDTH(DATAWIDTH), .PHAWIDTH(PHAWIDTH), .STAGE(ii) ) UcordicAmpPhaUnit( .clk(clk), .rst(rst), .xin(datasReal[ii]), .yin(datasImag[ii]), .phaOut(phas[ii + 1]), .phaIn(phas[ii]), .xout(datasReal[ii + 1]), .yout(datasImag[ii + 1]), .atanCoef(atanTable[ii]) ); end endgenerate /* always @(posedge clk) begin if(rst) begin amp1 <= {{2*AMPWIDTH -1}{1'b0}}; end else begin amp1 <= datasReal[LOOP] * K; end end assign amp = {amp1[2*AMPWIDTH - 1], amp1[AMPWIDTH - 2:0]}; */ assign amp = datasReal[LOOP]; assign pha = phas[LOOP]; endmodule module cordicAmpPhaUnit(clk, rst, xin, yin, phaOut, phaIn, xout, yout, atanCoef); /****************** PARAMETER ******************/ parameter DATAWIDTH = 12; parameter PHAWIDTH = 12; parameter STAGE = 0; /****************** INPUT OUTPUT ******************/ input clk; input rst; input signed [DATAWIDTH - 1:0] xin; input signed [DATAWIDTH - 1:0] yin; input signed [PHAWIDTH - 1:0] phaIn; input signed [PHAWIDTH - 1:0] atanCoef; output reg signed [DATAWIDTH - 1:0] xout; output reg signed [DATAWIDTH - 1:0] yout; output reg signed [PHAWIDTH - 1:0] phaOut; /****************** CORDIC UNIT ******************/ always @(posedge clk or negedge rst) begin if(rst) begin xout <= {DATAWIDTH{1'b0}}; yout <= {DATAWIDTH{1'b0}}; phaOut <= {PHAWIDTH{1'b0}}; end else begin if(yin[DATAWIDTH - 1]) begin xout <= xin - (yin >>> STAGE); yout <= yin + (xin >>> STAGE); phaOut <= phaIn - atanCoef; end else begin xout <= xin + (yin >>> STAGE); yout <= yin - (xin >>> STAGE); phaOut <= phaIn + atanCoef; end end end endmodule
仿真结果:
对于幅度,考虑到只是比例不同,K = 0.607253没有计算,例如:abs(2000 + 2000i) ≈ 4660 * K
对于相位,26位有符号数,8390402/2^25 = 0.2501 ≈ 0.25 ,即1/4个pi ,度量为pi。
对于其他象限,提前加一个转化过程即可。