CORDIC实现幅度和相位求解

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。

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

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值