Ok now i am trying to do my own CORDIC core to have the magnitude and phase value or a real/imaginary phasor.
I am following this algorithm:
http://www.dspguru.com/dsp/faqs/cordic and trying to make a RTL out of it.
My matlab code is working and is the following
function v = cordic(real, imaginaria,n)
% This function computes v = (beta in radians)
% using n iterations. Increasing n will increase the precision.
multiplier = 2^22;
tmp_real = 0;
if (real < 0)
tmp_real = real;
if imaginaria > 0
real = imaginaria;
imaginaria = -tmp_real;
acc_phase_rads = -(pi/2)* multiplier ;
else
real = -imaginaria;
imaginaria = tmp_real;
acc_phase_rads = pi/2 * multiplier;
end;
else
acc_phase_rads = 0;
end;
% Initialization of tables of constants used by CORDIC
% need a table of arctangents of negative powers of two, in radians:
% angles = atan(2.^-(0:27));
% and a table of products of reciprocal lengths of vectors :
ka = 1;
for j=1:n;
Kvalues(j) = ka
angles(j) = atan(ka)
ka = ka * 0.5;
end;
for l=1:n;
K = Kvalues(l) * multiplier;
phase_rads = angles(l) * multiplier;
tmp_real = real;
if (imaginaria >=0)
real = (real*multiplier + imaginaria * K)/multiplier;
imaginaria = (multiplier*imaginaria - tmp_real * K)/multiplier;
acc_phase_rads = (acc_phase_rads - phase_rads );
else
real = (real*multiplier - imaginaria * K)/multiplier;
imaginaria = (imaginaria*multiplier + tmp_real * K)/multiplier;
acc_phase_rads = (acc_phase_rads + phase_rads);
end;
end;
result_phase_rads = -acc_phase_rads/multiplier
result_mag = real * (1/1.6468)
return
My VHDL code at the moment is the following
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_signed.all;
-- entity declaration
entity cordic_V1 is
port(
-- system signals
clk_i : in std_logic;
rst_i_n : in std_logic;
-- interface signals
ena_i : in std_logic;
real_i : in std_logic_vector(31 downto 0);
imag_i : in std_logic_vector(31 downto 0);
fase_o : out std_logic_vector(31 downto 0);
mag_o : out std_logic_vector(31 downto 0);
finish_cordic : out std_logic
);
end cordic_V1;
begin
angulo_inst : angulo_atan
port map(
clk_i => clk_i,
rst_i_n => rst_i_n,
indice_i => std_logic_vector(indice),
angulo_o => angulo_indice);
ganho_inst : ganho_k
port map(
clk_i => clk_i,
rst_i_n => rst_i_n,
indice_i => std_logic_vector(indice_2),
ganho_o => ganho_indice);
fase_o <= std_logic_vector (fase_o_reg(31 downto 0));
mag_o <= std_logic_vector (mag_o_reg(31 downto 0));
finish_cordic <= finish_cordic_reg;
-- State machine process
process (rst_i_n, clk_i) is
begin
if (rst_i_n = '0') then
...
elsif rising_edge(clk_i) then
state_core <= state_core_next;
indice <= indice_next;
indice_2 <= indice_2_next;
parte_real <= parte_real_next;
parte_imaginaria <= parte_imaginaria_next;
temp_parte_real <= temp_parte_real_next;
fase_o_reg <= fase_o_reg_next;
mag_o_reg <= mag_o_reg_next;
phase_rads <= phase_rads_next;
acc_phase_rads <= acc_phase_rads_next;
K_reg <= K_reg_next;
tmp_mult_im_k <= tmp_mult_im_k_next;
tmp_mult_re_k <= tmp_mult_re_k_next;
tmp_operacoes_reg <= tmp_operacoes_reg_next;
tmp_operacoes_acc_reg <= tmp_operacoes_acc_reg_next;
finish_cordic_reg <= finish_cordic_reg_next;
end if;
end process;
process (state_core, indice, indice_2, parte_real, parte_imaginaria, temp_parte_real,
fase_o_reg, mag_o_reg, phase_rads, acc_phase_rads, K_reg, tmp_mult_im_k,
tmp_mult_re_k, tmp_operacoes_reg, tmp_operacoes_acc_reg, real_i, imag_i, ganho_indice, angulo_indice, finish_cordic_reg)
begin
state_core_next <= state_core;
indice_next <= indice;
indice_2_next <= indice_2;
p...
case state_core is
when INIT =>
-- initialize all the registers
indice_next <= (others => '0');
i...
state_core_next <= CORRIGE_Q_P1;
when CORRIGE_Q_P1 =>
parte_real_next <= real_i & ZERO_STUFF;
parte_imaginaria_next <= imag_i & ZERO_STUFF;
state_core_next <= CORRIGE_Q_P2;
when CORRIGE_Q_P2 =>
if parte_real(52) = '1' then
temp_parte_real_next <= parte_real;
state_core_next <= CORRIGE_Q_P3;
else
acc_phase_rads_next <= (others => '0');
state_core_next <= CALCULA_CORDIC_P1;
end if;
when CORRIGE_Q_P3 =>
if parte_imaginaria(52) = '0' then
parte_imaginaria_next <= not (temp_parte_real) ;--+ 1;
else
parte_real_next <= not (parte_imaginaria);-- + 1;
end if;
state_core_next <= CORRIGE_Q_P4;
when CORRIGE_Q_P4 =>
if parte_imaginaria(52) = '0' then
parte_real_next <= parte_imaginaria;
parte_imaginaria_next <= parte_imaginaria + 1;
acc_phase_rads_next <= "111111111" & pi_2 & ZERO_STUFF; -- -pi_2
else
parte_real_next <= parte_real + 1;-- + 1;
parte_imaginaria_next <= temp_parte_real;
acc_phase_rads_next <= "000000000" & pi_2 & ZERO_STUFF;
end if;
state_core_next <= CALCULA_CORDIC_P1;
when CALCULA_CORDIC_P1 =>
K_reg_next <= "000000000" & ZERO_STUFF & ganho_indice;
phase_rads_next <= "000000000" & ZERO_STUFF & angulo_indice;
temp_parte_real_next <= parte_real;
state_core_next <= CALCULA_CORDIC_P2;
--tmp_operacoes_reg acc real
--tmp_operacoes_acc_reg acc imaginario
when CALCULA_CORDIC_P2 =>
tmp_mult_im_k_next <= parte_imaginaria * K_reg;
tmp_mult_re_k_next <= temp_parte_real * K_reg;
state_core_next <= CALCULA_CORDIC_P2_1;
when CALCULA_CORDIC_P2_1 =>
if tmp_mult_im_k(105) = '0' then
tmp_mult_im_k_next <= ZERO_STUFF & tmp_mult_im_k(105 downto ZERO_STUFF'length);
tmp_mult_re_k_next <= ZERO_STUFF & tmp_mult_re_k(105 downto ZERO_STUFF'length) ;
else
tmp_mult_im_k_next <= ONE_STUFF & tmp_mult_im_k(105 downto ZERO_STUFF'length);
tmp_mult_re_k_next <= ONE_STUFF & tmp_mult_re_k(105 downto ZERO_STUFF'length) ;
end if;
state_core_next <= CALCULA_CORDIC_P3;
when CALCULA_CORDIC_P3 =>
if parte_imaginaria(52) = '0' then
tmp_operacoes_reg_next <= parte_real + tmp_mult_im_k;
tmp_operacoes_acc_reg_next <= parte_imaginaria - tmp_mult_re_k;
acc_phase_rads_next <= acc_phase_rads - phase_rads;
else
tmp_operacoes_reg_next <= parte_real - tmp_mult_im_k;
tmp_operacoes_acc_reg_next <= parte_imaginaria + tmp_mult_re_k;
acc_phase_rads_next <= acc_phase_rads + phase_rads;
end if;
state_core_next <= CALCULA_CORDIC_P4;
when CALCULA_CORDIC_P4 =>
if tmp_operacoes_reg(52) = '0' then
parte_real_next <= ZERO_STUFF & tmp_operacoes_reg(52 downto ZERO_STUFF'length);
else
parte_real_next <= ONE_STUFF & tmp_operacoes_reg(52 downto ZERO_STUFF'length);
end if;
if tmp_operacoes_acc_reg(52) = '0' then
parte_imaginaria_next <= ZERO_STUFF & tmp_operacoes_acc_reg(52 downto ZERO_STUFF'length);
else
parte_imaginaria_next <= ONE_STUFF & tmp_operacoes_acc_reg(52 downto ZERO_STUFF'length);
end if;
state_core_next <= CALCULA_CORDIC_P5;
when CALCULA_CORDIC_P5 =>
if indice < 24 then
indice_next <= indice + 1;
indice_2_next <= indice_2 + 1;
state_core_next <= CALCULA_CORDIC_P6;
elsif indice = 24 then
state_core_next <= FIM_P1;
end if;
when CALCULA_CORDIC_P6 =>
state_core_next <= CALCULA_CORDIC_P1;
when FIM_P1 =>
fase_o_reg_next <= not (ZERO_STUFF & acc_phase_rads(52 downto 21));
-- mag_o_reg_next <= parte_real;
-- finish_cordic <= '1';
state_core_next <= FIM_P2;
when FIM_P2 =>
fase_o_reg_next <= fase_o_reg + 1;
mag_o_reg_next <= parte_real;
finish_cordic_reg_next <= '1';
state_core_next <= INIT;
when others =>
state_core_next <= INIT;
end case;
end process;
end rtl_cordic;
any help is really welcome, i am having problem with negative angles in the middle of my calculos...