From 19d5dc19d6525cf6ecb9d89201c99795fa9036ae Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sun, 28 Mar 2010 17:04:28 +0000 Subject: [PATCH] - added xfer_info FIFO with byte and word counter information - added reset generator - cleaned up - reception is now working properly Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@835 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/emac/src/emac_rx.vhd | 304 +++++++++++++++++++++------------------ 1 file changed, 167 insertions(+), 137 deletions(-) diff --git a/lib/emac/src/emac_rx.vhd b/lib/emac/src/emac_rx.vhd index a988f8a..6019861 100644 --- a/lib/emac/src/emac_rx.vhd +++ b/lib/emac/src/emac_rx.vhd @@ -37,21 +37,21 @@ ARCHITECTURE behavior OF emac_rx IS subtype word_ptr_t is unsigned(RAM_ADDR_WIDTH-1 downto 0); -- Signals for EMAC connections - signal mii_fifo_din : unsigned(35 downto 0); - signal mii_fifo_dout : unsigned(35 downto 0); + signal mii_fifo_din : unsigned(31 downto 0); + signal mii_fifo_dout : unsigned(31 downto 0); signal mii_fifo_we : std_logic; signal mii_fifo_re : std_logic; signal mii_fifo_empty : std_logic; signal mii_fifo_full : std_logic; - signal cmd_fifo_din : unsigned(35 downto 0); - signal cmd_fifo_dout : unsigned(35 downto 0); + signal cmd_fifo_din : unsigned(31 downto 0); + signal cmd_fifo_dout : unsigned(31 downto 0); signal cmd_fifo_we : std_logic; signal cmd_fifo_re : std_logic; signal cmd_fifo_empty : std_logic; signal cmd_fifo_full : std_logic; - signal flush_en : std_logic; + signal reset_en : std_logic; signal fill_ptr : word_ptr_t; @@ -77,48 +77,56 @@ ARCHITECTURE behavior OF emac_rx IS signal ram_we_b : std_logic; signal ram_addr_b : word_ptr_t; signal ram_din_b : unsigned(31 downto 0); - signal ram_dout_b : unsigned(31 downto 0); - signal sipo_dout : unsigned(31 downto 0); - signal sipo_dout_be : unsigned(3 downto 0); - signal sipo_dout_vld : std_logic; - signal sipo_dout_en : std_logic; - signal sipo_rst : std_logic; - - signal sipo_10mbps_dout : unsigned(7 downto 0); - signal sipo_10mbps_rst : std_logic; - signal sipo_10mbps_dout_vld : std_logic; - signal sipo_10mbps_dout_en : std_logic; - signal byte_active_r : std_logic; - signal word_active_r : std_logic; + signal sipo_32bit_dout : unsigned(31 downto 0); + signal sipo_32bit_dout_be : unsigned(3 downto 0); + signal sipo_32bit_dout_vld : std_logic; + signal sipo_32bit_dout_en : std_logic; + signal sipo_32bit_en : std_logic; + signal sipo_32bit_rst : std_logic; + signal sipo_8bit_dout : unsigned(7 downto 0); + signal sipo_8bit_rst : std_logic; + signal sipo_8bit_dout_vld : std_logic; + signal sipo_8bit_dout_en : std_logic; + signal sipo_8bit_en : std_logic; + + signal byte_count_en : std_logic; signal byte_count : word_ptr_t; signal byte_count_reg : word_ptr_t; - signal byte_count_reg_s : word_ptr_t; signal word_count : word_ptr_t; - signal word_count_reg : word_ptr_t; - signal word_count_set : std_logic; - signal word_count_clr : std_logic; - signal word_count_ack : std_logic; - signal word_count_vld : std_logic; + signal word_count_en : std_logic; + + signal size_fifo_full : std_logic; + signal size_fifo_empty : std_logic; + signal size_fifo_we : std_logic; + signal size_fifo_re : std_logic; + signal size_fifo_din : unsigned(2*word_ptr_t'length-1 downto 0); + signal size_fifo_dout : unsigned(2*word_ptr_t'length-1 downto 0); + + signal reset_pipe : unsigned(31 downto 0); type host_state_t is (host_init, host_flush, host_idle); signal host_s, host_sn : host_state_t; - type xfer_state_t is (xfer_init, xfer_idle, xfer_setup, xfer_active, xfer_drop, xfer_free); + type xfer_state_t is (xfer_init, xfer_idle, xfer_setup, xfer_active, xfer_drop, xfer_commit, xfer_free); signal xfer_s, xfer_sn : xfer_state_t; + type stream_state_t is (stream_init, stream_idle, stream_start, stream_active, stream_stop, stream_finish); + signal stream_s, stream_sn : stream_state_t; + begin ctrl_out.rx_size <= cmd_fifo_dout(31 downto 16); ctrl_out.pkt_avail <= not cmd_fifo_empty; ctrl_out.rx_er <= mii_rx_er; + ctrl_out.reset_busy <= reset_en; dout <= ram_dout_a; - mii_fifo_din <= "0000" & sipo_dout; - mii_fifo_we <= sipo_dout_vld; + mii_fifo_din <= sipo_32bit_dout; + mii_fifo_we <= sipo_32bit_dout_vld; ram_en_a <= '1'; ram_din_a <= (others => '-'); @@ -126,53 +134,30 @@ begin ram_we_a <= '0'; ram_en_b <= '1'; - ram_din_b <= mii_fifo_dout(31 downto 0); + ram_din_b <= mii_fifo_dout; ram_addr_b <= xfer_ptr; ram_we_b <= xfer_ptr_adv; cmd_fifo_we <= commit_en; cmd_fifo_re <= ctrl_in.pkt_free_en; - cmd_fifo_din <= "0000" & resize(byte_count_reg_s, 16) & resize(xfer_base, 16); + cmd_fifo_din <= resize(size_fifo_dout(word_ptr_t'length-1 downto 0), 16) & resize(xfer_base, 16); + + size_fifo_din <= word_count & byte_count_reg; + reset_en <= reset_pipe(reset_pipe'left); ------------------------------------------------------------------ -host_state_next: +reset_gen: process(clk) begin if rising_edge(clk) then - if rst = '1' then - host_s <= host_init; + if rst = '1' or ctrl_in.reset = '1' then + reset_pipe <= (others => '1'); else - host_s <= host_sn; + reset_pipe <= reset_pipe(reset_pipe'left-1 downto 0) & '0'; end if; end if; end process; -host_state: - process(host_s) - begin - - flush_en <= '0'; - - host_sn <= host_s; - - case host_s is - - when host_init => - flush_en <= '1'; - host_sn <= host_flush; - - when host_flush => - flush_en <= '1'; - host_sn <= host_idle; - - when host_idle => - - when others => - host_sn <= host_idle; - end case; - - end process; - ------------------------------------------------------------------ -- Fill stuff ------------------------------------------------------------------ @@ -196,7 +181,7 @@ xfer_state_next: process(clk) begin if rising_edge(clk) then - if rst = '1' then + if reset_en = '1' then xfer_s <= xfer_init; else xfer_s <= xfer_sn; @@ -205,7 +190,7 @@ xfer_state_next: end process; xfer_state: - process(xfer_s, mii_fifo_empty, xfer_rdy, xfer_ram_full) + process(xfer_s, size_fifo_empty, mii_fifo_empty, xfer_rdy, xfer_ram_full) begin commit_en <= '0'; @@ -213,7 +198,7 @@ xfer_state: xfer_ptr_adv <= '0'; xfer_cnt_set <= '0'; xfer_cnt_adv <= '0'; - word_count_ack <= '0'; + size_fifo_re <= '0'; mii_fifo_re <= '0'; xfer_sn <= xfer_s; @@ -239,8 +224,8 @@ xfer_state: xfer_ptr_adv <= not mii_fifo_empty; if xfer_ram_full = '1' then xfer_sn <= xfer_drop; - elsif xfer_rdy = '1' then - if mii_fifo_empty = '1' then + elsif size_fifo_empty = '0' then + if xfer_rdy = '1' then xfer_sn <= xfer_free; end if; end if; @@ -248,14 +233,14 @@ xfer_state: when xfer_drop => mii_fifo_re <= '1'; xfer_cnt_adv <= not mii_fifo_empty; - if xfer_rdy = '1' then - if mii_fifo_empty = '1' then + if size_fifo_empty = '0' then + if xfer_rdy = '1' then xfer_sn <= xfer_free; end if; end if; when xfer_free => - word_count_ack <= '1'; + size_fifo_re <= '1'; commit_en <= not xfer_ram_full; xfer_sn <= xfer_idle; @@ -270,9 +255,9 @@ pkt_lost_register: process(clk) begin if rising_edge(clk) then - if flush_en = '1' then + if reset_en = '1' then ctrl_out.pkt_lost <= '0'; - elsif word_count_ack = '1' and xfer_ram_full = '1' then + elsif size_fifo_re = '1' and xfer_ram_full = '1' then ctrl_out.pkt_lost <= '1'; elsif ctrl_in.pkt_free_en = '1' then ctrl_out.pkt_lost <= '0'; @@ -300,7 +285,7 @@ xfer_ram_full_detect: process(clk) begin if rising_edge(clk) then - if xfer_ptr_set = '1' or flush_en = '1' then + if xfer_ptr_set = '1' or reset_en = '1' then xfer_ram_full <= '0'; elsif xfer_ptr_adv = '1' then if xfer_ptr = xfer_ram_limit then @@ -315,9 +300,10 @@ xfer_counter: process(clk) begin if rising_edge(clk) then - xfer_rdy <= '0'; - if xfer_size = word_count_reg then - xfer_rdy <= word_count_vld; + if xfer_cnt_set = '1' then + xfer_rdy <= '0'; + elsif xfer_size = size_fifo_dout(size_fifo_dout'left downto word_ptr_t'length) then + xfer_rdy <= '1'; end if; if xfer_cnt_set = '1' then xfer_size <= (others => '0'); @@ -345,7 +331,7 @@ xfer_base_logic: process(clk) begin if rising_edge(clk) then - if flush_en = '1' then + if reset_en = '1' then xfer_base <= (others => '0'); elsif commit_en = '1' then xfer_base <= xfer_ptr; @@ -358,12 +344,11 @@ byte_counter: process(mii_rx_clk) begin if rising_edge(mii_rx_clk) then - if sipo_10mbps_dout_en = '0' then + if sipo_8bit_rst = '1' then byte_count <= (others => '0'); - elsif sipo_10mbps_dout_vld = '1' then + elsif byte_count_en = '1' and sipo_8bit_dout_vld = '1' then byte_count <= byte_count + 1; end if; - byte_active_r <= sipo_10mbps_dout_en; end if; end process; @@ -371,9 +356,7 @@ byte_count_register: process(mii_rx_clk) begin if rising_edge(mii_rx_clk) then - if rst = '1' then - byte_count_reg <= (others => '0'); - elsif byte_active_r = '1' and sipo_10mbps_dout_vld = '0' then + if sipo_8bit_rst = '1' then byte_count_reg <= byte_count; end if; end if; @@ -383,58 +366,84 @@ word_counter: process(mii_rx_clk) begin if rising_edge(mii_rx_clk) then - word_active_r <= sipo_dout_en; - if rst = '1' or word_count_clr = '1' then + if sipo_32bit_rst = '1' then word_count <= (others => '0'); - elsif sipo_dout_vld = '1' then + elsif word_count_en = '1' and sipo_32bit_dout_vld = '1' then word_count <= word_count + 1; end if; end if; end process; --- MII doamin -word_count_set_logic: +------------------------------------------------------------------ +stream_state_next: process(mii_rx_clk) begin if rising_edge(mii_rx_clk) then - if rst = '1' or word_count_clr = '1' then - word_count_set <= '0'; - elsif word_active_r = '1' and sipo_dout_en = '0' then - word_count_set <= '1'; - end if; - end if; - end process; - --- Host doamin -word_count_clr_logic: - process(clk) - begin - if rising_edge(clk) then - if rst = '1' then - word_count_clr <= '0'; - elsif word_count_set = '1' then - if word_count_ack = '1' then - word_count_clr <= '1'; - end if; + if reset_en = '1' then + stream_s <= stream_init; else - word_count_clr <= '0'; + stream_s <= stream_sn; end if; end if; end process; -word_count_register: - process(clk) +stream_state: + process(stream_s, sipo_8bit_dout_en, sipo_32bit_dout_en) begin - if rising_edge(clk) then - if rst = '1' or word_count_ack = '1' then - word_count_vld <= '0'; - elsif word_count_set = '1' then - word_count_reg <= word_count; - byte_count_reg_s <= byte_count_reg; - word_count_vld <= '1'; + + sipo_32bit_en <= '0'; + sipo_32bit_rst <= '0'; + sipo_8bit_rst <= '0'; + word_count_en <= sipo_32bit_dout_en; + byte_count_en <= sipo_8bit_dout_en; + size_fifo_we <= '0'; + + stream_sn <= stream_s; + + case stream_s is + + when stream_init => + sipo_32bit_rst <= '1'; + sipo_8bit_rst <= '1'; + if sipo_8bit_dout_en = '0' then + stream_sn <= stream_idle; end if; - end if; - end process; + + when stream_idle => + sipo_32bit_en <= sipo_8bit_dout_en; + if sipo_8bit_dout_en = '1' then + stream_sn <= stream_start; + end if; + + when stream_start => + sipo_32bit_en <= sipo_8bit_dout_en; + if sipo_8bit_dout_en = '1' then + stream_sn <= stream_active; + end if; + + when stream_active => + sipo_32bit_en <= sipo_8bit_dout_en; + if sipo_8bit_dout_en = '0' then + stream_sn <= stream_stop; + sipo_8bit_rst <= '1'; + end if; + + when stream_stop => + sipo_32bit_en <= '0'; + if sipo_32bit_dout_en = '0' then + stream_sn <= stream_finish; + end if; + + when stream_finish => + size_fifo_we <= '1'; + stream_sn <= stream_idle; + sipo_32bit_rst <= '1'; + + when others => + stream_sn <= stream_idle; + end case; + + end process; ------------------------------------------------------------------ -- Instantiate synchronous FIFO @@ -447,7 +456,7 @@ inst_cmd_fifo: entity work.fifo_sync ) PORT MAP ( - rst => flush_en, + rst => reset_en, clk => clk, we => cmd_fifo_we, re => cmd_fifo_re, @@ -482,13 +491,13 @@ inst_ram : entity work.dpram_1w1r inst_mii_fifo: entity work.fifo_async GENERIC MAP ( - addr_width => 5, - data_width => 36, + addr_width => 4, + data_width => mii_fifo_din'length, do_last_read_update => true ) PORT MAP ( - rst => rst, + rst => reset_en, clk_w => mii_rx_clk, clk_r => clk, we => mii_fifo_we, @@ -501,6 +510,29 @@ inst_mii_fifo: entity work.fifo_async data_r => mii_fifo_dout ); +-- Instantiate synchronous FIFO +inst_size_fifo: entity work.fifo_async + GENERIC MAP + ( + addr_width => 1, + data_width => 2*word_ptr_t'length, + do_last_read_update => true + ) + PORT MAP + ( + rst => reset_en, + clk_w => mii_rx_clk, + clk_r => clk, + we => size_fifo_we, + re => size_fifo_re, + fifo_full => size_fifo_full, + fifo_empty => size_fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_w => size_fifo_din, + data_r => size_fifo_dout + ); + inst_sipo : entity work.sipo GENERIC MAP ( @@ -510,21 +542,20 @@ inst_sipo : entity work.sipo ) PORT MAP ( - rst => sipo_rst, + rst => sipo_32bit_rst, clk => mii_rx_clk, - din_vld => sipo_10mbps_dout_vld, - din_en => sipo_10mbps_dout_en, - din => sipo_10mbps_dout, - dout_be => sipo_dout_be, - dout_vld => sipo_dout_vld, - dout => sipo_dout, - dout_en => sipo_dout_en + din_vld => sipo_8bit_dout_vld, + din_en => sipo_32bit_en, + din => sipo_8bit_dout, + dout_be => sipo_32bit_dout_be, + dout_vld => sipo_32bit_dout_vld, + dout => sipo_32bit_dout, + dout_en => sipo_32bit_dout_en ); - sipo_rst <= rst or word_count_set; -inst_sipo_10mbps : entity work.sipo +inst_sipo_8bit : entity work.sipo GENERIC MAP ( data_width_in => 4, @@ -533,18 +564,17 @@ inst_sipo_10mbps : entity work.sipo ) PORT MAP ( - rst => sipo_10mbps_rst, + rst => sipo_8bit_rst, clk => mii_rx_clk, din_vld => mii_rx_dv, - din_en => mii_rx_dv, + din_en => sipo_8bit_en, din => mii_rx(3 downto 0), dout_be => open, - dout_vld => sipo_10mbps_dout_vld, - dout => sipo_10mbps_dout, - dout_en => sipo_10mbps_dout_en + dout_vld => sipo_8bit_dout_vld, + dout => sipo_8bit_dout, + dout_en => sipo_8bit_dout_en ); - - sipo_10mbps_rst <= rst or word_count_set; + sipo_8bit_en <= mii_rx_dv; end behavior;