library IEEE;
use IEEE.std_logic_1164.all;


entity CACHE_CONTROL is   -- CACHE_CONTROL 
        port (  
				-- nodes and buses for RAM_ROM_BIDIR
				
				CLOCK_PUBLIC							: in std_logic;  
				COUNTER_DEC_CHANGE						: in std_logic;
				DATA_BUS_IN								: in std_logic_vector(7 downto 0);

                CLOCK_DEC, ROM_DEC, W					: in std_logic; 
                ADDR_DEC 								: in std_logic_vector(11 downto 0);
                DATA_MEM								: out std_logic_vector(7 downto 0);
                ADDR_MEM 								: out std_logic_vector(11 downto 0);
				CLOCK_MEM, WRITE_MEM, DELAY				: out std_logic;				
				
				-- nodes and buses for CACHE_MAIN
				TAG										: in std_logic_vector(6 downto 0);
				OUT_CACHE								: in std_logic_vector(7 downto 0);
				MISS, M									: in std_logic;		
				TAG_FIX									: in std_logic_vector(6 downto 0);		
				CLOCK_CACHE, WRITE_CACHE				: out std_logic; 
				ADDR_CACHE								: out std_logic_vector(11 downto 0);			
				IN_CACHE 								: out std_logic_vector(7 downto 0);				

				
				-- nodes and buses for FLAG_BLOCK	
				F										: in std_logic;							
				CLOCK_FLAG								: out std_logic; 
				
				-- nodes and buses for COUNTER
				COUNTER									: in std_logic_vector(7 downto 0);
				ACLR, CLOCK_COUNTER						: out std_logic;	
				
				-- nodes and buses for other
				CLOCK_FIX								: out std_logic;
				
				qq										: in std_logic_vector(1 downto 0);
				MEM										: in std_logic_vector(7 downto 0)
        );
end CACHE_CONTROL ;


architecture CACHE_ARCH of CACHE_CONTROL is
begin
		
        process (COUNTER, ROM_DEC, COUNTER_DEC_CHANGE, CLOCK_PUBLIC)        
        begin
        DATA_MEM		<= "ZZZZZZZZ";      
        if(ROM_DEC='0') then	
			
			case COUNTER is
					when "00000000" => 		-- 0
						if (qq="00") then	
						DELAY			<= '1';					
						ACLR			<= '0';
						ADDR_CACHE 		<= ADDR_DEC;
						WRITE_CACHE 	<= '0';
						CLOCK_CACHE 	<= CLOCK_DEC;
						CLOCK_FLAG		<= '0';
						CLOCK_COUNTER	<= CLOCK_DEC;						
						CLOCK_FIX		<= CLOCK_DEC;
						end if;
					when "00000001" =>		-- 1	
						if(W='1' and (M='1' or (M='1' and F='0'))) then
							DELAY			<= '0';	--- delete
							ACLR			<= '0';						
							ADDR_CACHE 		<= ADDR_DEC;
							WRITE_CACHE	<= '1';
							IN_CACHE	<= DATA_BUS_IN;
							CLOCK_FLAG	<=  '1';
							CLOCK_CACHE 	<= not(CLOCK_DEC);														
						end if;
						if(M='1' and F='1') then
							DELAY			<= '1';	
							ACLR			<= '0';	
							ADDR_MEM (11 downto 5)	<= TAG(6 downto 0);
							ADDR_MEM (4 downto 0)	<= ADDR_DEC(4 downto 0);
							DATA_MEM				<= OUT_CACHE;
							WRITE_MEM				<= '1';
							WRITE_CACHE	<= '0';
							CLOCK_CACHE 	<= '0';	
							CLOCK_MEM				<= CLOCK_DEC;							
						end if;
						if(M='0' and W='0') then
							WRITE_CACHE <= '0';
							CLOCK_CACHE <= '0';
							DELAY		<= '0';
							ACLR		<= '1';
						end if;
						if(F='0' and M='1') then
							if(W='0') then
								CLOCK_CACHE	<= '0';
							end if;							
							WRITE_CACHE <= '1';
							DELAY			<= '1';	
							ACLR			<= '0';								
							ADDR_MEM (11 downto 1)	<= ADDR_DEC(11 downto 1);
							ADDR_MEM (0)			<= not(ADDR_DEC(0));
							WRITE_MEM				<= '0';
							CLOCK_MEM				<= CLOCK_DEC;															
						end if;
						CLOCK_FIX		<= '0';	
						CLOCK_COUNTER	<= CLOCK_DEC;
					when "00000010" => 		-- 2						
						if(W='1' and M='0') then
							ADDR_CACHE 		<= ADDR_DEC;
							WRITE_CACHE	<= '1';
							IN_CACHE	<= DATA_BUS_IN;
							DELAY		<= '0';							
							ACLR		<= '1';							
							CLOCK_CACHE	<= '0';
							CLOCK_FLAG	<= '0';														
						end if;		
						if(W='1' and M='1') then
							if(F='1') then
								WRITE_CACHE 	<= '0';
							else
								WRITE_CACHE 	<= '1';
							end if;								
							CLOCK_MEM				<= '0';		
							DELAY			<= '1';	
							ACLR			<= '0';	
							ADDR_CACHE(0)			<= not(ADDR_DEC(0));
							ADDR_CACHE (11 downto 1)	<= ADDR_DEC(11 downto 1);
							IN_CACHE	<= MEM;
							CLOCK_CACHE 	<= CLOCK_DEC;
						end if;	
						
						if((W='0' and M='1')) then
							
							CLOCK_MEM		<= '0';		
							DELAY			<= '1';	
							ACLR			<= '0';							
							ADDR_CACHE (11 downto 1)	<= ADDR_DEC(11 downto 1);
							ADDR_CACHE(0)			<= not(ADDR_DEC(0));							
							if(F='0') then		
								IN_CACHE		<= MEM;
								WRITE_CACHE 	<= '1';			
							else
								WRITE_CACHE 	<= '0';
							end if;		
							CLOCK_CACHE 	<= not(CLOCK_DEC);					
						end if;							
						if(M='0' and W='0') then
							CLOCK_CACHE <= '0';
							DELAY		<= '0';
							ACLR		<= '1';
						end if;
						CLOCK_COUNTER	<= CLOCK_DEC;
					when "00000011" =>		-- 3						
						DELAY			<= '1';	
						ACLR			<= '0';							
						if(F='1') then
							ADDR_MEM(0)	<= not(ADDR_DEC(0));
							ADDR_MEM (11 downto 5)	<= TAG(6 downto 0);
							ADDR_MEM (4 downto 1)	<= ADDR_DEC(4 downto 1);							
							DATA_MEM				<= OUT_CACHE;
							WRITE_MEM				<= '1';	
							CLOCK_CACHE 	<= '0';				
							WRITE_CACHE 	<= '0';									
						else
							if(W='1' and (M='1' and F='0')) then
								ADDR_CACHE(0)			<= not(ADDR_DEC(0));
								ADDR_CACHE (11 downto 1)	<= ADDR_DEC(11 downto 1);
								WRITE_CACHE 	<= '1';
								IN_CACHE	<= MEM;
								DELAY		<= '0';							
								ACLR		<= '1';							
								CLOCK_CACHE	<= '0';
								CLOCK_FLAG	<= '0';		
							else
								ADDR_MEM	<= ADDR_DEC;
								WRITE_MEM				<= '0';	
								if(M='1' and W='0') then								
									CLOCK_CACHE	<= '0';
									WRITE_CACHE 	<= '0';								
								else		
									ADDR_CACHE 				<= ADDR_DEC;	
									IN_CACHE		<= MEM;
									WRITE_CACHE 	<= '1';	
									CLOCK_CACHE	<= not(CLOCK_DEC);								
								end if;	
							end if;						
						end if;		
						CLOCK_MEM		<= CLOCK_DEC;
						CLOCK_COUNTER	<= CLOCK_DEC;
					when "00000100" =>		-- 4						
						ACLR			<= '0';							
						if(F='1' and M='1') then
							DELAY			<= '1';							
							--ADDR_MEM	<= ADDR_DEC;													
							if(W='1') then								
								ADDR_CACHE 				<= ADDR_DEC;						
								IN_CACHE				<= DATA_BUS_IN;	
								WRITE_CACHE				<= '1';
								CLOCK_CACHE				<= CLOCK_PUBLIC;
								ADDR_MEM(11 downto 1)	<= ADDR_DEC(11 downto 1);
								ADDR_MEM(0)	<= not(ADDR_DEC(0));	
								WRITE_MEM	<= '0';
								CLOCK_MEM	<= CLOCK_DEC;
							else
								ADDR_CACHE(11 downto 1) <= ADDR_DEC(11 downto 1);
								ADDR_CACHE(0)	<= not(ADDR_DEC(0));
								CLOCK_CACHE				<= '0';
								ADDR_MEM(11 downto 1)	<= ADDR_DEC(11 downto 1);
								ADDR_MEM(0)	<= not(ADDR_DEC(0));
								WRITE_MEM	<= '0';
								IN_CACHE		<= MEM;
								CLOCK_MEM	<= CLOCK_DEC;
								WRITE_CACHE	<= '0';
							end if;										
						end if;
						if(W='0' and M='1' and F='0') then
							CLOCK_CACHE		<= (CLOCK_DEC);
							ADDR_CACHE	<= ADDR_DEC;
							DELAY			<= '0'; -- delete							
							WRITE_CACHE		<= '1';
							IN_CACHE		<= MEM;
							
						end if;	
						CLOCK_COUNTER	<= CLOCK_DEC;				
					when "00000101" =>		-- 5						
						if(W='1' and F='1' and M='1') then
							DELAY			<= '0';	
							ACLR			<= '1';	
							ADDR_CACHE(11 downto 1)	<= ADDR_DEC(11 downto 1);
							ADDR_CACHE(0)	<= not(ADDR_DEC(0));
							IN_CACHE		<= MEM;
							WRITE_CACHE		<= '1';
							CLOCK_CACHE		<= CLOCK_PUBLIC;	
						end if;			
						if(W='0' and M='1' and F='0') then
							ADDR_CACHE	<= ADDR_DEC;
							CLOCK_CACHE		<= '0';							
							CLOCK_MEM		<= '0';		
							DELAY			<= '0';
							ACLR			<= '1';
						end if;
						if(W='0' and M='1' and F='1') then
						ADDR_CACHE(0)	<= not(ADDR_DEC(0));
							DELAY			<= '1';	
							ACLR			<= '0';
							ADDR_CACHE(11 downto 1)	<= ADDR_DEC(11 downto 1);
							
							IN_CACHE	<= MEM;
							WRITE_CACHE <= '1';
							CLOCK_CACHE	<= not(CLOCK_DEC);
						end if;			
						CLOCK_COUNTER	<= CLOCK_DEC;
					when "00000110" =>		-- 6						
						if(W='1') then
							DELAY			<= '0';							
							ACLR			<= '1';
							CLOCK_CACHE		<= '0';
							CLOCK_MEM		<= '0';
							DATA_MEM		<= "ZZZZZZZZ";															
						else
							DELAY			<= '1';	
							ACLR			<= '0';
							ADDR_CACHE		<= ADDR_DEC;
							IN_CACHE	<= MEM;
							WRITE_CACHE <= '1';
							CLOCK_CACHE		<= '0';
							ADDR_MEM		<= ADDR_DEC;
							WRITE_MEM		<= '0';							
							CLOCK_MEM		<= CLOCK_DEC;
						end if;	
						CLOCK_COUNTER	<= CLOCK_DEC;				
					when "00000111" =>		-- 7	
						DELAY			<= '0';	
						ACLR			<= '1';
						ADDR_CACHE		<= ADDR_DEC;
						IN_CACHE		<= MEM;
						WRITE_CACHE		<= '1';						
						CLOCK_FLAG			<= CLOCK_DEC;	
						CLOCK_CACHE			<= CLOCK_PUBLIC;	
						CLOCK_COUNTER	<= CLOCK_DEC;			
					when "00001000" =>		-- 8
							ADDR_CACHE		<= ADDR_DEC;
							IN_CACHE		<= MEM;
							WRITE_CACHE		<= '0';		
							CLOCK_CACHE		<= '0';
							CLOCK_MEM		<= '0';						
							DELAY			<= '0';							
							ACLR			<= '1';							
							DATA_MEM		<= "ZZZZZZZZ";	
							CLOCK_COUNTER	<= CLOCK_DEC;			
					when others => null;
				end case;
				--else
				--	CLOCK_COUNTER <= COUNTER_DEC_CHANGE;
			end if;	
        end process;
end CACHE_ARCH;
