LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.all;
USE IEEE.STD_LOGIC_UNSIGNED.all;
entity cordic is
generic (steps : Integer := 9);
port (
clk : in std_logic;
clr : in std_logic;
validi : in std_logic;
w : in std_logic_vector(6 downto 0); -- 0 to 90 deg
valido : out std_logic;
sin : out std_logic_vector(7 downto 0); -- 0 to 255
cos : out std_logic_vector(7 downto 0)); -- 0 to 255
end cordic;
architecture a of cordic is
type angle_arr is array (0 to 9) of Integer range 0 to 511;
constant angles : angle_arr := (360, 213, 112, 57, 29, 14, 7, 4, 2, 1);
constant x_ini : Integer := 620;
subtype xy_type is Integer range -1024 to 1023;
subtype w_type is Integer range -1024 to 1023;
type xy_arr is array(0 to steps) of xy_type;
type w_arr is array(0 to steps) of w_type;
signal angle : w_arr;
signal x, y : xy_arr;
signal sin_i, cos_i : Integer range 0 to 255;
signal valid : std_logic_vector(0 to steps);
begin
process(clk)
begin
if rising_edge(clk) then
if clr='1' then
for i in 0 to steps loop
x(i) <= 0;
y(i) <= 0;
angle(i) <= 0;
end loop;
x(0) <= x_ini;
valid <= (others => '0');
valido <= '0';
else
angle(0) <= conv_integer('0' & w)*8;
valid(0) <= validi;
for i in 1 to steps loop
valid(i) <= valid(i-1);
if angle(i-1) > 0 then
x(i) <= x(i-1) - y(i-1)/2**(i-1);
y(i) <= y(i-1) + x(i-1)/2**(i-1);
angle(i) <= angle(i-1) - angles(i-1);
else
x(i) <= x(i-1) + y(i-1)/2**(i-1);
y(i) <= y(i-1) - x(i-1)/2**(i-1);
angle(i) <= angle(i-1) + angles(i-1);
end if;
end loop;
valido <= valid(steps);
if x(steps) < 0 then cos_i <= 0;
else cos_i <= x(steps)/4; end if;
if y(steps) < 0 then sin_i <= 0;
else sin_i <= y(steps)/4; end if;
end if;
end if;
end process;
cos <= conv_std_logic_vector(cos_i, cos'length);
sin <= conv_std_logic_vector(sin_i, sin'length);
end;