----------------------------------------------------------------------------------
-- Company:        CERN, BE-CO-HT 
-- Engineer:       Carlos Gil Soriano
-- 
-- Create Date:    18:28:55 11/08/2011 
-- Design Name:    FIFO dispatcher with parallel load
-- Module Name:    FIFO_dispatcher - Behavioral 
-- Project Name:   CTDAH
-- Target Devices: Spartan 6
-- Tool versions: 
-- Description:    This is a FIFO dispathcher with parallel load and flush.
--
--                    |          |
--                    |----------|
--     reg_i LSB ---> |   REG 0  |
--                    |----------|
--               ---> |   REG 1  | 
--                    |----------|
--               ---> |   REG 2  | 
--                    |----------|
--     reg_i MSB ---> |   REG 3  | ---> reg_o
--                    |__________|
--
-- Dependencies:   none 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity FIFO_dispatcher is
   generic(
      g_data_width       : NATURAL := 8;
      g_dispatcher_depth : NATURAL := 4
   );
   port (
      reg_i  : in  STD_LOGIC_VECTOR (g_dispatcher_depth*g_data_width-1 downto 0);
      clk    : in  STD_LOGIC;
      load   : in  STD_LOGIC;
      flush  : in  STD_LOGIC;
      oen_i  : in  STD_LOGIC;
      reg_o  : out STD_LOGIC_VECTOR (g_data_width - 1 downto 0)
   );
end FIFO_dispatcher;

architecture Behavioral of FIFO_dispatcher is

type DISPATCHER_REG is array(0 to g_dispatcher_depth-1) of STD_LOGIC_VECTOR(g_data_width - 1 downto 0);

signal reg_int : DISPATCHER_REG;

begin

process(clk, flush)

begin

   if flush = '1' then
      flushLoop: for i in 0 to g_dispatcher_depth-1 loop
         reg_int(i)      <= (others => '0');
         reg_o           <= (others => '0');
      end loop;
   elsif rising_edge(clk) then
      if load = '1' then
         loadLoop: for i in 0 to g_dispatcher_depth - 1  loop
            reg_int(i)   <= reg_i((i+1)*g_data_width - 1  downto i*g_data_width) ;
         end loop;
      else
      end if;

      if oen_i = '1' then
         reg_o           <= reg_int(g_dispatcher_depth -1);
         if g_dispatcher_depth > 1 then                  --
            for i in 0 to g_dispatcher_depth - 2 loop
               reg_int(i+1) <= reg_int(i);
            end loop;
         else                                            -- 
         end if;                                            --  
         reg_int(0)      <= (others => '0');
      else
      end if;

   else
   end if;

end process;


end Behavioral;
