diff --git a/lib/emac/src/emac_tx.vhd b/lib/emac/src/emac_tx.vhd index 869334f..f26348a 100644 --- a/lib/emac/src/emac_tx.vhd +++ b/lib/emac/src/emac_tx.vhd @@ -96,11 +96,26 @@ ARCHITECTURE behavior OF emac_tx IS signal piso8_dout_vld : std_logic; signal piso8_din_rdy : std_logic; + signal piso8_din_vld : std_logic; signal piso8_dout : unsigned(3 downto 0); + signal piso8_din : unsigned(7 downto 0); signal reset_pipe : unsigned(31 downto 0); signal Gbps_en : std_logic; + signal fcs_inject_en : std_logic; + signal fcs_rst : std_logic; + signal fcs_en : unsigned(7 downto 0); + signal fcs_vld : std_logic; + signal fcs_din_vld : std_logic; + signal fcs : unsigned(31 downto 0); + signal fcs_rev_endian : unsigned(31 downto 0); + + signal mii_fifo_we : std_logic; + signal mii_fifo_re : std_logic; + signal mii_fifo_full : std_logic; + signal mii_fifo_empty : std_logic; + subtype ifg_cnt_t is natural range 0 to 23; -- 10/100 mbps -- subtype ifg_cnt_t is natural range 0 to 11; -- 1000 mbps @@ -110,7 +125,7 @@ ARCHITECTURE behavior OF emac_tx IS type host_state_t is (host_init, host_idle, host_alloc, host_setup, host_arm, host_fill, host_commit); signal host_s, host_sn : host_state_t; - type xfer_state_t is (xfer_init, xfer_idle, xfer_start, xfer_preamble0, xfer_preamble1, xfer_active, xfer_crc, xfer_stop, xfer_finish); + type xfer_state_t is (xfer_init, xfer_idle, xfer_start, xfer_preamble0, xfer_preamble1, xfer_active, xfer_crc, xfer_finish); signal xfer_s, xfer_sn : xfer_state_t; type piso_byte_mask_array_t is array (0 to 3) of unsigned (3 downto 0); @@ -144,8 +159,8 @@ begin ram_din_a(35 downto 32) <= piso_byte_mask_rom(to_integer(fill_remain)) when fill_pre_rdy = '1' else "1111"; ram_addr_a <= fill_ptr; - piso32_din <= preamble(preamble_addr) when preamble_en = '1' else ram_dout_b(31 downto 0); - piso32_din_be <= "1111" when preamble_en = '1' else ram_dout_b(35 downto 32); + piso32_din <= preamble(preamble_addr) when preamble_en = '1' else fcs_rev_endian when fcs_inject_en = '1' else ram_dout_b(31 downto 0); + piso32_din_be <= "1111" when (preamble_en = '1' or fcs_inject_en = '1') else ram_dout_b(35 downto 32); cmd_fifo_we <= commit_en; cmd_fifo_re <= uncommit_en; @@ -159,6 +174,8 @@ begin fill_cnt_en <= fill_bsy and din_vld; mem_free_en <= not mem_free_ack(0) and mem_free_ack(1); + fcs_rev_endian <= fcs(7 downto 0) & fcs(15 downto 8) & fcs(23 downto 16) & fcs(31 downto 24); + ------------------------------------------------------------------ reset_gen: process(clk) @@ -411,7 +428,7 @@ interframe_gap_counter: begin if rising_edge(mii_tx_clk) then ifg_idle <= '0'; - if reset_en = '1' or piso32_dout_vld = '1' then + if reset_en = '1' or mii_fifo_empty = '0' then ifg_cnt <= ifg_cnt_t'high; elsif ifg_cnt /= 0 then ifg_cnt <= ifg_cnt - 1; @@ -483,6 +500,8 @@ xfer_state: xfer_set <= '0'; xfer_en <= '0'; xfer_free_en <= '0'; + fcs_rst <= '0'; + fcs_inject_en <= '0'; uncommit_en <= '0'; xfer_sn <= xfer_s; @@ -499,6 +518,7 @@ xfer_state: when xfer_start => xfer_set <= '1'; + fcs_rst <= '1'; if cmd_fifo_empty = '0' and ifg_idle = '1' then xfer_sn <= xfer_preamble0; end if; @@ -523,15 +543,14 @@ xfer_state: when xfer_active => piso32_din_vld <= xfer_bsy; xfer_en <= '1'; - if xfer_bsy = '0' then + if xfer_bsy = '0' and piso32_dout_vld = '0' then xfer_sn <= xfer_crc; end if; when xfer_crc => - xfer_sn <= xfer_stop; - - when xfer_stop => - if piso32_dout_vld = '0' then + fcs_inject_en <= piso32_din_rdy; + piso32_din_vld <= '1'; + if piso32_din_rdy = '1' then xfer_sn <= xfer_finish; end if; @@ -610,7 +629,57 @@ inst_piso32 : entity work.piso ); - piso32_dout_en <= '1' when Gbps_en = '1' else piso8_din_rdy; + piso32_dout_en <= not mii_fifo_full; --'1' when Gbps_en = '1' else piso8_din_rdy; + +fcs_enable_gen: + process(mii_tx_clk) + begin + if rising_edge(mii_tx_clk) then + if fcs_rst = '1' then + fcs_en <= (others => '0'); + elsif piso32_dout_vld = '1' then + fcs_en <= fcs_en(fcs_en'left-1 downto 0) & '1'; + end if; + end if; + end process; + fcs_din_vld <= fcs_en(fcs_en'left) and piso32_dout_vld and piso32_dout_en; + +inst_fcs: entity work.crc32 + PORT MAP + ( + rst => fcs_rst, + clk => mii_tx_clk, + din_vld => fcs_din_vld, + din => piso32_dout, + crc32_vld => fcs_vld, + crc32_out => fcs + + ); + + mii_fifo_re <= '1' when Gbps_en = '1' else piso8_din_rdy; + mii_fifo_we <= piso32_dout_vld; + +-- Instantiate synchronous FIFO +inst_mii_fifo: entity work.fifo_sync + GENERIC MAP + ( + addr_width => 4, + data_width => piso32_dout'length, + do_last_read_update => true + ) + PORT MAP + ( + rst => reset_en, + clk => mii_tx_clk, + we => mii_fifo_we, + re => mii_fifo_re, + fifo_full => mii_fifo_full, + fifo_empty => mii_fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_w => piso32_dout, + data_r => piso8_din + ); inst_piso8 : entity work.piso GENERIC MAP @@ -623,24 +692,25 @@ inst_piso8 : entity work.piso ( rst => reset_en, clk => mii_tx_clk, - din_vld => piso32_dout_vld, + din_vld => piso8_din_vld, din_rdy => piso8_din_rdy, din_be => "11", - din => piso32_dout, + din => piso8_din, dout_vld => piso8_dout_vld, dout_en => '1', dout => piso8_dout ); - + piso8_din_vld <= not mii_fifo_empty; + mii_output_register: process(mii_tx_clk) begin if rising_edge(mii_tx_clk) then mii_tx_er <= '0'; if Gbps_en = '1' then - mii_tx_en <= piso32_dout_vld; - mii_tx <= piso32_dout; + mii_tx_en <= piso8_din_vld; + mii_tx <= piso8_din; else mii_tx_en <= piso8_dout_vld; mii_tx <= "0000" & piso8_dout;