------------------------------------------------------------------------------
-- Affaire :   ROBOT
-- Carte :		Camera
-- EPLD :		Epld_
-- Fonction : 	Ball Finder v2 !
-- Author :		EIRBOT 2003 ENSEIRB
-- Date :		25.10.2002
------------------------------------------------------------------------------

library IEEE, work;
use IEEE.std_logic_1164.all;
use ieee.std_logic_unsigned.all; 
use ieee.numeric_std.all; 
use work.all;

entity atmel is
	port (
		access_request : out std_logic;
		access_type : out std_logic_vector(1 downto 0);
		access_granted : in std_logic;
		A_mem : out std_logic_vector(18 downto 0);
		D_mem : inout std_logic_vector(15 downto 0);
		RD_L_mem : out std_logic;
		RD_H_mem : out std_logic;
		WR_L_mem : out std_logic;
		WR_H_mem : out std_logic;
		
		A     : in std_logic_vector(15 downto 8);
		AD     : inout std_logic_vector(7 downto 0);

		ALE  : in std_logic;
		ReadN  : in std_logic;
		WriteN : in std_logic;
		clk : in std_logic;

		entreeA : in std_logic_vector(7 downto 0);
		sortieA : out std_logic_vector(7 downto 0);
		entreeB : in std_logic_vector(7 downto 0);
		sortieB : out std_logic_vector(7 downto 0);
		entreeC : in std_logic_vector(7 downto 0);
		sortieC : out std_logic_vector(7 downto 0);
		entreeD : in std_logic_vector(7 downto 0);
		sortieD : out std_logic_vector(7 downto 0);
		entreeE : in std_logic_vector(7 downto 0);
		sortieE : out std_logic_vector(7 downto 0);
		entreeF : in std_logic_vector(7 downto 0);
		sortieF : out std_logic_vector(7 downto 0);
		entreeG : in std_logic_vector(7 downto 0);
		sortieG : out std_logic_vector(7 downto 0);
		entreeH : in std_logic_vector(7 downto 0);
		sortieH : out std_logic_vector(7 downto 0);
		entreeI : in std_logic_vector(7 downto 0);
		sortieI : out std_logic_vector(7 downto 0);
		entreeJ : in std_logic_vector(7 downto 0);
		sortieJ : out std_logic_vector(7 downto 0);
		entreeAA : in std_logic_vector(7 downto 0);
		sortieAA : out std_logic_vector(7 downto 0);
		entreeAB : in std_logic_vector(7 downto 0);
		sortieAB : out std_logic_vector(7 downto 0);
		entreeAC : in std_logic_vector(7 downto 0);
		sortieAC : out std_logic_vector(7 downto 0);
		entreeAD : in std_logic_vector(7 downto 0);
		sortieAD : out std_logic_vector(7 downto 0);
		entreeAE : in std_logic_vector(7 downto 0);
		sortieAE : out std_logic_vector(7 downto 0);
		entreeAF : in std_logic_vector(7 downto 0);
		sortieAF : out std_logic_vector(7 downto 0);
		entreeAG : in std_logic_vector(7 downto 0);
		sortieAG : out std_logic_vector(7 downto 0);
		entreeAH : in std_logic_vector(7 downto 0);
		sortieAH : out std_logic_vector(7 downto 0);
		entreeAI : in std_logic_vector(7 downto 0);
		sortieAI : out std_logic_vector(7 downto 0);
		entreeAJ : in std_logic_vector(7 downto 0);
		sortieAJ : out std_logic_vector(7 downto 0);
		entreeBA : in std_logic_vector(7 downto 0);
		sortieBA : out std_logic_vector(7 downto 0);
		entreeBB : in std_logic_vector(7 downto 0);
		sortieBB : out std_logic_vector(7 downto 0);
		entreeBC : in std_logic_vector(7 downto 0);
		sortieBC : out std_logic_vector(7 downto 0);
		entreeBD : in std_logic_vector(7 downto 0);
		sortieBD : out std_logic_vector(7 downto 0);
		entreeBE : in std_logic_vector(7 downto 0);
		sortieBE : out std_logic_vector(7 downto 0);
		entreeBF : in std_logic_vector(7 downto 0);
		sortieBF : out std_logic_vector(7 downto 0);
		entreeBG : in std_logic_vector(7 downto 0);
		sortieBG : out std_logic_vector(7 downto 0);
		entreeBH : in std_logic_vector(7 downto 0);
		sortieBH : out std_logic_vector(7 downto 0);
		entreeBI : in std_logic_vector(7 downto 0);
		sortieBI : out std_logic_vector(7 downto 0);
		entreeBJ : in std_logic_vector(7 downto 0);
		sortieBJ : out std_logic_vector(7 downto 0);
		entreeCA : in std_logic_vector(7 downto 0);
		sortieCA : out std_logic_vector(7 downto 0);
		entreeCB : in std_logic_vector(7 downto 0);
		sortieCB : out std_logic_vector(7 downto 0)
	);

end atmel;


architecture structure of atmel is

	signal Address : std_logic_vector(15 downto 0);
	signal Data_out : std_logic_vector(7 downto 0); -- sortie vers l'atmel
	signal Data_in : std_logic_vector(7 downto 0); -- entree dans le FPGA
	signal Data_mem : std_logic_vector(7 downto 0);
	signal enable_io, enable_mem, enable_ep_ram : std_logic;

	signal data_ep_ram, q_ep_ram : std_logic_vector(7 downto 0);
	signal wren_ep_ram : std_logic;

	signal choix : std_logic_vector(7 downto 0);

component ram16ko
	PORT
	(
		address		: IN STD_LOGIC_VECTOR (13 DOWNTO 0);
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
		wren		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
	);
end component;

begin

	Address(15 downto 8) <= A(15 downto 8);

-------------------------------------------------------------------------------
	address_latch : process(ALE,AD)
	begin
		if ALE='1' then
			Address(7 downto 0) <= AD;
		end if;
	end process;
	
	write_process : process(WriteN)
	begin
		if WriteN = '0' then Data_in <= AD; end if;
	end process;
	
	AD <= Data_out when ReadN = '0' else "ZZZZZZZZ";
-------------------------------------------------------------------------------
-- 0000 - 1FFF : io
-- 2000 - 3FFF : ??
-- 4000 - 7FFF : ep_ram
-- 8000 - FFFF : memory pages
	fonction : process (Address)
	begin
		if (Address(15 downto 13) = "000") then
			enable_io <= '1';
			enable_ep_ram <= '0';
			enable_mem <= '0';
		elsif (Address(15 downto 13) = "01") then
			enable_io <= '0';
			enable_ep_ram <= '1';
			enable_mem <= '0';
		elsif (Address(15) = '1') then
			enable_io <= '0';
			enable_ep_ram <= '0';
			enable_mem <= '1';
		else
			enable_io <= '0';
			enable_ep_ram <= '0';
			enable_mem <= '0';
		end if;
	end process;
-------------------------------------------------------------------------------
	A_mem(13 downto 0) <= Address(14 downto 1);
	D_mem(7 downto 0) <= Data_mem when ReadN = '1' and Address(0) = '0' else "ZZZZZZZZ";
	D_mem(15 downto 8) <= Data_mem when ReadN = '1' and Address(0) = '1' else "ZZZZZZZZ";
	RD_L_mem <= ReadN or not(enable_mem) or Address(0);
	RD_H_mem <= ReadN or not(enable_mem) or not(Address(0));
	WR_L_mem <= WriteN or not(enable_mem) or Address(0);
	WR_H_mem <= WriteN or not(enable_mem) or not(Address(0));
	wren_ep_ram <= WriteN or not(enable_ep_ram);
-------------------------------------------------------------------------------
	choix <= Address(7 downto 0);
-------------------------------------------------------------------------------
	lecture : process (choix, enable_io, enable_mem, enable_ep_ram, D_mem, access_granted, q_ep_ram, entreeA, entreeB, entreeC, entreeD, entreeE, entreeF, entreeG, entreeH, entreeI, entreeJ, entreeAA, entreeAB, entreeAC, entreeAD, entreeAE, entreeAF, entreeAG, entreeAH, entreeAI, entreeAJ, entreeBA, entreeBB, entreeBC, entreeBD, entreeBE, entreeBF, entreeBG, entreeBH, entreeBI, entreeBJ, entreeCA, entreeCB)
	begin
		if (enable_io = '1') then
			case choix is
				when "00000000" => Data_out <= entreeA;
				when "00000001" => Data_out <= entreeB;
				when "00000010" => Data_out <= entreeC;
				when "00000011" => Data_out <= entreeD;
				when "00000100" => Data_out <= entreeE;
				when "00000101" => Data_out <= entreeF;
				when "00000110" => Data_out <= entreeG;
				when "00000111" => Data_out <= entreeH;
				when "00001000" => Data_out <= entreeI;
				when "00001001" => Data_out <= entreeJ;
				when "00001010" => Data_out <= entreeAA;
				when "00001011" => Data_out <= entreeAB;
				when "00001100" => Data_out <= entreeAC;
				when "00001101" => Data_out <= entreeAD;
				when "00001110" => Data_out <= entreeAE;
				when "00001111" => Data_out <= entreeAF;
				when "00010000" => Data_out <= entreeAG;
				when "00010001" => Data_out <= entreeAH;
				when "00010010" => Data_out <= entreeAI;
				when "00010011" => Data_out <= entreeAJ;
				when "00010100" => Data_out <= entreeBA;
				when "00010101" => Data_out <= entreeBB;
				when "00010110" => Data_out <= entreeBC;
				when "00010111" => Data_out <= entreeBD;
				when "00011000" => Data_out <= entreeBE;
				when "00011001" => Data_out <= entreeBF;
				when "00011010" => Data_out <= entreeBG;
				when "00011011" => Data_out <= entreeBH;
				when "00011100" => Data_out <= entreeBI;
				when "00011101" => Data_out <= entreeBJ;
				when "00011110" => Data_out <= entreeCA;
				when "00011111" => Data_out <= entreeCB;
				when "11111110" => Data_out <= "1111000" & access_granted;
				when others => Data_out <= "01010101";
			end case;
		elsif (enable_ep_ram = '1') then
			Data_out <= q_ep_ram;
		elsif (enable_mem = '1') then
			if choix(0) = '0' then
				Data_out <= D_mem(7 downto 0);
			else
				Data_out <= D_mem(15 downto 8);
			end if;
		else
			Data_out <= "10101010";
		end if;
	end process;
-------------------------------------------------------------------------------
	ecriture : process (choix, WriteN, Data_in, enable_io, enable_mem, enable_ep_ram)
	begin
		if (enable_io = '1') and (WriteN = '0') then
			case choix is
				when "00000000" => sortieA <= Data_in;
				when "00000001" => sortieB <= Data_in;
				when "00000010" => sortieC <= Data_in;
				when "00000011" => sortieD <= Data_in;
				when "00000100" => sortieE <= Data_in;
				when "00000101" => sortieF <= Data_in;
				when "00000110" => sortieG <= Data_in;
				when "00000111" => sortieH <= Data_in;
				when "00001000" => sortieI <= Data_in;
				when "00001001" => sortieJ <= Data_in;
				when "00001010" => sortieAA <= Data_in;
				when "00001011" => sortieAB <= Data_in;
				when "00001100" => sortieAC <= Data_in;
				when "00001101" => sortieAD <= Data_in;
				when "00001110" => sortieAE <= Data_in;
				when "00001111" => sortieAF <= Data_in;
				when "00010000" => sortieAG <= Data_in;
				when "00010001" => sortieAH <= Data_in;
				when "00010010" => sortieAI <= Data_in;
				when "00010011" => sortieAJ <= Data_in;
				when "00010100" => sortieBA <= Data_in;
				when "00010101" => sortieBB <= Data_in;
				when "00010110" => sortieBC <= Data_in;
				when "00010111" => sortieBD <= Data_in;
				when "00011000" => sortieBE <= Data_in;
				when "00011001" => sortieBF <= Data_in;
				when "00011010" => sortieBG <= Data_in;
				when "00011011" => sortieBH <= Data_in;
				when "00011100" => sortieBI <= Data_in;
				when "00011101" => sortieBJ <= Data_in;
				when "00011110" => sortieCA <= Data_in;
				when "00011111" => sortieCB <= Data_in;
				when "11111110" => access_request <= Data_in(0);
				when "11111111" => A_mem(18 downto 14) <= Data_in(4 downto 0);
									access_type <= Data_in(6 downto 5);
				when others => NULL;
			end case;
		elsif (enable_ep_ram = '1') then
			data_ep_ram <= Data_in;
		elsif (enable_mem = '1') then
			Data_mem <= Data_in;
		end if;
	end process;
-------------------------------------------------------------------------------
ram16ko_inst : ram16ko PORT MAP (
		address	 => Address(13 downto 0),
		clock	 => clk,
		data	 => data_ep_ram,
		wren	 => wren_ep_ram,
		q	 => q_ep_ram
	);
-------------------------------------------------------------------------------


end structure;
