VHDL ile tasarladığım CORDIC modülü. Bu ilk sürümde bazı hatalar/sorunlar çıkabilir. İleride bu modülü çalışmalarımda kullandıkça düzeltmeyi düşünüyorum. ‘pi’den daha büyük döndürme değerleri için düzgün çalışmadığını gözlemledim. Sanırım matematiksel işlemlerde bir sorun var.
Not: Kodda iki basit hata buldum. Kısa zamanda çözmeye çalışacağım. Çıkışın genliği yanlış geliyor. Açı da sorun yok.
Kodda çok bariz bir hata vardı. CORDIC’te her kademe atan(2^(-i)) kadar döndürme yapabiliyor. İlk kademe 45 derece olan atan(2^0) ile başlıyor. Ben yanlışlıkla ilk kademeyi atan(2^-1)’den (yaklaşık 26 derece) başlatmıştım. Kademeler ilerledikçe açı küçüldüğü için modül toplamda 90 derece bir dönme yapamıyor. Bunu çözmek için başlangıca ekstradan iki adet atan(2^-1)’lik kademe ekledim (Kafam nerdeyse!). Bu da işleri iyice karıştırdı. Şimdi o kademeleri kaldırdım. İlk kademeyi i=0’dan başlattım. Sorun ortadan kalktı.
Dosyayı indirmek için tıklayın.
/* CORDIC module by Hasan Yavuz ÖZDERYA ( hy [at] ozderya.net ) Trabzon KTU DSPLAB 2013 v0.2 , 08.04.2013 : corrected barely wrong implementation v0.1 , 19.03.2013 */ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; use ieee.fixed_pkg.all; /* Main CORDIC module */ entity cordic is Generic(n:integer := 16; -- bus width (n=16 -> Q.15), internals work with Q1.15 ns:integer := 10); -- number of stages Port( rotation: in sfixed(3 downto -(n-4)); -- rotation input d_r : in sfixed(0 downto -(n-1)); -- inputs d_c : in sfixed(0 downto -(n-1)); q_r : out sfixed(0 downto -(n-1)); -- outputs q_c : out sfixed(0 downto -(n-1)); clk : in std_logic; reset : in std_logic ); subtype tfixed is sfixed(1 downto -(n-1)); -- type used for internals subtype rtfixed is sfixed(3 downto -(n-4)); -- type used for radians end entity cordic; architecture single_unit of cordic is -- first stage (#-1,jumper stage) rotates 90|180|270 degree if required type tfixed_array is array(-1 to ns-1) of tfixed; type rtfixed_array is array(-1 to ns-1) of rtfixed; type rtfixed_array2 is array(0 to ns-1) of rtfixed; -- stage input output signals signal s_beta,s_phi, -- phi: target rotation s_beta_o,s_phi_o : rtfixed_array; -- beta: rotation so far signal s_d_r, s_d_c, -- d_r,d_c: stage input real and complex s_q_r, s_q_c : tfixed_array; -- q_r,q_c: stage output real and complex -- constants signal atans : rtfixed_array2; -- holds arctangents of 2^-i (i=0,1,2..) constant c_K : tfixed := to_sfixed(0.607253031529134,1,-(n-1)); constant pi_3_2 : rtfixed := to_sfixed(MATH_3_PI_OVER_2,3, -(n-4)); constant pi : rtfixed := to_sfixed(MATH_PI,3, -(n-4)); constant pi_1_2 : rtfixed := to_sfixed(MATH_PI_OVER_2,3, -(n-4)); constant pi_1_4 : rtfixed := to_sfixed(MATH_PI_OVER_4,3, -(n-4)); begin -- generate required constants for iterative stages atan(2^-i) gen_atans: for i in 0 to ns-1 generate constant c_atan : real := arctan(2.0**(-i)); begin atans(i) <= to_sfixed(c_atan,rotation); end generate; -- generate intertal connections between stages gen_internals:for i in 0 to ns-1 generate -- except first stage which is input s_beta(i) <= s_beta_o(i-1); s_phi(i) <= s_phi_o(i-1); s_d_r(i) <= s_q_r(i-1); s_d_c(i) <= s_q_c(i-1); end generate; process(clk) variable a,b,p,k : tfixed; variable beta,phi : rtfixed; begin if reset = '1' then q_r <= to_sfixed(0,q_r); q_c <= to_sfixed(0,q_c); s_beta_o <= (others => to_sfixed(0,q_r)); s_phi_o <= (others => to_sfixed(0,q_r)); s_q_r <= (others => to_sfixed(0,q_r)); s_q_c <= (others => to_sfixed(0,q_r)); elsif rising_edge(clk) then -- register inputs for first stage s_beta(-1) <= to_sfixed(0,d_r); s_phi(-1) <= rotation; s_d_r(-1) <= resize(d_r,a); s_d_c(-1) <= resize(d_c,a); for i in -1 to ns-1 loop a := s_d_r(i); b := s_d_c(i); beta := s_beta(i); phi := s_phi(i); if i=-1 then -- jumper stage for r>pi/2 if phi > pi_3_2 then p := b; k := resize(-a,a); phi := resize(phi-pi_3_2,phi); elsif phi > pi then p := resize(-a,a); k := resize(-b,a); phi := resize(phi-pi,phi); elsif phi > pi_1_2 then p := resize(-b,a); k := a; phi := resize(phi-pi_1_2,phi); else p := a; k := b; end if; else -- iterative stages if phi>beta then p := resize(a-scalb(b,-i),a); -- scalb shifts number k := resize(b+scalb(a,-i),a); -- does binary division beta := resize(beta+atans(i),beta); else p := resize(a+scalb(b,-i),a); k := resize(b-scalb(a,-i),a); beta := resize(beta-atans(i),beta); end if; end if; s_q_r(i) <= p; s_q_c(i) <= k; s_beta_o(i) <= beta; s_phi_o(i) <= phi; end loop; -- last stage to output (notice 'c_K' scaler) q_r <= resize(c_K*s_q_r(ns-1),q_r); q_c <= resize(c_K*s_q_c(ns-1),q_r); end if; end process; end single_unit;