BlinkenArea - GitList
Repositories
Blog
Wiki
mips_sys
Code
Commits
Branches
Tags
Search
Tree:
902aa40
Branches
Tags
master
mips_sys
blocks
fifo_dc.vhd
replace email address in headers with blinkenarea address
Stefan Schuermans
commited
902aa40
at 2012-05-21 17:42:50
fifo_dc.vhd
Blame
History
Raw
-- MIPS I system -- Copyright 2011-2012 Stefan Schuermans <stefan@blinkenarea.org> -- Copyleft GNU public license V2 or later -- http://www.gnu.org/copyleft/gpl.html LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY e_block_fifo_dc IS GENERIC ( addr_width: natural; data_width: natural ); PORT ( rst: IN std_logic; wr_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; rd_clk: 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_dc; ARCHITECTURE a_block_fifo_dc OF e_block_fifo_dc IS COMPONENT e_block_rwram_dc GENERIC ( addr_width: natural; data_width: natural := 8 ); PORT ( rd_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); wr_clk: IN std_logic; 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_dc; SUBTYPE t_pos 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_rd_begin: t_pos := 0; SIGNAL n_rd_begin: t_pos; SIGNAL s_rd_begin_addr: t_addr; SIGNAL s_rd_begin_sn_addr: t_addr; -- _sn_ means sometimes next SIGNAL s_rd_rdy: std_logic; SIGNAL s_rd_en: std_logic; SIGNAL r_if_begin_addr: t_addr := (OTHERS => '0'); SIGNAL r_wr_begin_addr: t_addr := (OTHERS => '0'); SIGNAL r_wr_end: t_pos := 0; SIGNAL n_wr_end: t_pos; SIGNAL s_wr_end_addr: t_addr; SIGNAL s_wr_end_an_addr: t_addr; -- _an_ means always next SIGNAL s_wr_rdy: std_logic; SIGNAL s_wr_en: std_logic; SIGNAL r_if_end_addr: t_addr := (OTHERS => '0'); SIGNAL r_rd_end_addr: t_addr := (OTHERS => '0'); 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; FUNCTION to_gray ( pos: natural RANGE 0 TO 2 ** addr_width - 1 ) RETURN std_logic_vector IS VARIABLE v_pos: std_logic_vector(addr_width - 1 DOWNTO 0); VARIABLE v_shifted: std_logic_vector(addr_width - 1 DOWNTO 0); BEGIN v_pos := std_logic_vector(to_unsigned(pos, addr_width)); v_shifted := "0" & v_pos(addr_width - 1 DOWNTO 1); RETURN v_pos XOR v_shifted; END FUNCTION to_gray; BEGIN i_rwram: e_block_rwram_dc GENERIC MAP ( addr_width => addr_width, data_width => data_width ) PORT MAP ( rd_clk => rd_clk, i_rd_addr => s_rd_begin_sn_addr, o_rd_data => o_rd_data, wr_clk => wr_clk, i_wr_addr => s_wr_end_addr, i_wr_data => i_wr_data, i_wr_en => s_wr_en ); s_rd_begin_addr <= to_gray(r_rd_begin); s_rd_begin_sn_addr <= to_gray(n_rd_begin); s_rd_rdy <= '1' WHEN s_rd_begin_addr /= r_rd_end_addr ELSE '0'; s_rd_en <= s_rd_rdy AND i_rd_en; o_rd_rdy <= s_rd_rdy; p_rd_next: PROCESS(r_rd_begin, s_rd_en) BEGIN n_rd_begin <= r_rd_begin; IF s_rd_en = '1' THEN n_rd_begin <= next_pos(r_rd_begin); END IF; END PROCESS p_rd_next; p_rd_sync: PROCESS(rst, rd_clk) BEGIN IF rst = '1' THEN r_rd_begin <= 0; ELSIF rising_edge(rd_clk) THEN r_rd_begin <= n_rd_begin; END IF; END PROCESS p_rd_sync; p_rd_if: PROCESS(rst, rd_clk) BEGIN IF rst = '1' THEN r_if_begin_addr <= (OTHERS => '0'); r_rd_end_addr <= (OTHERS => '0'); ELSIF rising_edge(rd_clk) THEN r_if_begin_addr <= s_rd_begin_addr; r_rd_end_addr <= r_if_end_addr; END IF; END PROCESS p_rd_if; s_wr_end_addr <= to_gray(r_wr_end); s_wr_end_an_addr <= to_gray(next_pos(r_wr_end)); s_wr_rdy <= '1' WHEN s_wr_end_an_addr /= r_wr_begin_addr ELSE '0'; s_wr_en <= s_wr_rdy AND i_wr_en; o_wr_rdy <= s_wr_rdy; p_wr_next: PROCESS(r_wr_end, s_wr_en) BEGIN n_wr_end <= r_wr_end; IF s_wr_en = '1' THEN n_wr_end <= next_pos(r_wr_end); END IF; END PROCESS p_wr_next; p_wr_sync: PROCESS(rst, wr_clk) BEGIN IF rst = '1' THEN r_wr_end <= 0; ELSIF rising_edge(wr_clk) THEN r_wr_end <= n_wr_end; END IF; END PROCESS p_wr_sync; p_wr_if: PROCESS(rst, wr_clk) BEGIN IF rst = '1' THEN r_if_end_addr <= (OTHERS => '0'); r_wr_begin_addr <= (OTHERS => '0'); ELSIF rising_edge(wr_clk) THEN r_if_end_addr <= s_wr_end_addr; r_wr_begin_addr <= r_if_begin_addr; END IF; END PROCESS p_wr_if; END ARCHITECTURE a_block_fifo_dc;