library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.all;
entity Bresenhamer is
    Port ( WriteEnable : out  STD_LOGIC;
           X : out  STD_LOGIC_VECTOR (9 downto 0);
           Y : out  STD_LOGIC_VECTOR (8 downto 0);
           X1 : in  STD_LOGIC_VECTOR (9 downto 0);
           Y1 : in  STD_LOGIC_VECTOR (8 downto 0);
           X2 : in  STD_LOGIC_VECTOR (9 downto 0);
           Y2 : in  STD_LOGIC_VECTOR (8 downto 0);
			  SS : out  STD_LOGIC_VECTOR (3 downto 0);
			  Clk : in STD_LOGIC;
           StartDraw : in  STD_LOGIC;
			  dbg : out  STD_LOGIC_VECTOR (11 downto 0);
			  Reset : in  STD_LOGIC);
end Bresenhamer;
architecture Behavioral of Bresenhamer is
signal myX1,myX2 : STD_LOGIC_VECTOR (11 downto 0);
signal myY1,myY2 : STD_LOGIC_VECTOR (11 downto 0);
signal p,p0_1,p0_2,p0_3,p0_4,p0_5,p0_6,p0_7,p0_8 : STD_LOGIC_VECTOR (11 downto 0);
signal p_1,p_2,p_3,p_4,p_5,p_6,p_7,p_8 : STD_LOGIC_VECTOR (11 downto 0);
signal ndx,ndy : STD_LOGIC_VECTOR (11 downto 0);
signal dx,dy,t_2dx,t_2dy,neg_dx,neg_dy,t_2neg_dx,t_2neg_dy : STD_LOGIC_VECTOR (11 downto 0);
signal dx_minus_dy : STD_LOGIC_VECTOR (11 downto 0);
signal minus_dx_minus_dy : STD_LOGIC_VECTOR (11 downto 0);
signal minus_dx_plus_dy : STD_LOGIC_VECTOR (11 downto 0);
signal dx_plus_dy : STD_LOGIC_VECTOR (11 downto 0);
signal State : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal condX1X2,condY1Y2 : STD_LOGIC;
signal ccounter : STD_LOGIC_VECTOR (18 downto 0) := "0000000000000000000";

constant IDLE : STD_LOGIC_VECTOR(3 downto 0) := "0000";
constant INIT : STD_LOGIC_VECTOR(3 downto 0) := "0001";
constant CASE1 : STD_LOGIC_VECTOR(3 downto 0) := "0010";
constant CASE2 : STD_LOGIC_VECTOR(3 downto 0) := "0011";
constant CASE3 : STD_LOGIC_VECTOR(3 downto 0) := "0100";
constant CASE4 : STD_LOGIC_VECTOR(3 downto 0) := "0101";
constant CASE5 : STD_LOGIC_VECTOR(3 downto 0) := "0110";
constant CASE6 : STD_LOGIC_VECTOR(3 downto 0) := "0111";
constant CASE7 : STD_LOGIC_VECTOR(3 downto 0) := "1000";
constant CASE8 : STD_LOGIC_VECTOR(3 downto 0) := "1001";
constant CLEAR : STD_LOGIC_VECTOR(3 downto 0) := "1010";
begin
ndx <= ("00" & X2)-("00" & X1);
ndy <= ("000" & Y2)-("000" & Y1);
neg_dx <= 0-dx;
neg_dy <= 0-dy;
dbg <= p;
dx_minus_dy <= dx+neg_dy;
minus_dx_minus_dy <= neg_dx+neg_dy;
minus_dx_plus_dy <= neg_dx+dy;
dx_plus_dy <= dx+dy;
t_2dy <= dy(10 downto 0) & '0';
t_2dx <= dx(10 downto 0) & '0';
t_2neg_dy <= neg_dy(10 downto 0) & '0';
t_2neg_dx <= neg_dx(10 downto 0) & '0';
p0_1 <= t_2dy+neg_dx;
p0_2 <= t_2dx+neg_dy;
p0_3 <= t_2neg_dx+dy;
p0_4 <= t_2dy+neg_dx;
p0_5 <= t_2neg_dy+dx;
p0_6 <= t_2neg_dx+dy;
p0_7 <= t_2dx+neg_dy;
p0_8 <= t_2neg_dy+dx;
p_1 <= p+t_2dy when p(11)='1' else p+t_2dy+t_2neg_dx;
p_2 <= p+t_2dx when p(11)='1' else p+t_2dx+t_2neg_dy;
p_3 <= p+t_2neg_dx when p(11)='1' else p+t_2neg_dx+t_2neg_dy;
p_4 <= p+t_2dy when p(11)='1' else p+t_2dy+t_2dx;
p_5 <= p+t_2neg_dy when p(11)='1' else p+t_2neg_dy+t_2dx;
p_6 <= p+t_2neg_dx when p(11)='1' else p+t_2neg_dx+t_2dy;
p_7 <= p+t_2dx when p(11)='1' else p+t_2dx+t_2dy;
p_8 <= p+t_2neg_dy when p(11)='1' else p+t_2neg_dy+t_2neg_dx;
X <= ccounter(9 downto 0) when State = CLEAR else myX1(9 downto 0);
Y <= ccounter(18 downto 10) when State = CLEAR else myY1(8 downto 0);
SS <= State;
WriteEnable <= '0' when State = IDLE or State = INIT else '1';
process (Clk) begin
	if (rising_edge(Clk)) then
		if (State = IDLE) then
			if (Reset = '1') then
				State <= CLEAR;
				ccounter <= (others=>'0');
			elsif (StartDraw = '1') then
				myX1(9 downto 0) <= X1;
				myX1(11 downto 10) <= "00";
				myY1(8 downto 0) <= Y1;
				myY1(11 downto 9) <= "000";
				myX2(9 downto 0) <= X2;
				myX2(11 downto 10) <= "00";
				myY2(8 downto 0) <= Y2;
				myY2(11 downto 9) <= "000";
				dx <= ndx;
				dy <= ndy;
				State <= INIT;
			end if;
		elsif (State = INIT) then
			if (dx(11) = '0' and dy(11) = '0' and dx_minus_dy(11) = '0') then
				State <= CASE1;
				p <= p0_1;
			elsif (dx(11) = '0' and dy(11) = '0' and dx_minus_dy(11) = '1') then
				State <= CASE2;
				p <= p0_2;
			elsif (dx(11) = '1' and dy(11) = '0' and minus_dx_minus_dy(11) = '1') then
				State <= CASE3;
				p <= p0_3;
			elsif (dx(11) = '1' and dy(11) = '0' and minus_dx_minus_dy(11) = '0') then
				State <= CASE4;
				p <= p0_4;
			elsif (dx(11) = '1' and dy(11) = '1' and minus_dx_plus_dy(11) = '0') then
				State <= CASE5;
				p <= p0_5;
			elsif (dx(11) = '1' and dy(11) = '1' and minus_dx_plus_dy(11) = '1') then
				State <= CASE6;
				p <= p0_6;
			elsif (dx(11) = '0' and dy(11) = '1' and dx_plus_dy(11) = '1') then
				State <= CASE7;
				p <= p0_7;
			else
				State <= CASE8;
				p <= p0_8;
			end if;
		elsif (State = CASE1) then
			if (myX1 = myX2) then
				State <= IDLE;
			else
				myX1 <= myX1 + 1;
				p <= p_1;
				if (P(11) = '0') then
					myY1 <= myY1 + 1;
				end if;
			end if;
		elsif (State = CASE2) then
			if (myY1 = myY2) then
				State <= IDLE;
			else
				myY1 <= myY1 + 1;
				p <= p_2;
				if (P(11) = '0') then
					myX1 <= myX1 + 1;
				end if;
			end if;
		elsif (State = CASE3) then
			if (myY1 = myY2) then
				State <= IDLE;
			else
				myY1 <= myY1 + 1;
				p <= p_3;
				if (P(11) = '0') then
					myX1 <= myX1 - 1;
				end if;
			end if;
		elsif (State = CASE4) then
			if (myX1 = myX2) then
				State <= IDLE;
			else
				myX1 <= myX1 - 1;
				p <= p_4;
				if (P(11) = '0') then
					myY1 <= myY1 + 1;
				end if;
			end if;
		elsif (State = CASE5) then
			if (myX1 = myX2) then
				State <= IDLE;
			else
				myX1 <= myX1 - 1;
				p <= p_5;
				if (P(11) = '0') then
					myY1 <= myY1 - 1;
				end if;
			end if;
		elsif (State = CASE6) then
			if (myY1 = myY2) then
				State <= IDLE;
			else
				myY1 <= myY1 - 1;
				p <= p_6;
				if (P(11) = '0') then
					myX1 <= myX1 - 1;
				end if;
			end if;
		elsif (State = CASE7) then
			if (myY1 = myY2) then
				State <= IDLE;
			else
				myY1 <= myY1 - 1;
				p <= p_7;
				if (P(11) = '0') then
					myX1 <= myX1 + 1;
				end if;
			end if;
		elsif (State = CASE8) then
			if (myX1 = myX2) then
				State <= IDLE;
			else
				myX1 <= myX1 + 1;
				p <= p_8;
				if (P(11) = '0') then
					myY1 <= myY1 - 1;
				end if;
			end if;
		elsif (State = CLEAR) then
			ccounter <= ccounter + 1;
			if (ccounter = "1111111111111111111") then
				State <= IDLE;
			end if;
		end if;
	end if;
end process;
end Behavioral;
