-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: Dual-ported register file with asynchrous read

-- 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

-----------------------------------------------------------------------
-- $Header: /tmp/cvsroot/VHDL/lib/misc/bbfifo.vhd,v 1.1 2008-10-20 19:26:01 Jens Exp $
-----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

entity bbfifo is
	Generic 
	(
		depth	   : integer := 2;
		data_width : integer := 8
	);
	Port
	(
		rst			: in  STD_LOGIC;
		clk			: in  STD_LOGIC;
		re			: in  STD_LOGIC;
		we			: in  STD_LOGIC;
		ready		: out STD_LOGIC;
		avail		: out STD_LOGIC;
		din			: in  unsigned(data_width-1 downto 0);
		dout		: out unsigned(data_width-1 downto 0)
	);
end bbfifo;

architecture Behavioral of bbfifo is

	type bucket_array_t is array (0 to depth) of unsigned(data_width-1 downto 0);
	signal req : unsigned(0 to depth);
	signal rdy : unsigned(1 to depth+1);
	signal bucket_array : bucket_array_t; 
	signal ce_in : unsigned(1 to depth);
	signal ce_out : unsigned(1 to depth);
	
begin
	
	req(0)			<= we;
	rdy(depth+1)	<= re;
	ready			<= '1' when req(0 to depth-1) /= (0 to depth-1 => '1') else '0';
	avail			<= req(depth);
	bucket_array(0)	<= din;
	dout			<= bucket_array(depth);
	
gen_ce:
	for i in 1 to depth generate
	begin
		process (rdy, req)
		begin
			ce_in(i) <= not req(i) and req(i-1);
		end process;
	end generate;

gen_rdy:
	for i in 1 to depth generate
	begin
		process (clk)
		begin
			if rising_edge(clk) then
				if rst = '1' then
					rdy(i) <= '1';
				elsif req(i-1) = '1' then
					rdy(i) <= rdy(i+1);
				end if;
			end if;
		end process;
	end generate;

gen_req:
	for i in 1 to depth generate
	begin
		process (clk)
		begin
			if rising_edge(clk) then
				if rst = '1' then
					req(i) <= '0';
				elsif rdy(i+1) = '1' then
					req(i) <= req(i-1);
				end if;
			end if;
		end process;
	end generate;

gen_data:
	for i in 1 to depth generate
	begin
		process (clk)
		begin
			if rising_edge(clk) then
				if rst = '1' then
					bucket_array(i) <= (others => '0');
				elsif req(i-1) = '1' then
					bucket_array(i) <= bucket_array(i-1);
				end if;
			end if;
		end process;
	end generate;

end Behavioral;

