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;
Testbench
`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。
对于其他象限,提前加一个转化过程即可.