----------------------------------------------------------------------------------
-- Company: 
-- Engineer: KIEGAING EMMANUEL/GAMOM
-- 
-- Create Date:    19:51:54 04/19/2011 
-- Design Name: 
-- Module Name:    FIFO_64 - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--FIFO 64 Octets utisé pour les modules d'entrée 
-- ce fifo est de type fwft first word falls throught ce qui 
-- signifie que l'on a toujours la donnée au sommet de la pile en 
-- sortie du fifo. 
-- Dependencies:  RAM_64.vhd
-- 
-- Revision: 08-11-2012
-- Revision 0.01 - File Created
-- Additional Comments: suppression du signal counter_en dans les expressions 
-- 08/11/12 : prise en compte du retard de propagation des infos dans la FIFO.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Library NocLib;
use NocLib.CoreTypes.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity FIFO_64_FWFT is
    Port ( clk : in  STD_LOGIC;
           din : in  STD_LOGIC_VECTOR (Word-1 downto 0);
           rd_en : in  STD_LOGIC;
           srst : in  STD_LOGIC;
           wr_en : in  STD_LOGIC;
           dout : out  STD_LOGIC_VECTOR (Word-1 downto 0);
           empty : out  STD_LOGIC;
           full : out  STD_LOGIC);
end FIFO_64_FWFT;

architecture Behavioral of FIFO_64_FWFT is
-- declaration de la ram 64 octets
COMPONENT RAM_64
	PORT(
		clka : IN std_logic;
		clkb : IN std_logic;
		wea : IN std_logic;
		ena : IN std_logic;
		enb : IN std_logic;
		addra : IN std_logic_vector(5 downto 0);
		addrb : IN std_logic_vector(5 downto 0);
		dia : IN std_logic_vector(Word-1 downto 0);          
		--doa : OUT std_logic_vector(Word-1 downto 0);
		dob : OUT std_logic_vector(Word-1 downto 0)
		);
	END COMPONENT;
type fsm_states is (state0, state1, state2);-- definition du type etat pour le codage des etats des fsm
signal fwft_fsm_state : fsm_states;
type ram_type is array (63 downto 0) of std_logic_vector (Word-1 downto 0);
	signal RAM: ram_type;
-- declaration des signeaux des compteurs
signal push_address_counter : std_logic_vector(5 downto 0);
signal pop_address_counter : std_logic_vector(5 downto 0);
signal fifo_counter : std_logic_vector(5 downto 0);
--autre signaux
signal rd_ready : std_logic:='0';
signal empty_signal : std_logic;
signal full_signal  : std_logic;
signal wr_en_signal : std_logic;
signal rd_en_signal : std_logic;
signal clk_signal :  std_logic;
signal dob_signal : std_logic_vector(Word-1 downto 0);
signal dout_signal : std_logic_vector(Word-1 downto 0);
signal doa_signal : std_logic_vector(Word-1 downto 0);
signal counter_en : std_logic; 

begin

-- ram instantiation de la ram 64 octets du FIFO
--fifo_RAM_64: RAM_64 PORT MAP(
--		clka => clk_signal,
--		clkb => clk_signal,
--		wea => wr_en_signal,
--		ena => wr_en_signal,
--		enb => rd_en_signal,
--		addra => push_address_counter,
--		addrb => pop_address_counter,
--		dia => din,
--		--doa => doa_signal,
--		dob => dob_signal
--	);
-- circuiterie des signaux de validation et d'etat du fifo
wr_en_signal <= wr_en and (not full_signal); -- la donnée est ignorée si le fifo est plein
rd_en_signal <= rd_en and (not empty_signal);-- pas de lecture si le fifo est vide
full_signal <= '1' when fifo_counter = "111111" else
				   '0';
empty_signal <= '1' when rd_ready='0' or unsigned(fifo_counter) = 0  else
					 '0';
clk_signal <= clk;
full <= full_signal;
empty <= empty_signal;

-- sortie du fifo fwft
dout <= dout_signal;

-- le processus des transistion
fwft_fsm_nsl : process(clk)
 begin
    if rising_edge(clk) then
	   if srst = '1' then
		   fwft_fsm_state  <= state0;
		else
		   case fwft_fsm_state  is
					when state0 => if wr_en_signal = '1' then  --tampon vide seule l'écriture est possible
											fwft_fsm_state  <= state1;
										end if;
										
										
					when state1 => --if rd_en_signal = '1' and wr_en_signal='1'  then  --écriture seule dans le tampon
											
											fwft_fsm_state  <= state2;
										--end if;
										
					when state2 => if rd_en_signal = '1' and wr_en_signal='1'  then
											fwft_fsm_state  <= state2;
										elsif rd_en_signal='1' and wr_en_signal='0' and unsigned(fifo_counter) = 1 then --lecture avec écriture
											fwft_fsm_state  <= state0;
										elsif unsigned(fifo_counter) = 0 then
											fwft_fsm_state  <= state0;
										end if;
					
					when others => fwft_fsm_state <= state0;
			end case;
	   end if;
	end if;
 end process;
 -- actions associées à la fsm
 -- mux qui oriente les sortie doa et dob vers out
 val_fwft:process (fwft_fsm_state,dob_signal)
 
 begin
 case fwft_fsm_state  is
					when state0 => 
		
						dout_signal <= dob_signal;
						counter_en   <= '0';
						rd_ready <='0';
					when state1 => 
		
						dout_signal <= dob_signal;
						counter_en   <= '1';
						rd_ready <='0';
					when state2 => 
		
						dout_signal <= dob_signal;
						counter_en   <= '1';
						rd_ready <='1';
					when others =>
	               dout_signal <= dob_signal;
						counter_en   <= '0';
						rd_ready <='0';
		end case;
end process;
doa_latch_process : process(clk)
begin
  if rising_edge(clk) then
		if wr_en_signal ='1'  then
			doa_signal <= din;
		end if;
  end if;
end process;
	               
-- processus de comptage des adresses d'empilement
push_process : process(clk)
 begin
 if rising_edge(clk) then
   if srst = '1' then
	 push_address_counter <= (others =>'0');
	elsif wr_en_signal ='1' then
			RAM(conv_integer(push_address_counter)) <=din;
	   	push_address_counter <= push_address_counter +1;
	 end if;
 end if;
end process;
 
 -- processus de comptage des adresses depilement du fifo
pop_process : process(clk)
 begin
 if rising_edge(clk) then
   if srst = '1' then
	  pop_address_counter <= (others =>'0');
	elsif rd_en_signal ='1' then
		pop_address_counter <= pop_address_counter +1;
	end if;
 end if;
 end process;
  dob_signal<=RAM(conv_integer(pop_address_counter));
 -- processus de comptage des octets dans le fifo
 fifo_counter_process : process(clk)
 variable count : std_logic_vector(5 downto 0):= (others=>'0');
begin
 if rising_edge(clk) then
   if srst = '1' then
	 fifo_counter <= (others =>'0');
	 count:=(others =>'0');
	else
	 if wr_en_signal ='1'  and rd_en_signal ='0' then 
			count:=count+1;
	  end if;
	 if rd_en_signal ='1' and wr_en_signal ='0' and counter_en='1' then
			count:=count-1;		
	 end if;
	 fifo_counter<=count;
  end if;
 end if;
end process;

end Behavioral;

