CORDIC yani COordinate Rotation DIgital Computer, bilgisayarlarda kullanılan ve trigonometrik fonksiyonları kısa yoldan en az hata ile hesaplamada kullanılan bir algoritmadır. Algoritmanın temeli, bir noktanın orjin etrafında gitgide azalan bir açı ile döndürülmesinden gelir. , dönüşüm matrisi olmak üzere yapılan işlemleri matematiksel olarak şu şekilde yazabiliriz:
Dönüşüm matrisindeki ve
ifadelerini
cinsinden yazalım.
Elimizde olmak üzere
ve
değerlerinden oluşan tablolarımız olsun. Bu tabloları kullanarak istediğimiz değerdeki
ve
değerlerini bulabiliriz.
Burada dönmenin yönünü belirtir.
ya da
değerlerinden birini alabilir. Bu işlemler ne kadar tekrar edilirse istenilen
ve
değerlerine o kadar yaklaşılır.
Bilgisayarlarda çarpma işlemi yapmak, kaydırma işlemi yapmaktan daha fazla zaman harcar. Bu yüzden yerine işlemleri daha kolay hesaplanabilecek hale getiren
ifadesini yazalım ve
değerlerini bir tabloda saklayalım.
Her işlemde değerini tekrar tekrar çarpmak yerine en son belirli iterasyon değeri için hesaplanmış
ile çarparak işlemleri bitirebiliriz.
değeri için
ve
fonksiyonlarını
iterasyonda hesaplamaya çalışalım.
Burada hesaplanan gerçek açıdır. Yaptığımız işlemler koordinat sisteminde aşağıdaki gibi olacaktır:
Kullanılacak sayı formatı ve
için
, açı için
olarak seçilmiştir. Donanımın tasarımı aşağıdaki gibi olacaktır:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity CORDIC is port(Clk, Reset, S : in std_logic; --Clock, Reset ve S girişleri Angle : in std_logic_vector(15 downto 0); --Hesaplanacak yeni açı girişi Sin, Cos : out std_logic_vector(15 downto 0)); --Sin, Cos çıkışları end CORDIC; architecture Behavioral of CORDIC is --Shifter component ArithmeticShifter port(DataIn : in std_logic_vector(15 downto 0); i : in std_logic_vector(3 downto 0); DataOut : out std_logic_vector(15 downto 0)); end component; --Toplayıcı-Çıkarıcı component Adder generic(W : integer := 8); port(Sigma : in std_logic; A, B : in std_logic_vector(W - 1 downto 0); O : out std_logic_vector(W - 1 downto 0)); end component; --Çarpıcı(Q15 x Q15 = Q30) component Multiplier port(A, B : in std_logic_vector(15 downto 0); O : out std_logic_vector(31 downto 0)); end component; --Register component Reg generic(ResetValue : std_logic_vector(15 downto 0) := X"00"); port(Clk, Reset : in std_logic; DataIn : in std_logic_vector(15 downto 0); DataOut : out std_logic_vector(15 downto 0)); end component; signal XiIn, XiOut : std_logic_vector(15 downto 0); signal XiShifterOut : std_logic_vector(15 downto 0); signal XiMultiplierOut : std_logic_vector(31 downto 0); signal YiIn, YiOut : std_logic_vector(15 downto 0); signal YiShifterOut : std_logic_vector(15 downto 0); signal YiMultiplierOut : std_logic_vector(31 downto 0); signal atanLUTOut : std_logic_vector(15 downto 0); signal AngleOut, AngleIn : std_logic_vector(15 downto 0); signal AngleAdderOut : std_logic_vector(15 downto 0); signal Sigma : std_logic; signal i : std_logic_vector(3 downto 0) := X"0"; signal CounterAdderOut : std_logic_vector(3 downto 0); begin --Xi Registeri --Reset Değeri = 1 (UQ1.15) Xi : Reg generic map(X"8000") port map(Clk, Reset, XiIn, XiOut); --Xi için shifter XShifter : ArithmeticShifter port map(XiOut, i, XiShifterOut); --Xi için Toplayıcı çıkarıcı Adder1 : Adder generic map(16) port map(Sigma, YiOut, XiShifterOut, YiIn); --Yi Registeri --Reset Değeri = 0 (UQ1.15) Yi : Reg generic map(X"0000") port map(Clk, Reset, YiIn, YiOut); --Yi için shifter YShifter : ArithmeticShifter port map(YiOut, i, YiShifterOut); --Yi için Toplayıcı çıkarıcı Adder2 : Adder generic map(16) port map(not Sigma, XiOut, YiShifterOut, XiIn); --Xi ve Yi'yi K katsayısı ile çarp XiMultiplier : Multiplier port map(XiOut, X"4DBA", XiMultiplierOut); YiMultiplier : Multiplier port map(YiOut, X"4DBA", YiMultiplierOut); --Q30 -> Q15 için shift işlemi Shift : for j in 0 to 15 generate Sin(j) <= YiMultiplierOut(j + 15); Cos(j) <= XiMultiplierOut(j + 15); end generate; --Açı Registeri AngleRegister : Reg generic map(X"0000") port map(Clk, Reset, AngleIn, AngleOut); AngleAdder : Adder generic map(16) port map(not Sigma, AngleOut, atanLUTOut, AngleAdderOut); --Yeni açı girmek için multiplexer with S select AngleIn <= AngleAdderOut when '0', Angle when others; --Açının işaret bitini Sigma <= AngleOut(15); --Atan tablosu (Q1.14) with i select atanLUTOut <= X"3201" when X"0", X"1DAC" when X"1", X"0FAD" when X"2", X"07F5" when X"3", X"03FE" when X"4", X"0200" when X"5", X"0100" when X"6", X"0080" when X"7", X"0040" when X"8", X"0020" when X"9", X"0010" when X"A", X"0008" when X"B", X"0004" when X"C", X"0002" when X"D", X"0001" when X"E", X"0000" when others; --Counter CounterAdder : Adder generic map(4) port map('0', i, X"1", CounterAdderOut); process(Reset, Clk) begin if Reset = '1' then i <= X"0"; elsif rising_edge(Clk) then i <= CounterAdderOut; end if; end process; end Behavioral;
Tasarımın diğer dosyalarına buradan ulaşabilirsiniz.