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。

对于其他象限,提前加一个转化过程即可。

01-20 14:15