----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date: 30.11.2021 10:35:30
-- Design Name: 
-- Module Name: Gene_Snake - Behavioral
-- Project Name: 
-- Target Devices: 
-- Tool Versions: 
-- Description: 
-- 
-- Dependencies: 
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
----------------------------------------------------------------------------------
-- a faire:
--  - faire bouger le snake
--  - ajouter une clk

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity Gene_Snake is
Port ( X : in unsigned (9 downto 0);
       Y : in unsigned (8 downto 0);
       up : in std_logic;
       down : in std_logic;
       left : in std_logic;
       right : in std_logic;
       clk_rapide: in std_logic;
       clk_lente : in std_logic;
       reset: in std_logic;
       snakePresent : out std_logic);
end Gene_Snake;

architecture Behavioral of Gene_Snake is
-- Déclaration des types de données
type coord is array(0 to 39, 0 to 29) of unsigned(10 downto 0);
type direction is (haut, bas, gauche, droite);
type pos is record
    X: unsigned(9 downto 0);
    Y: unsigned(8 downto 0);
    dir: direction;
    isDefined: std_logic;
end record;
type listSnake is array(0 to 1200) of pos;

-- Déclaration des signaux
signal mat: coord;
signal snake: listSnake;
signal snakeHere: std_logic;
signal update: std_logic;
signal current_index: unsigned(10 downto 0);
signal lastSnake: pos;
begin

process(X,Y,mat,reset, snake)
variable ref : unsigned(10 downto 0);
variable position : pos;
begin
    if(reset='0')
    then
--        snake <= (others=>(to_unsigned(1023,10),to_unsigned(511,10)));
        for i in 0 to snake'length-1 loop
            if(i>100 and i<103)
            then
                snake(i).X <= to_unsigned((22+i-101)*16 - 8,10);
                snake(i).Y <= to_unsigned(32-8,9);
                snake(i).dir <= gauche;
                snake(i).isDefined <= '1';
            else
                snake(i).X <= to_unsigned(1023,10);
                snake(i).Y <= to_unsigned(511,9);
                snake(i).dir <= gauche;
                snake(i).isDefined <= '0';
            end if;
        end loop;
        for x in 0 to 39 loop
            for y in 0 to 29 loop
                mat(x,y) <= to_unsigned(y*40+x,11);
            end loop;
        end loop;
    end if;
    
    snakeHere <= '0';
    for dx in -1 to 0 loop
        for dy in -1 to 0 loop
            ref := mat(to_integer(X/16)+dx,to_integer(Y/16)+dy);
            position := snake(to_integer(ref));
            if(position.isDefined= '1') then
                if(X>=position.X-8 and X<=position.X+8 and Y>=position.Y-8 and Y<=position.Y+8) then
                    snakeHere <= snakeHere or '1';
                end if;
            end if;
         end loop;
     end loop;
end process;

-- On change la position (X et Y) d'une case du snake à chaque coup
-- d'horloge de clk_rapide.
--process(snake, clk_lente, clk_rapide, update, current_index)
--variable current_dir : direction;
--begin
--current_dir := snake(to_integer(current_index)).dir;
--if (clk_lente'event and clk_lente = '1') then
--    update <= '1';
--end if;

--if (update ='1' and clk_rapide'event and clk_rapide = '1') then
--    lastSnake <= snake(to_integer(current_index));
--    if (current_dir = haut) then
--        snake(to_integer(current_index)).Y <= snake(to_integer(current_index)).Y - 1;
--    end if;
--    if (current_dir = bas) then
--        snake(to_integer(current_index)).Y <= snake(to_integer(current_index)).Y + 1;
--    end if;
--    if (current_dir = droite) then
--        snake(to_integer(current_index)).X <= snake(to_integer(current_index)).X + 1;
--    end if;
--    if (current_dir = gauche) then
--        snake(to_integer(current_index)).X <= snake(to_integer(current_index)).X - 1;
--    end if;
    
--    if ((snake(to_integer(current_index)).X/16 /= lastSnake.X/16) or (snake(to_integer(current_index)).Y/16 /= lastSnake.Y/16)) then
--        mat(to_integer(lastSnake.X/16),to_integer(lastSnake.Y/16)) <= to_unsigned(1200,11);
--        mat(to_integer(snake(to_integer(current_index)).X/16),to_integer(snake(to_integer(current_index)).Y/16))<=current_index;
--    end if;
--    current_index <= current_index + 1;
--end if;

--if (to_integer(current_index) = snake'length) then
--    current_index <= (others => '0');
--    update <= '0';
--end if;
--end process;

snakePresent <= snakeHere;
end Behavioral;
