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

Library xpm;
use xpm.vcomponents.all;

-- Read and Write requests are ignored while the FIFO is in a reset state (reset busy signal high)

entity async_fifo is
        generic (
            DATA_WIDTH          : integer := 32;
            FIFO_DEPTH          : integer := 16;    -- (16 - 4194304)
            PROG_EMPTY_THRESH   : integer := 3;     -- MIN:3    MAX:(FIFO_DEPTH-3)
            PROG_FULL_THRESH    : integer := 13     -- MIN:3+CDC_SYNC_STAGES    MAX:(FIFO_DEPTH-3)
        );
        port (
            wr_clk      : in std_logic;
            rd_clk      : in std_logic;
            reset       : in std_logic; --wr_clk synchronous
            wen         : in std_logic;
            ren         : in std_logic;
            empty       : out std_logic;
            almost_empty: out std_logic;
            prog_empty  : out std_logic;
            full        : out std_logic;
            almost_full : out std_logic;
            prog_full   : out std_logic;
            wr_data     : in std_logic_vector(DATA_WIDTH-1 downto 0);
            rd_data     : out std_logic_vector(DATA_WIDTH-1 downto 0)
        );
end entity;

architecture arch of async_fifo is

    --*****SIGNAL DECLARATION*****
    signal rd_busy, wr_busy : std_logic := '0';
    
begin

    xpm_fifo_async_inst : xpm_fifo_async
        generic map (
            CDC_SYNC_STAGES     => 2,
            DOUT_RESET_VALUE    => "0",
            ECC_MODE            => "no_ecc",
            FIFO_MEMORY_TYPE    => "auto",
            FIFO_READ_LATENCY   => 1,
            FIFO_WRITE_DEPTH    => FIFO_DEPTH,
            FULL_RESET_VALUE    => 1,
            PROG_EMPTY_THRESH   => PROG_EMPTY_THRESH,
            PROG_FULL_THRESH    => PROG_FULL_THRESH,
            RD_DATA_COUNT_WIDTH => 1,
            READ_DATA_WIDTH     => DATA_WIDTH,
            READ_MODE           => "std",
            RELATED_CLOCKS      => 0,
            USE_ADV_FEATURES    => "0A0A",
            WAKEUP_TIME         => 0,
            WRITE_DATA_WIDTH    => DATA_WIDTH,
            WR_DATA_COUNT_WIDTH => 1
        )
        port map (
            almost_empty    => almost_empty,
            almost_full     => almost_full,
            data_valid      => open,
            dbiterr         => open,
            dout            => rd_data,
            empty           => empty,
            full            => full,
            overflow        => open,
            prog_empty      => prog_empty,
            prog_full       => prog_full,
            rd_data_count   => open,
            rd_rst_busy     => rd_busy,
            sbiterr         => open,
            underflow       => open,
            wr_ack          => open,
            wr_data_count   => open,
            wr_rst_busy     => wr_busy,
            din             => wr_data,
            injectdbiterr   => '0',
            injectsbiterr   => '0',
            rd_clk          => rd_clk,
            rd_en           => ren and (not rd_busy),
            rst             => reset,
            sleep           => '0',
            wr_clk          => wr_clk,
            wr_en           => wen and (not wr_busy)
        );

end architecture;