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.