LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY e_io_eth_txframe IS PORT ( rst: IN std_logic; clk: IN std_logic; o_if_data: OUT std_logic_vector(7 DOWNTO 0); o_if_data_en: OUT std_logic; i_if_data_ack: IN std_logic; i_frame_en: IN std_logic; i_frame_data: IN std_logic_vector(31 DOWNTO 0); i_frame_data_en: IN std_logic; o_frame_data_ack: OUT std_logic; o_frame_done: OUT std_logic ); END ENTITY e_io_eth_txframe; ARCHITECTURE a_io_eth_txframe OF e_io_eth_txframe IS TYPE t_state IS (st_idle, st_sync, st_start, st_data, st_pad, st_crc, st_gap); SUBTYPE t_data_cnt IS natural RANGE 0 TO 3; SUBTYPE t_byte_cnt IS natural RANGE 0 TO 255; SIGNAL r_state: t_state := st_idle; SIGNAL n_state: t_state; SIGNAL r_data_cnt: t_data_cnt := 0; SIGNAL n_data_cnt: t_data_cnt; SIGNAL r_data: std_logic_vector(31 DOWNTO 0) := (OTHERS => '0'); SIGNAL n_data: std_logic_vector(31 DOWNTO 0); SIGNAL r_byte_cnt: t_byte_cnt := 0; SIGNAL n_byte_cnt: t_byte_cnt; SIGNAL r_crc_start: std_logic := '0'; SIGNAL n_crc_start: std_logic; SIGNAL s_crc_en: std_logic; SIGNAL s_crc_start: std_logic; SIGNAL s_crc_data: std_logic_vector( 7 DOWNTO 0); SIGNAL s_crc_crc: std_logic_vector(31 DOWNTO 0); COMPONENT e_block_crc32 IS PORT ( rst: IN std_logic; clk: IN std_logic; i_en: IN std_logic; i_start: IN std_logic; i_data: IN std_logic_vector( 7 DOWNTO 0); o_crc: OUT std_logic_vector(31 DOWNTO 0) ); END COMPONENT e_block_crc32; BEGIN crc32: e_block_crc32 PORT MAP ( rst => rst, clk => clk, i_en => s_crc_en, i_start => s_crc_start, i_data => s_crc_data, o_crc => s_crc_crc ); p_next: PROCESS(r_state, r_data_cnt, r_data, r_byte_cnt, r_crc_start, i_if_data_ack, i_frame_en, i_frame_data, i_frame_data_en, s_crc_crc) VARIABLE v_data: std_logic_vector(31 DOWNTO 0); BEGIN n_state <= r_state; n_data_cnt <= r_data_cnt; n_data <= r_data; n_byte_cnt <= r_byte_cnt; n_crc_start <= '0'; o_if_data <= X"00"; o_if_data_en <= '0'; o_frame_data_ack <= '0'; o_frame_done <= '0'; s_crc_en <= '0'; s_crc_start <= '0'; s_crc_data <= (OTHERS => '0'); CASE r_state IS WHEN st_idle => IF i_frame_en = '1' THEN n_state <= st_sync; n_byte_cnt <= 0; END IF; WHEN st_sync => IF i_if_data_ack = '1' THEN IF r_byte_cnt = 6 THEN n_state <= st_start; ELSE n_byte_cnt <= r_byte_cnt + 1; END IF; END IF; o_if_data <= X"55"; o_if_data_en <= '1'; WHEN st_start => IF i_if_data_ack = '1' THEN IF i_frame_data_en = '1' THEN n_state <= st_data; n_data_cnt <= 0; n_data <= i_frame_data; n_byte_cnt <= 0; n_crc_start <= '1'; o_frame_data_ack <= '1'; ELSE n_state <= st_gap; n_byte_cnt <= 0; END IF; END IF; o_if_data <= X"D5"; o_if_data_en <= '1'; WHEN st_data => IF i_if_data_ack = '1' THEN IF r_data_cnt = 3 THEN IF i_frame_data_en = '1' THEN n_state <= st_data; n_data_cnt <= 0; n_data <= i_frame_data; o_frame_data_ack <= '1'; ELSE IF r_byte_cnt = 59 THEN n_state <= st_crc; n_data_cnt <= 0; ELSE n_state <= st_pad; END IF; END IF; ELSE n_data_cnt <= r_data_cnt + 1; n_data(23 DOWNTO 0) <= r_data(31 DOWNTO 8); END IF; IF r_byte_cnt /= 59 THEN n_byte_cnt <= r_byte_cnt + 1; END IF; s_crc_en <= '1'; s_crc_start <= r_crc_start; s_crc_data <= r_data(7 DOWNTO 0); END IF; o_if_data <= r_data(7 DOWNTO 0); o_if_data_en <= '1'; WHEN st_pad => IF i_if_data_ack = '1' THEN IF r_byte_cnt = 59 THEN n_state <= st_crc; n_data_cnt <= 0; ELSE n_byte_cnt <= r_byte_cnt + 1; END IF; s_crc_en <= '1'; s_crc_data <= (OTHERS => '0'); END IF; o_if_data <= (OTHERS => '0'); o_if_data_en <= '1'; WHEN st_crc => IF r_data_cnt = 0 THEN v_data := s_crc_crc; -- get CRC value on first CRC byte ELSE v_data := r_data; END IF; IF i_if_data_ack = '1' THEN IF r_data_cnt = 3 THEN n_state <= st_gap; n_byte_cnt <= 0; ELSE n_data_cnt <= r_data_cnt + 1; n_data(23 DOWNTO 0) <= v_data(31 DOWNTO 8); END IF; END IF; o_if_data <= v_data(7 DOWNTO 0); o_if_data_en <= '1'; WHEN st_gap => -- 12 octets, *2 because of clk, plus async FIFO len IF r_byte_cnt = 12 * 8 * 2 + 16 THEN n_state <= st_idle; o_frame_done <= '1'; ELSE n_byte_cnt <= r_byte_cnt + 1; END IF; WHEN OTHERS => NULL; END CASE; END PROCESS p_next; p_sync: PROCESS(rst, clk) BEGIN IF rst = '1' THEN r_state <= st_idle; r_data_cnt <= 0; r_data <= (OTHERS => '0'); r_byte_cnt <= 0; r_crc_start <= '0'; ELSIF rising_edge(clk) THEN r_state <= n_state; r_data_cnt <= n_data_cnt; r_data <= n_data; r_byte_cnt <= n_byte_cnt; r_crc_start <= n_crc_start; END IF; END PROCESS p_sync; END ARCHITECTURE a_io_eth_txframe;