----------------------------------------------------------------------------------
-- 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: 30-07-2012
-- Revision 0.01 - File Created
-- Additional Comments: 
-- le signal counter_en a été supprimé
----------------------------------------------------------------------------------
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;
use work.CoreTypes.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity FIFO_256_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_256_FWFT;

architecture Behavioral of FIFO_256_FWFT is
-- declaration de la ram 256 octets
COMPONENT RAM_256
	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(Word-1 downto 0);
		addrb : IN std_logic_vector(Word-1 downto 0);
		dia : IN 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, state3);-- definition du type etat pour le codage des etats des fsm
signal fwft_fsm_state : fsm_states;
type ram_type is array (255 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(Word-1 downto 0);
signal pop_address_counter : std_logic_vector(Word-1 downto 0);
signal fifo_counter : std_logic_vector(Word-1 downto 0);
--autre signaux
signal empty_signal: std_logic:='1';
signal rd_ready : std_logic:='0';
signal full_signal  : std_logic;
signal wr_en_signal : std_logic;--_vector(0 downto 0);
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 bloc ram 256 octets du FIFO
fifo_RAM_256: RAM_256 PORT MAP(
		clka => clk_signal,
		clkb => clk_signal,
		wea => wr_en_signal,
		ena => '1',
		enb => '1',
		addra => push_address_counter,
		addrb => pop_address_counter,
		dia => din,
		dob => doa_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 = "11111111" else
				   '0';
--empty_signal <= '1' when fifo_counter = "000000"  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_signal)
 begin
    if rising_edge(clk_signal) 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 state3 => if rd_en_signal = '1' then  --écriture seule dans le tampon
											fwft_fsm_state  <= state0;
										elsif wr_en_signal='1' then
											fwft_fsm_state  <= state2;
										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
 with fwft_fsm_state select
    dout_signal <= dob_signal when state0, 
	                dob_signal when state1, --la sortie est la donnée en entrée
	                dob_signal when state2, -- la sortie vient de la RAM
						 dob_signal when state3,
						 doa_signal when others;
 -- counter_en
 with fwft_fsm_state select
    counter_en   <= '0' when state0, 
	                 '1' when state1,
	                 '1' when state2,
						  '1' when state3,	
						  '0' when others;
						  
with fwft_fsm_state select
    rd_ready   <= '0' when state0, 
	                 '0' when state1,
	                 '1' when state2,
						  '1' when state3,	
						  '0' when others;
doa_latch_process : process(clk_signal)
begin
  if rising_edge(clk_signal) 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_signal)
 begin
 if rising_edge(clk_signal) 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_signal)
 begin
 if rising_edge(clk_signal) then
   if srst = '1' then
	  pop_address_counter <= (others =>'0'); --pour avoir un décalage entre la valeur lue et celle qui est écrite
	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_signal)
variable count : std_logic_vector(word-1 downto 0):= (others=>'0');
begin
 if rising_edge(clk_signal) then
   if srst = '1' then
	 fifo_counter <= (others =>'0');
	 count:=(others =>'0');
	else
	 if wr_en_signal ='1'  and rd_en_signal ='0' then 
		--fifo_counter <= fifo_counter +1;
		count:=count+1;
	  end if;
	 if rd_en_signal ='1' and wr_en_signal ='0' and counter_en='1' then
		--fifo_counter <= fifo_counter - 1;
		count:=count-1;		
	 end if;
	 fifo_counter<=count;
  end if;
 end if;
end process;

end Behavioral;

