-- A bridge between the read side of a native FIFO and the Flexelerator's "enable" signal technique


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity fifo_to_enable is
port(

	-- Input from FIFO:
	din : in std_logic_vector;
	rden : out std_logic;
	empty : in std_logic;
	
	-- Output with enable:
	data : out std_logic_vector;
	valid : out std_logic;
	enable : in std_logic;
	
	clk : in std_logic;
	reset : in std_logic
	
	);
	
end entity;

architecture behavioral of fifo_to_enable is

	signal s_rden : std_logic := '0';
	signal s_rden_d : std_logic := '0';
	signal s_valid : std_logic := '0';
	
	subtype t_data is std_logic_vector( din'range );
	type t_data_buffer is array( 1 to 2 ) of t_data;
	signal s_data_buffer : t_data_buffer := ( others => ( others => '0' ) );
	
	signal s_cntr : natural range 0 to 3;
	
begin
	
	
	s_rden <= '1' when empty = '0' and enable = '1' and reset = '0' and s_cntr < 3 else '0';
	rden <= s_rden;
	s_valid <= '1' when s_cntr > 0 and enable = '1' and reset = '0' else '0';
	valid <= s_valid;
	data <= s_data_buffer( 1 );
		
	-- Delayed rden:
	delayed_rden : process( clk ) is
	begin
		if( rising_edge( clk ) ) then
			s_rden_d <= s_rden;
		end if;
	end process;
	
	data_manipulation : process( clk ) is
	begin
		if( rising_edge( clk ) ) then
			
			if( s_valid = '1' ) then
				s_data_buffer(1) <= s_data_buffer(2);
				--s_data_buffer(2) <= s_data_buffer(3);
			end if;
					
			if( reset = '1' ) then
				s_cntr <= 0;
			elsif( s_rden_d = '1' and s_valid = '0' ) then
				s_cntr <= s_cntr + 1;
				s_data_buffer( s_cntr + 1 ) <= din;
			elsif( s_rden_d = '1' and s_valid = '1' ) then
				s_data_buffer( s_cntr ) <= din;
			elsif( s_rden_d = '0' and s_valid = '1' ) then
				s_cntr <= s_cntr - 1;
			end if;
			
		end if;
	end process;
	
end architecture;
