
--
-- Small Asynchronous FIFO
--

library ieee;
use ieee.std_logic_1164.all;


-- synthesis translate_off
library UNISIM;
use UNISIM.all;
-- synthesis translate_on

entity async_fifo is
  generic (
    width : natural := 32);
  port (
    wclk    : in  std_logic;
    rst     : in  std_logic;
    wadv    : in  std_logic;
    wdata   : in  std_logic_vector(width-1 downto 0);
    wnfull  : out std_logic;
    wfull   : out std_logic;
    rclk    : in  std_logic;
    radv    : in  std_logic;
    rdata   : out std_logic_vector(width-1 downto 0);
    rdw_out : out std_logic_vector(width-1 downto 0);
    rempty  : out std_logic;
    rnempty : out std_logic
    );

end async_fifo;

architecture rtl of async_fifo is

  component async_bram_fifo
    port (
      din        : in  std_logic_vector(31 downto 0);
      rd_clk     : in  std_logic;
      rd_en      : in  std_logic;
      rst        : in  std_logic;
      wr_clk     : in  std_logic;
      wr_en      : in  std_logic;
      dout       : out std_logic_vector(31 downto 0);
      empty      : out std_logic;
      full       : out std_logic;
      prog_empty : out std_logic;
      prog_full  : out std_logic);
  end component;

  component async_bram_fifo64
    port (
      din        : in  std_logic_vector(63 downto 0);
      rd_clk     : in  std_logic;
      rd_en      : in  std_logic;
      rst        : in  std_logic;
      wr_clk     : in  std_logic;
      wr_en      : in  std_logic;
      dout       : out std_logic_vector(63 downto 0);
      empty      : out std_logic;
      full       : out std_logic;
      prog_empty : out std_logic;
      prog_full  : out std_logic);
  end component;

  signal dinl, doutl      : std_logic_vector(31 downto 0);
  signal dinw, doutw      : std_logic_vector(63 downto 0);
  signal rdw_out_i        : std_logic_vector(width-1 downto 0);
  signal remptyl, remptyh : std_logic;
begin

  rdw_out <= rdw_out_i;

  reg_oip : process (rclk, rst)
  begin  -- process reg_oip
    if rst = '1' then                     -- asynchronous reset (active low)
      rdata <= (others => '0');
    elsif rclk'event and rclk = '1' then  -- rising clock edge
      if radv = '1' then
        rdata <= rdw_out_i;
      end if;
    end if;
  end process reg_oip;


  gen_1bram : if width < 33 generate

    dinl(width-1 downto 0) <= wdata;
    rdw_out_i              <= doutl(width-1 downto 0);

    abf0 : async_bram_fifo
      port map (
        din        => dinl,
        rd_clk     => rclk,
        rd_en      => radv,
        rst        => rst,
        wr_clk     => wclk,
        wr_en      => wadv,
        dout       => doutl,
        empty      => rempty,
        full       => wfull,
        prog_empty => rnempty,
        prog_full  => wnfull);

  end generate gen_1bram;

  gen_2bram : if width > 32 generate
    dinw(width-1 downto 0) <= wdata;
    rdw_out_i              <= doutw(width-1 downto 0);

    abf0 : async_bram_fifo64
      port map (
        din        => dinw,
        rd_clk     => rclk,
        rd_en      => radv,
        rst        => rst,
        wr_clk     => wclk,
        wr_en      => wadv,
        dout       => doutw,
        empty      => rempty,
        full       => wfull,
        prog_empty => rnempty,
        prog_full  => wnfull);

  end generate gen_2bram;
  


end rtl;
