-------------------------------------------------------------------------
-- Project: FIFO, generic FIFOs written in VHDL
-- Release 1
--
-- Copyright (C) 2007 J. Ahrensfeld
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
--
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
-----------------------------------------------------------------------

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

use work.fifo_ctrl_pkg.all;

entity fifo_sync is
	Generic 
	(
		addr_width					: natural := 3;
		data_width					: natural := 8;
		almost_full_thresh			: integer := 6;
		almost_empty_thresh			: integer := 2;
		allow_full_writes			: boolean := false;
		allow_empty_reads			: boolean := false;
		do_last_read_update			: boolean := true
		
	);
	Port
	(
		rst			: in  STD_LOGIC;
		clk			: in  STD_LOGIC;
		we				: in  STD_LOGIC;
		re				: in  STD_LOGIC;
		fifo_full	: out STD_LOGIC;
		fifo_empty	: out STD_LOGIC;
		fifo_afull	: out STD_LOGIC;
		fifo_aempty	: out STD_LOGIC;
		data_w		: in  unsigned (data_width-1 downto 0);
		data_r		: out unsigned (data_width-1 downto 0)
	);
end fifo_sync;

architecture Behavioral of fifo_sync is
	
	signal mem_wr_en	: STD_LOGIC;
	signal mem_rd_en	: STD_LOGIC;
	signal ptr_w		: unsigned (addr_width-1 downto 0);
	signal ptr_r		: unsigned (addr_width-1 downto 0);
	signal full			: STD_LOGIC;
	signal empty		: std_logic;
	signal pre_empty	: STD_LOGIC;
	signal rinc			: std_logic;
	
begin

	fifo_full	<= full;
	fifo_empty	<= empty;

	mem_wr_en	<= (we and not full) when allow_full_writes = false else we;
	rinc		<= (re and not empty) when allow_empty_reads = false else re;
	mem_rd_en	<= not pre_empty when do_last_read_update = false else '1';


inst_fifo_sync_ctrl: entity work.fifo_sync_ctrl
	GENERIC MAP
	(
		addr_width			=> addr_width,
		almost_full_thresh	=> almost_full_thresh,
		almost_empty_thresh	=> almost_empty_thresh
	)
	PORT MAP
	(
		rst				=>	rst,
		clk				=>	clk,
		winc			=>	mem_wr_en,
		rinc			=>	rinc,
		ptr_w			=>	ptr_w,
		ptr_r			=>	ptr_r,
		fifo_full		=>	full,
		fifo_empty		=>	empty,
		fifo_pre_full	=>	open,
		fifo_pre_empty	=>	pre_empty,
		fifo_afull		=>	fifo_afull,
		fifo_aempty		=>	fifo_aempty

	);

inst_dpram_1w1r2c: entity work.dpram_1w1r2c_ra
	GENERIC MAP
	(
		addr_width	=> addr_width,
		data_width	=> data_width
	)
	PORT MAP(
		clk_a		=> clk,
		clk_b		=> clk,
		we_a		=> mem_wr_en,
		re_b		=> mem_rd_en,
		addr_a	=> ptr_w,
		addr_b	=> ptr_r,
		din_a		=> data_w,
		dout_b	=> data_r
	);

end Behavioral;

