--------------------------------------------------------------------------------
-- Company: <Name>
--
-- File: Fabric_Master1.vhd
-- File history:
--      <Revision number>: <Date>: <Comments>
--      <Revision number>: <Date>: <Comments>
--      <Revision number>: <Date>: <Comments>
--
-- Description: 
--
-- <Description here>
--
-- Targeted device: <Family::SmartFusion2> <Die::M2S050T> <Package::896 FBGA>
-- Author: <Application Team>
--
--------------------------------------------------------------------------------


library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library smartfusion2;
use smartfusion2.all;

entity Fabric_Master1 is
  port (
		RESET_N           : in    std_logic;    
        HCLK              : in    std_logic;
        HTRANS            : out   std_logic_vector(1 downto 0);
        HSIZE             : out   std_logic_vector(1 downto 0);
        HWRITE            : out   std_logic;
        HWDATA            : out   std_logic_vector(31 downto 0);
        HADDR             : out   std_logic_vector(31 downto 0);
        HMASTLOCK         : out   std_logic;
        HREADY            : out   std_logic;
        HSEL              : out   std_logic;
        HREADYOUT         : in    std_logic;
        HRESP             : in    std_logic;
        HRDATA            : in    std_logic_vector(31 downto 0);
		INT1			  : out   std_logic;
		MASTER1_START     : in    Std_logic;
	    MASTER1_STOP      : in    Std_logic
       );
end;

architecture Fabric_Master1 of Fabric_Master1 is
attribute syn_preserve : boolean;
attribute syn_preserve of Fabric_Master1: architecture is true;

attribute syn_hier : string;
attribute syn_hier of Fabric_Master1 : architecture is "hard" ;


type ahb_master_states is (idle,
							address_phase,
							data_phase,
							loadcountphase,
							int_phase,
							Ld_residualCycles,
							stop_phase
							); 

  signal ahb_states        : ahb_master_states;


 signal HADDR_TEMP        : std_logic_vector(31 downto 0);
 signal HWRITE_DATA_TEMP  : std_logic_vector(31 downto 0); 
 signal INT1_TEMP         : Std_logic;
 signal count_Temp1       : std_logic_vector(31 downto 0);
 signal clock_count       :std_logic_vector(31 downto 0);

		
 signal HREADY_Int0	   	: std_logic;		
 signal HREADY_Int1	   	: std_logic;	

 signal HREADY_rsngedge : std_logic;
 signal HREADY_flngedge	: std_logic;				
 signal HrdyCount       : std_logic_vector(1 downto 0);	
 signal Tr_Enable   	: std_logic; 
 signal Recount			: std_logic_vector(31 downto 0);	
 signal Res_Enable   	: std_logic; 
begin
     
       HMASTLOCK         <= '0';
       HREADY            <= '1';
       HADDR             <= HADDR_TEMP;
       HWDATA            <= HWRITE_DATA_TEMP;
       INT1 			 <= INT1_TEMP;

----------------------------------------------------------------------------------------------------
process (RESET_N,HCLK)
begin

	if(RESET_N ='0')then
		HREADY_Int0 <= '0';
		HREADY_Int1 <= '0';
	else
		if(rising_edge(HCLK))then
			HREADY_Int0  <= HREADYOUT;
			HREADY_Int1	 <= HREADY_Int0; 
		end if;
	end if;
end process;

--------------------------------------------------------------------------------------------------------
process (RESET_N,HCLK)
begin
 if (RESET_N = '0') then
     HrdyCount<= (others => '0');
 else
	if (rising_edge(HCLK)) then
			if(HrdyCount = "10" and ahb_states = data_phase)then  
            	HrdyCount<= (others => '0');
			elsif(HREADY_flngedge = '1'AND ahb_states = address_phase )then
				HrdyCount <= HrdyCount + '1';
			end if;
	end if; 
  end if;     
end process;
------------------------------------------------------------------------------------------------------------
process (RESET_N,HCLK)
begin
 if (RESET_N = '0') then
    Tr_Enable <=  '0';
 else
	if (rising_edge(HCLK)) then
			if(ahb_states /= data_phase) then
				Tr_Enable <='0';
			elsif(HREADY_flngedge = '1')then  
            	Tr_Enable <= '1';
			else
				
			end if;
	end if; 
  end if;     
end process;
HREADY_flngedge <=   (not HREADYOUT) and (HREADY_Int0);
HREADY_rsngedge <=   (not HREADY_Int0) and   (HREADYOUT) ;
--------------------------------------------eSRAM1 accesses count------------------------------------------------
 process (RESET_N,HCLK)
begin
 if (RESET_N = '0') then
     count_Temp1<= (others => '0');
 else
	if (rising_edge(HCLK)) then
	   	
			if(clock_count = X"00000400" and (ahb_states = int_phase or ahb_states=Ld_residualCycles))then  --resetting on 1024 datas
            	count_Temp1<= (others => '0');
			elsif(HREADY_rsngedge = '1' and Tr_Enable = '1')then

				count_Temp1 <= count_Temp1 + '1';
			end if;
		end if;
	
  end if;     
end process;

---------------------------------------Residue clock transfers count in last access----------------------------------------
process (RESET_N,HCLK)
begin
 if (RESET_N = '0') then
     Recount<= (others => '0');
	 Res_Enable <='0';

elsif(ahb_states <= idle) then
	Recount<= (others => '0');
     Res_Enable <='0';
 else
	if (rising_edge(HCLK)) then
			
				if(clock_count = X"00000400" and ahb_states=loadcountphase and HREADY_flngedge = '1') then
				Recount<=(others => '0');
				Res_Enable <='1';
				end if;
				if(clock_count = X"00000400" and HREADYOUT = '1' and Res_Enable ='0' and HREADY_flngedge = '0')then
				Recount<= Recount + '1';
				end if;
	end if; 
  end if;     
end process;

------------------------------------State transitions ----------------------------------------------------------------------
process(HCLK,RESET_N)
begin

if(RESET_N = '0')then
	ahb_states <= idle;
else
	if(rising_edge(HCLK))then
		case ahb_states is
			  when idle 			=>  if(MASTER1_START = '1' and MASTER1_STOP='0')then  
											ahb_states <= address_phase;
		 					 			end if;
			when address_phase 		=>  if(HrdyCount = "10")then
											ahb_states <= data_phase;
	  						    		end if;			
			when data_phase 		=> 	if(HREADYOUT = '1'and   clock_count(11 downto 0) = X"3FF")then
											ahb_states <= loadcountphase;
										end if;
			when loadcountphase => 		if(HREADYOUT = '1') then	
					    				ahb_states <= Ld_residualCycles;
										end if;	
			when Ld_residualCycles 	=>	if(HREADYOUT = '1') then	
				    					ahb_states <= int_phase;
								 		end if;
			when int_phase	=>  		if(MASTER1_STOP = '1')then
										ahb_states <= stop_phase;
										end if;
			when stop_phase			=>  ahb_states <= idle;

			when others 			=> NULL;				
	
		end case;
	end if;
end if;
end process;
-------------------------------------Output assignments----------------------------------------------------------------------
process(HCLK,RESET_N)
begin

if(RESET_N = '0')then
	   HTRANS            <= "00";
       HWRITE            <= '0';
       HSIZE             <= "00";
	   HADDR_TEMP        <= X"20008000";--eSARM1 
       HWRITE_DATA_TEMP  <= (others =>'0');
   	   INT1_TEMP		 <='0';	
	   clock_count		<= (others => '0');
	 
else 
 if(rising_edge(HCLK))then

		case ahb_states is
			when idle => 
					if(MASTER1_START = '1' and MASTER1_STOP='0' )then
					 HTRANS    <= "10";
        	    	 HSIZE 	   <= "10";
		       		 HSEL 	   <= '1';					  
	            	 HWRITE    <= '1';
					end if;
		   
			when data_phase => 	
				if(HREADYOUT = '1' and  Tr_Enable = '1')then
					 HADDR_TEMP 	 <= HADDR_TEMP + "00000000000000000000000000000100";
	           	 	HWRITE_DATA_TEMP <= HWRITE_DATA_TEMP + '1';
			   	 	clock_count 	 <= clock_count + '1';	
				end if;
			when loadcountphase =>
				 if(HREADYOUT = '1')then
					 HADDR_TEMP 	  <= HADDR_TEMP + 4;
				 end if; 

      			HWRITE_DATA_TEMP <= count_Temp1;
				
			when Ld_residualCycles 	=>	
					
					 if( HREADYOUT = '1')then
					 HADDR_TEMP 	  <= HADDR_TEMP + 4;
					 
					 end if; 
				if(HREADY_flngedge = '1') then
					clock_count	   <= (others => '0');
					end if;
			when int_phase	=>  
					
				
				if(HREADY_flngedge = '1') then
				 	 HWRITE_DATA_TEMP <= Recount;
				 	clock_count	   <= (others => '0');
					INT1_TEMP   <='1';
					
				end if; 
			
			
							       	 
	        when stop_phase	=>
			 HADDR_TEMP        <= X"20008000";
			 HWRITE_DATA_TEMP  <= (others =>'0');
			 HTRANS            <= "00";
           	 HWRITE            <= '0';
             HSEL              <= '0';
             HSIZE             <= "00";
			 clock_count	   <= (others => '0');
			 INT1_TEMP 		   <='0';
			when others => NULL;
 		
		end case;
	end if;
end if;
end process;
         
end Fabric_Master1;


