diff --git a/lib/emac/src/emac_rx.vhd b/lib/emac/src/emac_rx.vhd index 6019861..38a1adb 100644 --- a/lib/emac/src/emac_rx.vhd +++ b/lib/emac/src/emac_rx.vhd @@ -44,8 +44,8 @@ ARCHITECTURE behavior OF emac_rx IS signal mii_fifo_empty : std_logic; signal mii_fifo_full : std_logic; - signal cmd_fifo_din : unsigned(31 downto 0); - signal cmd_fifo_dout : unsigned(31 downto 0); + signal cmd_fifo_din : unsigned(2*word_ptr_t'length+2 downto 0); + signal cmd_fifo_dout : unsigned(2*word_ptr_t'length+2 downto 0); signal cmd_fifo_we : std_logic; signal cmd_fifo_re : std_logic; signal cmd_fifo_empty : std_logic; @@ -67,6 +67,7 @@ ARCHITECTURE behavior OF emac_rx IS signal xfer_cnt_set : std_logic; signal xfer_cnt_adv : std_logic; signal xfer_rdy : std_logic; + signal xfer_vld : std_logic; signal ram_en_a : std_logic; signal ram_we_a : std_logic; @@ -102,48 +103,98 @@ ARCHITECTURE behavior OF emac_rx IS 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 size_fifo_din : unsigned(2*word_ptr_t'length+2 downto 0); + signal size_fifo_dout : unsigned(2*word_ptr_t'length+2 downto 0); signal reset_pipe : unsigned(31 downto 0); + signal preamble_rst : std_logic; + signal preamble_rdy : std_logic; + signal preamble_bsy : std_logic; + signal preamble_OK : std_logic; + + signal mac_chk_rdy : std_logic; + signal mac_chk_BC : std_logic; + signal mac_chk_OK : std_logic; + signal mac_chk_rst : std_logic; + signal mac_chk_num_OK : natural range 0 to 6; + signal mac_chk_num_BC : natural range 0 to 6; + signal mac_chk_cnt : natural range 0 to 5; + signal mac_chk_addr : mac_addr_t; + 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_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); + type stream_state_t is (stream_init, stream_reset, stream_idle, stream_active, stream_stop, stream_finish); signal stream_s, stream_sn : stream_state_t; + alias cmd_mac_ok_in is cmd_fifo_din(cmd_fifo_din'left); + alias cmd_bcast_in is cmd_fifo_din(cmd_fifo_din'left-1); + alias cmd_invalid_in is cmd_fifo_din(cmd_fifo_din'left-2); + alias cmd_nbytes_in is cmd_fifo_din(word_ptr_t'length-1 downto 0); + alias cmd_base_in is cmd_fifo_din(2*word_ptr_t'length-1 downto word_ptr_t'length); + + alias cmd_mac_ok_out is cmd_fifo_dout(cmd_fifo_dout'left); + alias cmd_bcast_out is cmd_fifo_dout(cmd_fifo_dout'left-1); + alias cmd_invalid_out is cmd_fifo_dout(cmd_fifo_dout'left-2); + alias cmd_nbytes_out is cmd_fifo_dout(word_ptr_t'length-1 downto 0); + alias cmd_base_out is cmd_fifo_dout(2*word_ptr_t'length-1 downto word_ptr_t'length); + + alias stream_mac_ok_in is size_fifo_din(size_fifo_din'left); + alias stream_broadcast_in is size_fifo_din(size_fifo_din'left-1); + alias stream_badcrc_in is size_fifo_din(size_fifo_din'left-2); + alias stream_nbytes_in is size_fifo_din(word_ptr_t'length-1 downto 0); + alias stream_nwords_in is size_fifo_din(2*word_ptr_t'length-1 downto word_ptr_t'length); + + alias stream_mac_ok_out is size_fifo_dout(size_fifo_dout'left); + alias stream_broadcast_out is size_fifo_dout(size_fifo_dout'left-1); + alias stream_badcrc_out is size_fifo_dout(size_fifo_dout'left-2); + alias stream_nbytes_out is size_fifo_dout(word_ptr_t'length-1 downto 0); + alias stream_nwords_out is size_fifo_dout(2*word_ptr_t'length-1 downto word_ptr_t'length); + 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; + ctrl_out.rx_size <= resize(cmd_nbytes_out, 16); + ctrl_out.pkt_avail <= not cmd_fifo_empty; + ctrl_out.rx_er <= mii_rx_er; + ctrl_out.reset_busy <= reset_en; + ctrl_out.pkt_bcast <= cmd_bcast_out; + ctrl_out.pkt_mac_match <= cmd_mac_ok_out; - dout <= ram_dout_a; + dout <= ram_dout_a; - mii_fifo_din <= sipo_32bit_dout; - mii_fifo_we <= sipo_32bit_dout_vld; + mii_fifo_din <= sipo_32bit_dout; + mii_fifo_we <= word_count_en and sipo_32bit_dout_vld; - ram_en_a <= '1'; - ram_din_a <= (others => '-'); - ram_addr_a <= fill_ptr; - ram_we_a <= '0'; + ram_en_a <= '1'; + ram_din_a <= (others => '-'); + ram_addr_a <= fill_ptr; + ram_we_a <= '0'; - ram_en_b <= '1'; - ram_din_b <= mii_fifo_dout; - ram_addr_b <= xfer_ptr; - ram_we_b <= xfer_ptr_adv; + ram_en_b <= '1'; + 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 <= resize(size_fifo_dout(word_ptr_t'length-1 downto 0), 16) & resize(xfer_base, 16); + cmd_fifo_we <= commit_en; + cmd_fifo_re <= ctrl_in.pkt_free_en; + + cmd_mac_ok_in <= stream_mac_ok_out; + cmd_bcast_in <= stream_broadcast_out; + cmd_invalid_in <= stream_badcrc_out; + cmd_nbytes_in <= stream_nbytes_out; + cmd_base_in <= xfer_base; - size_fifo_din <= word_count & byte_count_reg; - reset_en <= reset_pipe(reset_pipe'left); + stream_nbytes_in <= byte_count_reg; + stream_nwords_in <= word_count; + stream_mac_ok_in <= mac_chk_OK; + stream_broadcast_in <= mac_chk_BC; + stream_badcrc_in <= '0'; + + reset_en <= reset_pipe(reset_pipe'left); ------------------------------------------------------------------ reset_gen: @@ -167,7 +218,7 @@ fill_pointer: if rising_edge(clk) then dout_vld <= ctrl_in.pkt_read_en; if ctrl_in.pkt_req_en = '1' then - fill_ptr <= resize(cmd_fifo_dout(15 downto 0), word_ptr_t'length); + fill_ptr <= cmd_base_out; elsif ctrl_in.pkt_read_en = '1' then fill_ptr <= fill_ptr + 1; end if; @@ -190,7 +241,7 @@ xfer_state_next: end process; xfer_state: - process(xfer_s, size_fifo_empty, mii_fifo_empty, xfer_rdy, xfer_ram_full) + process(xfer_s, size_fifo_empty, mii_fifo_empty, xfer_rdy, xfer_vld, xfer_ram_full) begin commit_en <= '0'; @@ -241,7 +292,7 @@ xfer_state: when xfer_free => size_fifo_re <= '1'; - commit_en <= not xfer_ram_full; + commit_en <= not xfer_ram_full and xfer_vld; xfer_sn <= xfer_idle; when others => @@ -274,7 +325,7 @@ xfer_limit_register: if cmd_fifo_empty = '1' then xfer_ram_limit <= xfer_base - 1; else - xfer_ram_limit <= resize(cmd_fifo_dout(15 downto 0), word_ptr_t'length) - 1; + xfer_ram_limit <= cmd_base_out - 1; end if; end if; end if; @@ -302,8 +353,10 @@ xfer_counter: if rising_edge(clk) then 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_vld <= '0'; + elsif xfer_size = stream_nwords_out then xfer_rdy <= '1'; + xfer_vld <= stream_mac_ok_out or stream_broadcast_out or ctrl_in.promiscious; end if; if xfer_cnt_set = '1' then xfer_size <= (others => '0'); @@ -374,6 +427,65 @@ word_counter: end if; end process; +preamble_sync_logic: + process(mii_rx_clk) + begin + if rising_edge(mii_rx_clk) then + if preamble_rst = '1' then + preamble_rdy <= '0'; + preamble_bsy <= '0'; + preamble_OK <= '0'; + elsif sipo_8bit_dout_vld = '1' then + if preamble_bsy = '1' then + if sipo_8bit_dout = X"D5" then + preamble_OK <= '1'; + end if; + end if; + if sipo_8bit_dout /= X"55" then + preamble_bsy <= '0'; + preamble_rdy <= preamble_bsy; + else + preamble_bsy <= '1'; + end if; + end if; + end if; + end process; + +mac_check_logic: + process(mii_rx_clk) + begin + if rising_edge(mii_rx_clk) then + if mac_chk_rst = '1' then + mac_chk_rdy <= '0'; + mac_chk_OK <= '0'; + mac_chk_BC <= '0'; + mac_chk_cnt <= 0; + mac_chk_num_OK <= 0; + mac_chk_num_BC <= 0; + mac_chk_addr <= ctrl_in.mac_addr; + elsif mac_chk_rdy = '1' then + if mac_chk_num_OK = 6 then + mac_chk_OK <= '1'; + end if; + if mac_chk_num_BC = 6 then + mac_chk_BC <= '1'; + end if; + elsif sipo_8bit_dout_vld = '1' then + if sipo_8bit_dout = mac_chk_addr(mac_chk_cnt) then + mac_chk_num_OK <= mac_chk_num_OK + 1; + end if; + if sipo_8bit_dout = X"FF" then + mac_chk_num_BC <= mac_chk_num_BC + 1; + end if; + if mac_chk_cnt /= 5 then + mac_chk_cnt <= mac_chk_cnt + 1; + else + mac_chk_rdy <= '1'; + end if; + end if; + end if; + end process; + ------------------------------------------------------------------ stream_state_next: process(mii_rx_clk) @@ -388,59 +500,68 @@ stream_state_next: end process; stream_state: - process(stream_s, sipo_8bit_dout_en, sipo_32bit_dout_en) + process(stream_s, reset_en, sipo_8bit_dout_en, sipo_8bit_dout, sipo_32bit_dout_en, sipo_32bit_dout_vld, preamble_rdy, preamble_OK) begin 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; + sipo_32bit_rst <= reset_en; + sipo_8bit_rst <= reset_en; + word_count_en <= '0'; + byte_count_en <= '0'; size_fifo_we <= '0'; + preamble_rst <= reset_en; + mac_chk_rst <= reset_en; + sipo_32bit_en <= sipo_8bit_dout_en; + 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; + stream_sn <= stream_reset; end if; - 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_reset => + sipo_32bit_rst <= '1'; + sipo_8bit_rst <= '1'; + preamble_rst <= '1'; + stream_sn <= stream_idle; + when stream_idle => + sipo_32bit_en <= '0'; + if preamble_rdy = '1' then + stream_sn <= stream_init; + if preamble_OK = '1' then + byte_count_en <= '1'; + mac_chk_rst <= '1'; + sipo_32bit_rst <= '1'; + stream_sn <= stream_active; + end if; + end if; + when stream_active => - sipo_32bit_en <= sipo_8bit_dout_en; + word_count_en <= sipo_32bit_dout_en; + byte_count_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'; + word_count_en <= sipo_32bit_dout_en; + byte_count_en <= sipo_8bit_dout_en; 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'; + stream_sn <= stream_init; when others => - stream_sn <= stream_idle; + stream_sn <= stream_init; end case; end process; @@ -452,7 +573,7 @@ inst_cmd_fifo: entity work.fifo_sync ( addr_width => NextExpBaseTwo(RAM_SIZE) - 4, -- RAMSIZE(words)/MIN_PACKET_LEN(words) data_width => cmd_fifo_din'length, - do_last_read_update => true + do_last_read_update => false ) PORT MAP ( @@ -515,7 +636,7 @@ inst_size_fifo: entity work.fifo_async GENERIC MAP ( addr_width => 1, - data_width => 2*word_ptr_t'length, + data_width => size_fifo_din'length, do_last_read_update => true ) PORT MAP