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。
对于其他象限,提前加一个转化过程即可。
原文:https://www.cnblogs.com/mia1004/p/11628409.html