----------------------------------------------------------------------------------
-- Company:        CERN, BE-CO-HT 
-- Engineer:       Carlos Gil Soriano
-- 
-- Create Date:    10:33:33 11/08/2011 
-- Design Name:    FIFO variable stack length
-- Module Name:    FIFO_stack - Behavioral 
-- Project Name:   CTDAH
-- Target Devices: Spartan 6
-- Tool versions: 
-- Description:    This module implements a generic FIFO stack of variable
--                 data input length and stack depth. The ASCII art represents
--                 the behaviour of the module, which works as a g_stack_depth
--                 delay with parallel output
--
--    input--->    
--             |          |
--             |----------|
--             |   REG 0  | ---> reg_o LSB
--             |----------|
--             |   REG 1  | ---> 
--             |----------|
--             |   REG 2  | ---> 
--             |----------|
--             |   REG 3  | ---> reg_o MSB
--             |__________|
--          
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity FIFO_stack is
   generic(
      g_data_width  : NATURAL := 8;
      g_stack_depth : NATURAL := 8
   );
   port (
      reg_i  : in   STD_LOGIC_VECTOR (g_data_width-1 downto 0);
      clk    : in   STD_LOGIC;
      push   : in   STD_LOGIC;
      flush  : in   STD_LOGIC;
      reg_o  : out  STD_LOGIC_VECTOR (g_stack_depth*g_data_width - 1 downto 0)
   );
end FIFO_stack;

architecture Behavioral of FIFO_stack is

type FIFO_REG is array(0 to g_stack_depth-1) of std_logic_vector(g_data_width - 1 downto 0); 

signal reg_int : FIFO_REG;

begin
   
   reg_o((g_stack_depth)*g_data_width-1 downto (g_stack_depth-1)*g_data_width ) <= reg_int(g_stack_depth-1);

   gen_out: for i in 0 to g_stack_depth-2 generate
      reg_o((i+1)*g_data_width-1 downto i*g_data_width ) <= reg_int(i);
   end generate gen_out;

   reg_proc: process(clk)
   begin

     if rising_edge(clk) then
       if flush = '1' then
         for i in 0 to g_stack_depth-1 loop
           reg_int(i)   <= (others => '0');
         end loop;
       elsif push = '1' then
         reg_int(0)      <= reg_i;
         for i in 0 to g_stack_depth-2 loop
           reg_int(i+1) <= reg_int(i);
         end loop; 
       else
       end if;
     end if;

   end process;

end Behavioral;
