---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 16:04:58 09/24/2009 -- Design Name: -- Module Name: FIFO - beh -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.all; -- clk and reset needed for FIFO. rd increments to read pointer to the next element -- in the queue (actually removes an element), r_data is ALWAYS available on the output -- and is defined by the current value of the r_ptr_reg. When wr is asserted, on next -- rising edge, w_data is placed into the FIFO and THEN the w_ptr_reg is incremented. -- After initialization, both r_ptr_reg and w_ptr_reg point to the same element in -- the FIFO. entity FIFO is Generic( NUM_DATA_BITS: natural := 8; NUM_ADDR_BITS: natural := 4); Port ( clk : in std_logic; reset : in std_logic; rd, wr : in std_logic; w_data : in std_logic_vector(NUM_DATA_BITS-1 downto 0); empty, full : out std_logic; r_data : out std_logic_vector(NUM_DATA_BITS-1 downto 0) ); end FIFO; ---------------------------------------------------------------------------------- -- All operations occur in one clock cycle architecture beh of FIFO is type reg_file_type is array (2**NUM_ADDR_BITS-1 downto 0) of std_logic_vector(NUM_DATA_BITS-1 downto 0); signal array_reg : reg_file_type; signal w_ptr_reg, w_ptr_next, w_ptr_succ : std_logic_vector(NUM_ADDR_BITS-1 downto 0); signal r_ptr_reg, r_ptr_next, r_ptr_succ : std_logic_vector(NUM_ADDR_BITS-1 downto 0); signal full_reg, empty_reg, full_next, empty_next : std_logic; signal wr_op : std_logic_vector(1 downto 0); signal wr_en : std_logic; begin -- Read port. After initialization, register 0's value is held on the output port r_data <= array_reg(to_integer(unsigned(r_ptr_reg))); -- Write enabled ONLY when FIFO is not full wr_en <= wr and (not full_reg); ---------------------------------- -- register file ---------------------------------- process (clk, reset) begin if ( reset = '1' ) then array_reg <= (others => (others => '0')); elsif ( clk'event and clk = '1' ) then if ( wr_en = '1' ) then array_reg(to_integer(unsigned(w_ptr_reg))) <= w_data; end if; end if; end process; ---------------------------------- -- FIFO sequential logic ---------------------------------- process (clk, reset) begin if (reset = '1') then w_ptr_reg <= (others => '0'); r_ptr_reg <= (others => '0'); full_reg <= '0'; empty_reg <= '1'; elsif (clk'event and clk = '1') then w_ptr_reg <= w_ptr_next; r_ptr_reg <= r_ptr_next; full_reg <= full_next; empty_reg <= empty_next; end if; end process; -- successive pointer values w_ptr_succ <= std_logic_vector(unsigned(w_ptr_reg)+1); r_ptr_succ <= std_logic_vector(unsigned(r_ptr_reg)+1); ---------------------------------- -- FIFO next state logic ---------------------------------- wr_op <= wr & rd; process (w_ptr_reg, w_ptr_succ, r_ptr_reg, r_ptr_succ, wr_op, empty_reg, full_reg) begin -- defaults w_ptr_next <= w_ptr_reg; r_ptr_next <= r_ptr_reg; full_next <= full_reg; empty_next <= empty_reg; -- case out requested operation case wr_op is -- no op when "00" => -- read when "01" => if ( empty_reg /= '1' ) then r_ptr_next <= r_ptr_succ; full_next <= '0'; if ( r_ptr_succ = w_ptr_reg ) then empty_next <= '1'; end if; end if; -- write when "10" => if ( full_reg /= '1' ) then w_ptr_next <= w_ptr_succ; empty_next <= '0'; if ( w_ptr_succ = r_ptr_reg ) then full_next <= '1'; end if; end if; -- write/read when others => w_ptr_next <= w_ptr_succ; r_ptr_next <= r_ptr_succ; end case; end process; -- output state full <= full_reg; empty <= empty_reg; end beh;