LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY e_block_fifo IS GENERIC ( addr_width: natural; data_width: natural ); PORT ( rst: IN std_logic; clk: IN std_logic; o_wr_rdy: OUT std_logic; i_wr_data: IN std_logic_vector(data_width - 1 DOWNTO 0); i_wr_en: IN std_logic; o_rd_rdy: OUT std_logic; o_rd_data: OUT std_logic_vector(data_width - 1 DOWNTO 0); i_rd_en: IN std_logic ); END ENTITY e_block_fifo; ARCHITECTURE a_block_fifo OF e_block_fifo IS COMPONENT e_block_rwram GENERIC ( addr_width: natural; data_width: natural := 8 ); PORT ( clk: IN std_logic; i_rd_addr: IN std_logic_vector(addr_width - 1 DOWNTO 0); o_rd_data: OUT std_logic_vector(data_width - 1 DOWNTO 0); i_wr_addr: IN std_logic_vector(addr_width - 1 DOWNTO 0); i_wr_data: IN std_logic_vector(data_width - 1 DOWNTO 0); i_wr_en: IN std_logic ); END COMPONENT e_block_rwram; SUBTYPE t_addr_n IS natural RANGE 0 TO 2 ** addr_width - 1; SUBTYPE t_addr IS std_logic_vector(addr_width - 1 DOWNTO 0); SUBTYPE t_data IS std_logic_vector(data_width - 1 DOWNTO 0); SIGNAL r_begin: t_addr_n := 0; SIGNAL r_end: t_addr_n := 0; SIGNAL r_end_dly1: t_addr_n := 0; SIGNAL r_end_dly2: t_addr_n := 0; SIGNAL r_begin_chgd: std_logic := '0'; SIGNAL r_ram_wr_addr: t_addr := (OTHERS => '0'); SIGNAL r_ram_wr_data: t_data := (OTHERS => '0'); SIGNAL r_ram_wr_en: std_logic := '0'; SIGNAL s_ram_rd_addr: t_addr; SIGNAL s_rd_rdy: std_logic; SIGNAL s_wr_rdy: std_logic; FUNCTION next_pos ( pos: natural RANGE 0 TO 2 ** addr_width - 1 ) RETURN natural IS VARIABLE v_next: natural RANGE 0 TO 2 ** addr_width - 1; BEGIN IF pos = 2 ** addr_width - 1 THEN v_next := 0; ELSE v_next := pos + 1; END IF; RETURN v_next; END FUNCTION next_pos; BEGIN s_ram_rd_addr <= std_logic_vector(to_unsigned(r_begin, addr_width)); s_rd_rdy <= '0' WHEN r_begin = r_end OR r_begin_chgd = '1' ELSE '1'; s_wr_rdy <= '0' WHEN r_begin = next_pos(r_end) ELSE '1'; o_rd_rdy <= s_rd_rdy; o_wr_rdy <= s_wr_rdy; i_rwram: e_block_rwram GENERIC MAP ( addr_width => addr_width, data_width => data_width ) PORT MAP ( clk => clk, i_rd_addr => s_ram_rd_addr, o_rd_data => o_rd_data, i_wr_addr => r_ram_wr_addr, i_wr_data => r_ram_wr_data, i_wr_en => r_ram_wr_en ); p_fifo: PROCESS(rst, clk) BEGIN IF rst = '1' THEN r_begin <= 0; r_end <= 0; r_end_dly1 <= 0; r_end_dly2 <= 0; r_begin_chgd <= '0'; r_ram_wr_addr <= (OTHERS => '0'); r_ram_wr_data <= (OTHERS => '0'); r_ram_wr_en <= '0'; ELSIF rising_edge(clk) THEN -- read IF i_rd_en = '1' AND s_rd_rdy = '1' THEN r_begin <= next_pos(r_begin); r_begin_chgd <= '1'; ELSE r_begin_chgd <= '0'; END IF; -- write IF i_wr_en = '1' AND s_wr_rdy = '1' THEN r_ram_wr_addr <= std_logic_vector(to_unsigned(r_end, addr_width)); r_ram_wr_data <= i_wr_data; r_ram_wr_en <= '1'; r_end_dly2 <= next_pos(r_end); ELSE r_ram_wr_en <= '0'; END IF; -- delay r_end 2 cycles: 1 for writing to RAM, 1 to read RAM r_end_dly1 <= r_end_dly2; r_end <= r_end_dly1; END IF; END PROCESS p_fifo; END ARCHITECTURE a_block_fifo;