-- altera vhdl_input_version vhdl_2008
-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html)

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity vector_FIFO is
    generic(
        FIFO_DEPTH  : natural := 2;
        DATA_WIDTH  : natural := 32;
        FIFO_WIDTH  : natural
    );
    port
    (
        -- SYSTEM
        clk         : in std_logic;
        reset       : in std_logic;
        -- INPUT
        full        : out std_logic_vector(0 to FIFO_WIDTH-1);
        write       : in std_logic_vector(0 to FIFO_WIDTH-1);
        data_in     : in std_logic_vector(DATA_WIDTH-1 downto 0);
        -- OUTPUT
        empty       : out std_logic_vector(0 to FIFO_WIDTH-1);
        read        : in std_logic;
        data_out    : out std_logic_vector(DATA_WIDTH-1 downto 0)
    );
end entity;

architecture arch of vector_FIFO is
    signal main_full, sup_full, main_empty, sup_empty : std_logic;
    signal sup_data : std_logic_vector(0 to FIFO_WIDTH-1);
    
    -- HACK: Quartus Workaround (Does not support unary or [VHDL 2008])
    function or_reduce(input : std_logic_vector) return std_logic is
        variable ret : std_logic := '0';
    begin
        for i in 0 to input'length-1 loop
            ret := ret or input(i);
        end loop;
        return ret;
    end function;
begin
    
    full    <= (others => (main_full or sup_full));
    empty   <= (not sup_data) or (empty'range => (main_empty or sup_empty));
    
    fifo_main_inst : configuration work.FWFT_FIFO_cfg
        generic map (
            FIFO_DEPTH  => FIFO_DEPTH,
            DATA_WIDTH  => DATA_WIDTH
        )
        port map (
            -- SYSTEM
            reset       => reset,
            clk         => clk,
            -- INPUT
            full        => main_full,
            write       => or_reduce(write), --or write,
            data_in     => data_in,
            -- OUTPUT
            empty       => main_empty,
            read        => read,
            data_out    => data_out,
            -- MISC
            free        => open
        );
        
    fifo_sup_inst : configuration work.FWFT_FIFO_cfg
        generic map (
            FIFO_DEPTH  => FIFO_DEPTH,
            DATA_WIDTH  => FIFO_WIDTH
        )
        port map (
            -- SYSTEM
            reset       => reset,
            clk         => clk,
            -- INPUT
            full        => sup_full,
            write       => or_reduce(write), --or write,
            data_in     => write,
            -- OUTPUT
            empty       => sup_empty,
            read        => read,
            data_out    => sup_data,
            -- MISC
            free        => open
        );
    
end architecture;
