Vektörel dairesel açı dönüşüm işlemlerinde temel amaç yazımızda verilen ilk denklemde tanımlanan değişkeni değerini sıfıra yaklaştırmaktır .
Başlangıç değerleri ve
seçildiği durumda kartezyen koordinat değerlerimin polar koordinat değerlerine dönüşümü yapılmaktadır .

ki parametresi aşağıdaki gibi hesaplanmaktadır.

Aşağıda vektörel modda genlik ve açı değerlerini hesplayan VHDL kodları verilmiştir.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.MATH_REAL.ALL;
entity cordic_rec2pol is
generic(
ITERTATION : integer := 20;
VALUE_SIZE : integer := 20;
MUL_COEFF : integer := 18; -- 2^MULL_COEFF;
DATA_SIZE : integer := 24 -- DATA_SIZE > MUL_COEFF +2
);
port(
in_clk : in std_logic;
in_rst : in std_logic;
in_strt : in std_logic;
in_data_real : in std_logic_vector(DATA_SIZE - 1 downto 0);
in_data_imag : in std_logic_vector(DATA_SIZE - 1 downto 0);
out_data_r : out std_logic_vector(DATA_SIZE - 1 downto 0);
out_data_phase : out std_logic_vector(DATA_SIZE - 1 downto 0);
out_data_vld : out std_logic
);
end cordic_rec2pol;
architecture Behavioral of cordic_rec2pol is
constant c_PI : real := 3.14159_26535_89793_23846;
type t_Cordic_values is array (0 to VALUE_SIZE - 1) of real;
type t_Std_Logic_Vector_data is array (0 to VALUE_SIZE - 1) of std_logic_vector(DATA_SIZE - 1 downto 0);
type t_Int_data is array (0 to VALUE_SIZE - 1) of integer;
function f_Conv_Real_to_Int(r_Cordic_values : t_Cordic_values; VALUE_SIZE, MUL_COEFF : integer ) return t_Int_data is
variable v_Int_data : t_Int_data;
begin
for n_i in 0 to VALUE_SIZE - 1 loop
v_Int_data(n_i) := integer(r_Cordic_values(n_i) * real(2**MUL_COEFF));
end loop;
return v_Int_data;
end f_Conv_Real_to_Int;
function f_Conv_Int_to_Std_Logic_Vector(r_Int_values : t_Int_data; VALUE_SIZE, DATA_SIZE : integer ) return t_Std_Logic_Vector_data is
variable v_Std_Logic_Vector_data : t_Std_Logic_Vector_data;
begin
for n_i in 0 to VALUE_SIZE - 1 loop
v_Std_Logic_Vector_data(n_i) := conv_std_logic_vector(r_Int_values(n_i), DATA_SIZE);
end loop;
return v_Std_Logic_Vector_data;
end f_Conv_Int_to_Std_Logic_Vector;
-- ****
function f_Calc_tp_values(VALUE_SIZE : integer) return t_Cordic_values is
variable v_tp_values : t_Cordic_values;
begin
v_tp_values(0) := 1.0;
v_tp_values(1) := 1.0;
v_tp_values(2) := 1.0;
for n_i in 3 to VALUE_SIZE - 1 loop
v_tp_values(n_i) := v_tp_values(n_i - 1) / 2.0;
end loop;
return v_tp_values;
end f_Calc_tp_values;
constant c_tp_values : t_Cordic_values := f_Calc_tp_values(VALUE_SIZE);
constant c_tp_int_values : t_Int_data := f_Conv_Real_to_Int(c_tp_values, VALUE_SIZE, MUL_COEFF);
constant c_tp_std_values : t_Std_Logic_Vector_data := f_Conv_Int_to_Std_Logic_Vector(c_tp_int_values, VALUE_SIZE, DATA_SIZE);
-- ****
-- ****
function f_Calc_atantp_values(c_tp_values : t_Cordic_values ;VALUE_SIZE : integer) return t_Cordic_values is
variable v_atantp_values : t_Cordic_values;
begin
v_atantp_values(0) := c_PI / 4.0;
v_atantp_values(1) := c_PI / 4.0;
v_atantp_values(2) := c_PI / 4.0;
for n_i in 3 to VALUE_SIZE - 1 loop
v_atantp_values(n_i) := arctan(c_tp_values(n_i));
end loop;
return v_atantp_values;
end f_Calc_atantp_values;
constant c_atantp_values : t_Cordic_values := f_Calc_atantp_values(c_tp_values, VALUE_SIZE);
constant c_atantp_int_values : t_Int_data := f_Conv_Real_to_Int(c_atantp_values, VALUE_SIZE, MUL_COEFF);
constant c_atantp_std_values : t_Std_Logic_Vector_data := f_Conv_Int_to_Std_Logic_Vector(c_atantp_int_values, VALUE_SIZE, DATA_SIZE);
-- ****
-- ****
function f_Calc_K_values(c_atantp_values : t_Cordic_values; VALUE_SIZE : integer) return real is
variable v_K : real;
begin
v_K := sqrt(2.0) / 4.0;
for n_i in 3 to VALUE_SIZE - 1 loop
v_K := v_K * cos(c_atantp_values(n_i));
end loop;
return v_K;
end f_Calc_K_values;
constant c_K : real := f_Calc_K_values(c_atantp_values, VALUE_SIZE);
constant c_K_std : std_logic_vector(DATA_SIZE - 1 downto 0) := conv_std_logic_vector(integer(c_K * real(2**MUL_COEFF)), DATA_SIZE);
-- ****
type t_Cordic_Cntrl is (IDLE, SET_TX, MUL_PARAM, ADD_PARAM, CHK_ITER, MUL_CONSTANT, DONE);
signal r_Cordic_Cntrl : t_Cordic_Cntrl := IDLE;
signal r_Z : std_logic_vector(DATA_SIZE - 1 downto 0) := (others => '0');
signal r_TX : std_logic_vector(DATA_SIZE - 1 downto 0) := (others => '0');
signal r_data_real : std_logic_vector(DATA_SIZE - 1 downto 0) := (others => '0');
signal r_data_r : std_logic_vector(DATA_SIZE - 1 downto 0) := (others => '0');
signal r_data_real_mul : std_logic_vector(2 * DATA_SIZE - 1 downto 0) := (others => '0');
signal r_data_real_add : std_logic_vector(2 * DATA_SIZE - 1 downto 0) := (others => '0');
signal r_data_imag : std_logic_vector(DATA_SIZE - 1 downto 0) := (others => '0');
signal r_data_phase : std_logic_vector(DATA_SIZE - 1 downto 0) := (others => '0');
signal r_data_imag_add : std_logic_vector(2 * DATA_SIZE - 1 downto 0) := (others => '0');
signal n_i : integer range 0 to VALUE_SIZE := 0;
signal r_data_vld : std_logic := '0';
begin
out_data_r <= r_data_r;
out_data_phase <= r_data_phase;
out_data_vld <= r_data_vld;
process(in_clk, in_rst, in_strt)
begin
if in_rst = '1' then
r_Cordic_Cntrl <= IDLE;
r_Z <= (others => '0');
r_TX <= (others => '0');
r_data_real <= (others => '0');
r_data_r <= (others => '0');
r_data_real_add <= (others => '0');
r_data_real_mul <= (others => '0');
r_data_imag <= (others => '0');
r_data_phase <= (others => '0');
r_data_imag_add <= (others => '0');
r_data_vld <= '0';
n_i <= 0;
elsif rising_edge(in_clk) then
r_data_vld <= '0';
case r_Cordic_Cntrl is
when IDLE =>
if in_strt = '1' then
r_Z <= (others => '0');
r_TX <= (others => '0');
r_data_real <= in_data_real;
r_data_imag <= in_data_imag;
n_i <= 0;
r_Cordic_Cntrl <= SET_TX;
end if;
when SET_TX =>
r_TX <= r_data_real;
r_Cordic_Cntrl <= MUL_PARAM;
when MUL_PARAM =>
r_data_real_add <= r_data_imag * c_tp_std_values(n_i);
r_data_imag_add <= r_TX * c_tp_std_values(n_i);
r_Cordic_Cntrl <= ADD_PARAM;
when ADD_PARAM =>
if r_data_imag(r_data_imag'high) = '1' then
r_data_real <= r_data_real - r_data_real_add(MUL_COEFF + DATA_SIZE - 1 downto MUL_COEFF);
r_data_imag <= r_data_imag + r_data_imag_add(MUL_COEFF + DATA_SIZE - 1 downto MUL_COEFF);
r_Z <= r_Z - c_atantp_std_values(n_i);
else
r_data_real <= r_data_real + r_data_real_add(MUL_COEFF + DATA_SIZE - 1 downto MUL_COEFF);
r_data_imag <= r_data_imag - r_data_imag_add(MUL_COEFF + DATA_SIZE - 1 downto MUL_COEFF);
r_Z <= r_Z + c_atantp_std_values(n_i);
end if;
r_Cordic_Cntrl <= CHK_ITER;
when CHK_ITER =>
if n_i = ITERTATION - 1 then
n_i <= 0;
r_Cordic_Cntrl <= MUL_CONSTANT;
else
n_i <= n_i + 1;
r_Cordic_Cntrl <= SET_TX;
end if;
when MUL_CONSTANT =>
r_data_real_mul <= r_data_real * c_K_std;
r_Cordic_Cntrl <= DONE;
when DONE =>
r_data_vld <= '1';
r_data_r <= r_data_real_mul(MUL_COEFF + DATA_SIZE - 1 downto MUL_COEFF);
r_data_phase <= r_Z;
r_Cordic_Cntrl <= IDLE;
when others => NULL;
end case;
end if;
end process;
end Behavioral;
Aşağıda vektörel modda genlik ve açı değerlerini hesaplayan cordic_rec2pol.vhd VHDL kodunun benzetimini yapılabilmesi için oluşturulmuş sınama kodları verilmiştir.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.MATH_REAL.ALL;
entity tb_cordic_rec_pol is
end tb_cordic_rec_pol;
architecture Behavioral of tb_cordic_rec_pol is
component cordic_rec2pol
generic(
ITERTATION : integer := 2;
VALUE_SIZE : integer := 8;
MUL_COEFF : integer := 12; -- 2^MULL_COEFF;
DATA_SIZE : integer := 16 -- DATA_SIZE > MUL_COEFF +2
);
port(
in_clk : in std_logic;
in_rst : in std_logic;
in_strt : in std_logic;
in_data_real : in std_logic_vector(DATA_SIZE - 1 downto 0);
in_data_imag : in std_logic_vector(DATA_SIZE - 1 downto 0);
out_data_r : out std_logic_vector(DATA_SIZE - 1 downto 0);
out_data_phase : out std_logic_vector(DATA_SIZE - 1 downto 0);
out_data_vld : out std_logic
);
end component;
constant CLK_PERIOD : time := 10 ns;
constant r_PI : real := 3.14159_26535_89793_23846;
constant ITERTATION : integer := 24;
constant VALUE_SIZE : integer := 24;
constant MUL_COEFF : integer := 24; -- 2^MULL_COEFF;
constant DATA_SIZE : integer := 30; -- DATA_SIZE > MUL_COEFF +2
signal in_clk : std_logic := '0';
signal in_strt : std_logic := '0';
signal in_data_real : std_logic_vector(DATA_SIZE - 1 downto 0);
signal in_data_imag : std_logic_vector(DATA_SIZE - 1 downto 0);
signal n_i : integer := 0;
signal r_data_r : std_logic_vector(DATA_SIZE - 1 downto 0) := (others => '0');
signal r_data_phase : std_logic_vector(DATA_SIZE - 1 downto 0) := (others => '0');
signal r_data_vld : std_logic := '0';
type t_Cntrl is (SET_TETA,WAIT_DATA, DONE );
signal r_Cntrl : t_Cntrl := SET_TETA;
signal r_data_r_real : real := 0.0;
signal r_data_phase_real : real := 0.0;
signal r_mse_mag : real := 0.0;
signal r_mse_teta : real := 0.0;
begin
process
begin
in_clk <= '1';
wait for CLK_PERIOD / 2;
in_clk <= '0';
wait for CLK_PERIOD / 2;
end process;
process(in_clk)
begin
if rising_edge(in_clk) then
in_strt <= '0';
case r_Cntrl is
when SET_TETA =>
in_data_real <= conv_std_logic_vector( integer(real(n_i) / 5.0 * real(2**MUL_COEFF)), DATA_SIZE);
in_data_imag <= conv_std_logic_vector( integer(real(5 - n_i) / 5.0 * real(2**MUL_COEFF)), DATA_SIZE);
in_strt <= '1';
r_Cntrl <= WAIT_DATA;
when WAIT_DATA =>
if r_data_vld = '1' then
r_data_r_real <= real(conv_integer(r_data_r)) / real(2**MUL_COEFF);
r_data_phase_real <= real(conv_integer(r_data_phase)) / real(2**MUL_COEFF);
r_mse_mag <= r_mse_mag + (sqrt((real(n_i)/5.0)**2 + (real(5 - n_i) / 5.0)**2) -
(real(conv_integer(r_data_r)) / real(2**MUL_COEFF)))**2.0 / 6.0;
r_mse_teta <= r_mse_teta + (arctan(real(5 - n_i), real(n_i)) -
(real(conv_integer(r_data_phase)) / real(2**MUL_COEFF)))**2.0 / 6.0;
if n_i = 5 then
r_Cntrl <= DONE;
n_i <= 0;
else
r_Cntrl <= SET_TETA;
n_i <= n_i + 1;
end if;
end if;
when DONE =>
null;
when OTHERS => NULL;
end case;
end if;
end process;
cordic_rec2pol_map : cordic_rec2pol generic map(
ITERTATION => VALUE_SIZE,
VALUE_SIZE => VALUE_SIZE,
MUL_COEFF => MUL_COEFF, -- 2^MULL_COEFF;
DATA_SIZE => DATA_SIZE -- DATA_SIZE > MUL_COEFF + 2
)
port map(
in_clk => in_clk,
in_rst => '0',
in_strt => in_strt,
in_data_real => in_data_real,
in_data_imag => in_data_imag,
out_data_r => r_data_r,
out_data_phase => r_data_phase,
out_data_vld => r_data_vld
);
end Behavioral;
NOT: Bu yazıda, Suhap ŞAHİN, Burcu Kır Savaş, “Jenerik CORDIC Algoritmasının FPGA’DA Donanımsal Gerçeklenmesi”, Sakarya Üniversitesi Fen Bilimleri Enstitüsü Dergisi, 27 (1), 2017, çalışmadan direk alıntı yapılmış ve faydalanılmıştır. Kendisinin izni ile konu anlatımında bilgiler kullanılmıştır.