123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- --+-----------------------------------+-------------------------------------+--
- --| ___ ___ | (c) 2013-2014 William R Sowerbutts |--
- --| ___ ___ ___ ___( _ ) / _ \ | will@sowerbutts.com |--
- --| / __|/ _ \ / __|_ / _ \| | | | | |--
- --| \__ \ (_) | (__ / / (_) | |_| | | A Z80 FPGA computer, just for fun |--
- --| |___/\___/ \___/___\___/ \___/ | |--
- --| | http://sowerbutts.com/ |--
- --+-----------------------------------+-------------------------------------+--
- --| FIFO implementation with high water mark. Could be improved; currently |--
- --| it is impossible to use the last byte in the FIFO (because it cannot |--
- --| distinguish completely-full from completely-empty) |--
- --+-------------------------------------------------------------------------+--
- library IEEE;
- use IEEE.std_logic_1164.all;
- use IEEE.numeric_std.all;
- entity fifo is
- generic(
- depth_log2 : integer := 10; -- 5 gives 32 bytes, implements without a BRAM.
- hwm_space : integer := 5; -- minimum bytes free in buffer before we assert flow control signals
- width : integer := 8
- );
- port(
- clk : in std_logic;
- reset : in std_logic;
- write_en : in std_logic;
- write_ready : out std_logic; -- is there space to write?
- read_en : in std_logic;
- read_ready : out std_logic; -- is there data waiting to read?
- data_in : in std_logic_vector(width-1 downto 0);
- data_out : out std_logic_vector(width-1 downto 0);
- high_water_mark : out std_logic
- );
- end fifo;
- architecture behaviour of fifo is
- type fifo_entry is array (natural range <>) of std_logic_vector(width-1 downto 0);
- signal fifo_contents : fifo_entry(0 to (2 ** depth_log2) - 1); -- this is the FIFO buffer memory
- signal read_ptr : unsigned(depth_log2-1 downto 0) := (others => '0');
- signal write_ptr : unsigned(depth_log2-1 downto 0) := (others => '0');
- signal full : std_logic;
- signal empty : std_logic;
- begin
- is_empty: process(read_ptr, write_ptr)
- begin
- if read_ptr = write_ptr then
- empty <= '1';
- else
- empty <= '0';
- end if;
- if read_ptr = (write_ptr+1) then
- full <= '1';
- else
- full <= '0';
- end if;
- if (write_ptr - read_ptr) >= ((2 ** depth_log2) - 1 - hwm_space) then
- high_water_mark <= '1';
- else
- high_water_mark <= '0';
- end if;
- end process;
- fifo_update: process(clk)
- begin
- if rising_edge(clk) then
- if reset = '1' then
- -- reset
- read_ptr <= to_unsigned(0, depth_log2);
- write_ptr <= to_unsigned(0, depth_log2);
- else
- -- normal operation
- if write_en = '1' and full = '0' then
- fifo_contents(to_integer(write_ptr)) <= data_in;
- write_ptr <= write_ptr + 1;
- end if;
- if read_en = '1' and empty = '0' then
- read_ptr <= read_ptr + 1;
- end if;
- data_out <= fifo_contents(to_integer(read_ptr));
- end if;
- end if;
- end process;
- write_ready <= not full;
- read_ready <= not empty;
- end;
|