------------------------------------------------------------------------------
-- Carte :		Cam-ass-ultra
-- Fonction : 	Memory sharer
-- Author :		crazyfred / EIRBOT 2006
-- Date :		01.05.2006
------------------------------------------------------------------------------

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

entity mem_sharer is
	port (
		A_ramV : out std_logic_vector(18 downto 0);
		D_ramV : inout std_logic_vector(15 downto 0);
		RD_L_ramV : out std_logic;
		RD_H_ramV : out std_logic;
		WR_L_ramV : out std_logic;
		WR_H_ramV : out std_logic;

		A_ramT : out std_logic_vector(18 downto 0);
		D_ramT : inout std_logic_vector(15 downto 0);
		RD_L_ramT : out std_logic;
		RD_H_ramT : out std_logic;
		WR_L_ramT : out std_logic;
		WR_H_ramT : out std_logic;

		A_flashA : out std_logic_vector(18 downto 0);
		D_flashA : inout std_logic_vector(7 downto 0);
		RD_flashA : out std_logic;
		WR_flashA : out std_logic;

		A_flashB : out std_logic_vector(18 downto 0);
		D_flashB : inout std_logic_vector(7 downto 0);
		RD_flashB : out std_logic;
		WR_flashB : out std_logic;

		request_A : in std_logic;
		request_type_A : in std_logic_vector(1 downto 0);
		access_granted_A : out std_logic;
		RD_L_A : in std_logic;
		RD_H_A : in std_logic;
		WR_L_A : in std_logic;
		WR_H_A : in std_logic;
		Address_A : in std_logic_vector(18 downto 0);
		Data_A : inout std_logic_vector(15 downto 0);

		request_B : in std_logic;
		request_type_B : in std_logic_vector(1 downto 0);
		access_granted_B : out std_logic;
		RD_L_B : in std_logic;
		RD_H_B : in std_logic;
		WR_L_B : in std_logic;
		WR_H_B : in std_logic;
		Address_B : in std_logic_vector(18 downto 0);
		Data_B : inout std_logic_vector(15 downto 0);

		request_C : in std_logic;
		request_type_C : in std_logic_vector(1 downto 0);
		access_granted_C : out std_logic;
		RD_L_C : in std_logic;
		RD_H_C : in std_logic;
		WR_L_C : in std_logic;
		WR_H_C : in std_logic;
		Address_C : in std_logic_vector(18 downto 0);
		Data_C : inout std_logic_vector(15 downto 0);
		
		clk : in std_logic;
		status : out std_logic_vector(7 downto 0)
	);

end mem_sharer;


architecture structure of mem_sharer is

	signal ramV_status : std_logic_vector(1 downto 0);
	signal ramT_status : std_logic_vector(1 downto 0);
	signal flashA_status : std_logic_vector(1 downto 0);
	signal flashB_status : std_logic_vector(1 downto 0);

	signal access_granted_A_ramV, access_granted_A_ramT, access_granted_A_flashA, access_granted_A_flashB : std_logic;
	signal access_granted_B_ramV, access_granted_B_ramT, access_granted_B_flashA, access_granted_B_flashB : std_logic;
	signal access_granted_C_ramV, access_granted_C_ramT, access_granted_C_flashA, access_granted_C_flashB : std_logic;

begin


	Data_A(7 downto 0) <= D_ramV(7 downto 0) when (ramV_status = "01") and (RD_L_A = '0') else
			D_ramT(7 downto 0) when (ramT_status = "01") and (RD_L_A = '0') else
			D_flashA when (flashA_status = "01") and (RD_L_A = '0') else
			D_flashB when (flashB_status = "01") and (RD_L_A = '0') else
			"ZZZZZZZZ";
	Data_A(15 downto 8) <= D_ramV(15 downto 8) when (ramV_status = "01") and (RD_H_A = '0') else
			D_ramT(15 downto 8) when (ramT_status = "01") and (RD_H_A = '0') else
			"00000000" when (flashA_status = "01") and (RD_H_A = '0') else
			"00000000" when (flashB_status = "01") and (RD_H_A = '0') else
			"ZZZZZZZZ";

	Data_B(7 downto 0) <= D_ramV(7 downto 0) when (ramV_status = "10") and (RD_L_B = '0') else
			D_ramT(7 downto 0) when (ramT_status = "10") and (RD_L_B = '0') else
			D_flashA when (flashA_status = "10") and (RD_L_B = '0') else
			D_flashB when (flashB_status = "10") and (RD_L_B = '0') else
			"ZZZZZZZZ";
	Data_B(15 downto 8) <= D_ramV(15 downto 8) when (ramV_status = "10") and (RD_H_B = '0') else
			D_ramT(15 downto 8) when (ramT_status = "10") and (RD_H_B = '0') else
			"00000000" when (flashA_status = "10") and (RD_H_B = '0') else
			"00000000" when (flashB_status = "10") and (RD_H_B = '0') else
			"ZZZZZZZZ";

	Data_C(7 downto 0) <= D_ramV(7 downto 0) when (ramV_status = "11") and (RD_L_C = '0') else
			D_ramT(7 downto 0) when (ramT_status = "11") and (RD_L_C = '0') else
			D_flashA when (flashA_status = "11") and (RD_L_C = '0') else
			D_flashB when (flashB_status = "11") and (RD_L_C = '0') else
			"ZZZZZZZZ";
	Data_C(15 downto 8) <= D_ramV(15 downto 8) when (ramV_status = "11") and (RD_H_C = '0') else
			D_ramT(15 downto 8) when (ramT_status = "11") and (RD_H_C = '0') else
			"00000000" when (flashA_status = "11") and (RD_H_C = '0') else
			"00000000" when (flashB_status = "11") and (RD_H_C = '0') else
			"ZZZZZZZZ";


	D_ramV(7 downto 0) <= Data_A(7 downto 0) when (ramV_status = "01") and (RD_L_A = '1') else
			Data_B(7 downto 0) when (ramV_status = "10") and (RD_L_B = '1') else
			Data_C(7 downto 0) when (ramV_status = "11") and (RD_L_C = '1') else
			"ZZZZZZZZ";
	D_ramV(15 downto 8) <= Data_A(15 downto 8) when (ramV_status = "01") and (RD_H_A = '1') else
			Data_B(15 downto 8) when (ramV_status = "10") and (RD_H_B = '1') else
			Data_C(15 downto 8) when (ramV_status = "11") and (RD_H_C = '1') else
			"ZZZZZZZZ";

	D_ramT(7 downto 0) <= Data_A(7 downto 0) when (ramT_status = "01") and (RD_L_A = '1') else
			Data_B(7 downto 0) when (ramT_status = "10") and (RD_L_B = '1') else
			Data_C(7 downto 0) when (ramT_status = "11") and (RD_L_C = '1') else
			"ZZZZZZZZ";
	D_ramT(15 downto 8) <= Data_A(15 downto 8) when (ramT_status = "01") and (RD_H_A = '1') else
			Data_B(15 downto 8) when (ramT_status = "10") and (RD_H_B = '1') else
			Data_C(15 downto 8) when (ramT_status = "11") and (RD_H_C = '1') else
			"ZZZZZZZZ";

	D_flashA <= Data_A(7 downto 0) when (flashA_status = "01") and (RD_L_A = '1') else
			Data_B(7 downto 0) when (flashA_status = "10") and (RD_L_B = '1') else
			Data_C(7 downto 0) when (flashA_status = "11") and (RD_L_C = '1') else
			"ZZZZZZZZ";

	D_flashB <= Data_A(7 downto 0) when (flashB_status = "01") and (RD_L_A = '1') else
			Data_B(7 downto 0) when (flashB_status = "10") and (RD_L_B = '1') else
			Data_C(7 downto 0) when (flashB_status = "11") and (RD_L_C = '1') else
			"ZZZZZZZZ";


	status <= flashB_status&flashA_status&ramT_status&ramV_status;

	ramV_manage : process(ramV_status, Address_A, Data_A, Address_B, Data_B, Address_C, Data_C, D_ramV, RD_L_A, RD_H_A, WR_L_A, WR_H_A, RD_L_B, RD_H_B, WR_L_B, WR_H_B, RD_L_C, RD_H_C, WR_L_C, WR_H_C)
	begin
		if (ramV_status = "00") then 
			RD_L_ramV <= '1';
			RD_H_ramV <= '1';
			WR_L_ramV <= '1';
			WR_H_ramV <= '1';
		elsif (ramV_status = "01") then
			A_ramV <= Address_A;
			RD_L_ramV <= RD_L_A;
			RD_H_ramV <= RD_H_A;
			WR_L_ramV <= WR_L_A;
			WR_H_ramV <= WR_H_A;
		elsif (ramV_status = "10") then
			A_ramV <= Address_B;
			RD_L_ramV <= RD_L_B;
			RD_H_ramV <= RD_H_B;
			WR_L_ramV <= WR_L_B;
			WR_H_ramV <= WR_H_B;
		elsif (ramV_status = "11") then
			A_ramV <= Address_C;
			RD_L_ramV <= RD_L_C;
			RD_H_ramV <= RD_H_C;
			WR_L_ramV <= WR_L_C;
			WR_H_ramV <= WR_H_C;
		end if;
	end process;

	ramT_manage : process(ramT_status, Address_A, Data_A, Address_B, Data_B, Address_C, Data_C, D_ramT, RD_L_A, RD_H_A, WR_L_A, WR_H_A, RD_L_B, RD_H_B, WR_L_B, WR_H_B, RD_L_C, RD_H_C, WR_L_C, WR_H_C)
	begin
		if (ramT_status = "00") then
			RD_L_ramT <= '1';
			RD_H_ramT <= '1';
			WR_L_ramT <= '1';
			WR_H_ramT <= '1';
		elsif (ramT_status = "01") then
			A_ramT <= Address_A;
			RD_L_ramT <= RD_L_A;
			RD_H_ramT <= RD_H_A;
			WR_L_ramT <= WR_L_A;
			WR_H_ramT <= WR_H_A;
		elsif (ramT_status = "10") then
			A_ramT <= Address_B;
			RD_L_ramT <= RD_L_B;
			RD_H_ramT <= RD_H_B;
			WR_L_ramT <= WR_L_B;
			WR_H_ramT <= WR_H_B;
		elsif (ramT_status = "11") then
			A_ramT <= Address_C;
			RD_L_ramT <= RD_L_C;
			RD_H_ramT <= RD_H_C;
			WR_L_ramT <= WR_L_C;
			WR_H_ramT <= WR_H_C;
		end if;
	end process;

	flashA_manage : process(flashA_status, Address_A, Data_A, Address_B, Data_B, Address_C, Data_C, D_flashA, RD_L_A, WR_L_A, RD_L_B, WR_L_B, RD_L_C, WR_L_C)
	begin
		if (flashA_status = "00") then
			RD_flashA <= '1';
			WR_flashA <= '1';
		elsif (flashA_status = "01") then
			A_flashA <= Address_A;
			RD_flashA <= RD_L_A;
			WR_flashA <= WR_L_A;
		elsif (flashA_status = "10") then
			A_flashA <= Address_B;
			RD_flashA <= RD_L_B;
			WR_flashA <= WR_L_B;
		elsif (flashA_status = "11") then
			A_flashA <= Address_C;
			RD_flashA <= RD_L_C;
			WR_flashA <= WR_L_C;
		end if;
	end process;

	flashB_manage : process(flashB_status, Address_A, Data_A, Address_B, Data_B, Address_C, Data_C, D_flashB, RD_L_A, WR_L_A, RD_L_B, WR_L_B, RD_L_C, WR_L_C)
	begin
		if (flashB_status = "00") then
			RD_flashB <= '1';
			WR_flashB <= '1';
		elsif (flashB_status = "01") then
			A_flashB <= Address_A;
			RD_flashB <= RD_L_A;
			WR_flashB <= WR_L_A;
		elsif (flashB_status = "10") then
			A_flashB <= Address_B;
			RD_flashB <= RD_L_B;
			WR_flashB <= WR_L_B;
		elsif (flashB_status = "11") then
			A_flashB <= Address_C;
			RD_flashB <= RD_L_C;
			WR_flashB <= WR_L_C;
		end if;
	end process;

--------------------------------------------------------------------------------------------

	ramV_statemachine : process(clk, ramV_status, request_A, request_B, request_C, request_type_A, request_type_B, request_type_C)
	begin
	if (rising_edge(clk)) then
		if (ramV_status = "00") then -- traitement des demandes d'accés qd la ramV est libre
			if (request_type_A = "00") and (request_A = '1') then
				ramV_status <= "01";
			elsif (request_type_B = "00") and (request_B = '1') then
				ramV_status <= "10";
			elsif (request_type_C = "00") and (request_C = '1') then
				ramV_status <= "11";
			end if;			
		elsif (ramV_status = "01") and ( (request_A = '0') or (request_type_A /= "00") ) then -- l'accés A n'en a plus besoin
			ramV_status <= "00";
		elsif (ramV_status = "10") and ( (request_B = '0') or (request_type_B /= "00") ) then -- l'accés B n'en a plus besoin
			ramV_status <= "00";
		elsif (ramV_status = "11") and ( (request_C = '0') or (request_type_C /= "00") ) then -- l'accés C n'en a plus besoin
			ramV_status <= "00";
		end if;
	end if;
	end process;

	access_granted_A_ramV <= not(ramV_status(1)) and ramV_status(0);
	access_granted_B_ramV <= ramV_status(1) and not(ramV_status(0));
	access_granted_C_ramV <= ramV_status(1) and ramV_status(0);
	
	ramT_statemachine : process(clk, ramT_status, request_A, request_B, request_C, request_type_A, request_type_B, request_type_C)
	begin
	if (rising_edge(clk)) then
		if (ramT_status = "00") then -- traitement des demandes d'accés qd la ramT est libre
			if (request_type_A = "01") and (request_A = '1') then
				ramT_status <= "01";
			elsif (request_type_B = "01") and (request_B = '1') then
				ramT_status <= "10";
			elsif (request_type_C = "01") and (request_C = '1') then
				ramT_status <= "11";
			end if;
		elsif (ramT_status = "01") and ( (request_A = '0') or (request_type_A /= "01") ) then -- l'accés A n'en a plus besoin
			ramT_status <= "00";
		elsif (ramT_status = "10") and ( (request_B = '0') or (request_type_B /= "01") ) then -- l'accés B n'en a plus besoin
			ramT_status <= "00";
		elsif (ramT_status = "11") and ( (request_C = '0') or (request_type_C /= "01") ) then -- l'accés C n'en a plus besoin
			ramT_status <= "00";
		end if;
	end if;
	end process;

	access_granted_A_ramT <= not(ramT_status(1)) and ramT_status(0);
	access_granted_B_ramT <= ramT_status(1) and not(ramT_status(0));
	access_granted_C_ramT <= ramT_status(1) and ramT_status(0);

	flashA_statemachine : process(clk, flashA_status, request_A, request_B, request_C, request_type_A, request_type_B, request_type_C)
	begin
	if (rising_edge(clk)) then
		if (flashA_status = "00") then -- traitement des demandes d'accés qd la flashA est libre
			if (request_type_A = "10") and (request_A = '1') then
				flashA_status <= "01";
			elsif (request_type_B = "10") and (request_B = '1') then
				flashA_status <= "10";
			elsif (request_type_C = "10") and (request_C = '1') then
				flashA_status <= "11";
			end if;
		elsif (flashA_status = "01") and ( (request_A = '0') or (request_type_A /= "10") ) then -- l'accés A n'en a plus besoin
			flashA_status <= "00";
		elsif (flashA_status = "10") and ( (request_B = '0') or (request_type_B /= "10") ) then -- l'accés B n'en a plus besoin
			flashA_status <= "00";
		elsif (flashA_status = "11") and ( (request_C = '0') or (request_type_C /= "10") ) then -- l'accés C n'en a plus besoin
			flashA_status <= "00";
		end if;
	end if;
	end process;

	access_granted_A_flashA <= not(flashA_status(1)) and flashA_status(0);
	access_granted_B_flashA <= flashA_status(1) and not(flashA_status(0));
	access_granted_C_flashA <= flashA_status(1) and flashA_status(0);

	flashB_statemachine : process(clk, flashB_status, request_A, request_B, request_C, request_type_A, request_type_B, request_type_C)
	begin
	if (rising_edge(clk)) then
		if (flashB_status = "00") then -- traitement des demandes d'accés qd la flashA est libre
			if (request_type_A = "11") and (request_A = '1') then
				flashB_status <= "01";
			elsif (request_type_B = "11") and (request_B = '1') then
				flashB_status <= "10";
			elsif (request_type_C = "11") and (request_C = '1') then
				flashB_status <= "11";
			end if;
		elsif (flashB_status = "01") and ( (request_A = '0') or (request_type_A /= "11") ) then -- l'accés A n'en a plus besoin
			flashB_status <= "00";
		elsif (flashB_status = "10") and ( (request_B = '0') or (request_type_B /= "11") ) then -- l'accés B n'en a plus besoin
			flashB_status <= "00";
		elsif (flashB_status = "11") and ( (request_C = '0') or (request_type_C /= "11") ) then -- l'accés C n'en a plus besoin
			flashB_status <= "00";
		end if;
	end if;
	end process;

	access_granted_A_flashB <= not(flashB_status(1)) and flashB_status(0);
	access_granted_B_flashB <= flashB_status(1) and not(flashB_status(0));
	access_granted_C_flashB <= flashB_status(1) and flashB_status(0);

access_granted_A <= access_granted_A_ramV or access_granted_A_ramT or access_granted_A_flashA or access_granted_A_flashB;
access_granted_B <= access_granted_B_ramV or access_granted_B_ramT or access_granted_B_flashA or access_granted_B_flashB;
access_granted_C <= access_granted_C_ramV or access_granted_C_ramT or access_granted_C_flashA or access_granted_C_flashB;

-------------------------------------------------------------------------------
end structure;
