diff --git a/lib/emac/src/pkt_gen.vhd b/lib/emac/src/pkt_gen.vhd index 389f294..a84770f 100644 --- a/lib/emac/src/pkt_gen.vhd +++ b/lib/emac/src/pkt_gen.vhd @@ -11,6 +11,7 @@ ENTITY pkt_gen IS Generic ( f_sysclk : real := 100.0; + TX_RAM_SIZE : natural := 2048; PKT_DLY_MIN : real := 1.0E-6; PKT_DLY_MAX : real := 100.0E-6; PKT_SIZE_MIN : natural := 64; @@ -21,6 +22,7 @@ ENTITY pkt_gen IS ( clk : in STD_LOGIC; rst : in STD_LOGIC; + en : in STD_LOGIC; mii_tx_clk : in STD_LOGIC; mii_tx_en : out STD_LOGIC; mii_tx_er : out STD_LOGIC; @@ -38,173 +40,97 @@ ARCHITECTURE behavior OF pkt_gen IS signal pkt_nwords : word_ptr_t := X"0010"; signal pkt_delay : natural := natural(1.0*f_sysclk); + signal fill_size : word_ptr_t; + signal fill_cnt : word_ptr_t; + signal fill_rdy : std_logic; + signal fill_set : std_logic; + signal fill_en : std_logic; + signal tx_packets : natural; signal tx_bytes : natural; - signal mii_fifo_din : unsigned(35 downto 0); - signal mii_fifo_dout : unsigned(35 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 xfer_size : word_ptr_t; - signal xfer_ptr : word_ptr_t; - signal xfer_cnt : word_ptr_t; - signal xfer_set : std_logic; - signal xfer_en : std_logic; - signal xfer_sync : unsigned(1 downto 0); - signal xfer_cnt_en : std_logic; - signal xfer_bsy : std_logic; - signal xfer_pre_rdy : std_logic; - signal uncommit_en : std_logic; - - signal piso8_din : unsigned(31 downto 0); - signal piso8_din_be : unsigned(3 downto 0); - signal piso8_din_rdy : std_logic; - signal piso8_din_vld : std_logic; - - signal piso8_dout : unsigned(7 downto 0); - signal piso8_dout_vld : std_logic; - signal piso8_dout_en : std_logic; - signal piso4_din_rdy : std_logic; - signal tx_en : std_logic; + signal tx_ctrl_in : tx_ctrl_in_t; + signal tx_ctrl_out : tx_ctrl_out_t; + signal tx_din : unsigned(31 downto 0); + signal tx_din_vld : 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 - - signal ifg_cnt : ifg_cnt_t; - signal ifg_idle : std_logic; - - type xfer_state_t is (xfer_init, xfer_idle, xfer_setup, xfer_arm, xfer_active, xfer_uncommit, xfer_free); - signal xfer_s, xfer_sn : xfer_state_t; - - type stream_state_t is (stream_init, stream_idle, stream_start, stream_preamble0, stream_preamble1, stream_active, stream_crc, stream_stop, stream_finish); - signal stream_s, stream_sn : stream_state_t; - - type piso_byte_mask_array_t is array (0 to 3) of unsigned (3 downto 0); - constant piso_byte_mask_rom : piso_byte_mask_array_t := - ( - "1111", - "1000", - "1100", - "1110" - ); - - signal preamble_en : std_logic; - signal preamble_addr : natural range 0 to 1; - type preamble_t is array (0 to 1) of unsigned(31 downto 0); - constant preamble : preamble_t := - ( - X"55555555", - X"555555D5" - ); + 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; begin - mii_tx_er <= '0'; - - piso8_din <= preamble(preamble_addr) when preamble_en = '1' else mii_fifo_dout(31 downto 0); - piso8_din_be <= "1111" when preamble_en = '1' else mii_fifo_dout(35 downto 32); - - mii_fifo_we <= xfer_bsy; - xfer_cnt_en <= xfer_bsy and not mii_fifo_full; - - mii_fifo_din(35 downto 32) <= piso_byte_mask_rom(to_integer(pkt_nbytes(1 downto 0))) when xfer_pre_rdy = '1' else "1111"; - mii_fifo_din(31 downto 0) <= pkt_data; - - ------------------------------------------------------------------ --- Transfer stuff ------------------------------------------------------------------- -xfer_state_next: +host_state_next: process(clk) begin if rising_edge(clk) then if rst = '1' then - xfer_s <= xfer_init; + host_s <= host_init; else - xfer_s <= xfer_sn; + host_s <= host_sn; end if; end if; end process; -xfer_state: - process(xfer_s, xfer_bsy, xfer_sync) +host_state: + process(host_s, tx_ctrl_out, pkt_nbytes, fill_rdy, en) begin - uncommit_en <= '0'; - xfer_set <= '0'; - xfer_en <= '0'; + tx_ctrl_in.pkt_alloc_en <= '0'; + tx_ctrl_in.pkt_commit_en <= '0'; + tx_ctrl_in.reset <= '0'; + tx_ctrl_in.Gbps_en <= '0'; + tx_ctrl_in.tx_er <= '0'; + tx_ctrl_in.tx_size <= pkt_nbytes; + fill_set <= '0'; + fill_en <= '0'; - xfer_sn <= xfer_s; + host_sn <= host_s; - case xfer_s is + case host_s is - when xfer_init => - xfer_sn <= xfer_idle; + when host_init => + if tx_ctrl_out.reset_busy = '0' then + host_sn <= host_idle; + end if; - when xfer_idle => - xfer_sn <= xfer_setup; - - when xfer_setup => - xfer_set <= '1'; - xfer_sn <= xfer_arm; - - when xfer_arm => - xfer_en <= '1'; - xfer_sn <= xfer_active; - - when xfer_active => - xfer_en <= '1'; - if xfer_bsy = '0' then - xfer_sn <= xfer_uncommit; - end if; - - when xfer_uncommit => - uncommit_en <= '1'; - xfer_sn <= xfer_free; - - when xfer_free => - if xfer_sync(1) = '1' then - xfer_sn <= xfer_idle; + when host_idle => + if tx_ctrl_out.pkt_alloc_req = '0' and en = '1' then + tx_ctrl_in.pkt_alloc_en <= '1'; + host_sn <= host_alloc; end if; + when host_alloc => + if tx_ctrl_out.pkt_alloc_req = '0' then + if tx_ctrl_out.pkt_armed = '1' then + host_sn <= host_setup; + else + host_sn <= host_idle; + end if; + end if; + + when host_setup => + fill_set <= '1'; + host_sn <= host_fill; + + when host_fill => + fill_en <= '1'; + if fill_rdy = '1' then + host_sn <= host_commit; + end if; + + when host_commit => + tx_ctrl_in.pkt_commit_en <= '1'; + host_sn <= host_idle; + when others => - xfer_sn <= xfer_idle; + host_sn <= host_idle; end case; end process; ------------------------------------------------------------------ -interframe_gap_ready: - process(clk) - begin - if rising_edge(clk) then - xfer_sync(1) <= xfer_sync(0); - xfer_sync(0) <= mii_fifo_empty; - end if; - end process; - ------------------------------------------------------------------- -interframe_gap_counter: - process(mii_tx_clk) - begin - if rising_edge(mii_tx_clk) then - ifg_idle <= '0'; - if rst = '1' or piso8_dout_vld = '1' then - ifg_cnt <= ifg_cnt_t'high; - ifg_idle <= '1'; - elsif ifg_cnt /= 0 then - ifg_cnt <= ifg_cnt - 1; - else - ifg_idle <= '1'; - end if; - end if; - end process; - ------------------------------------------------------------------- -pkt_params: +pkt_generator: process(clk) variable size : word_ptr_t; variable delay : natural; @@ -221,7 +147,7 @@ pkt_params: seed2 := 12586901; tx_packets <= 0; tx_bytes <= 0; - elsif uncommit_en = '1' then + elsif tx_ctrl_in.pkt_commit_en = '1' then uniform(seed1, seed2, krand); size := to_unsigned(PKT_SIZE_MIN + natural(real(PKT_SIZE_MAX-PKT_SIZE_MIN)*krand), word_ptr_t'length); delay := natural(1.0E6*f_sysclk*(PKT_DLY_MIN + (PKT_DLY_MAX-PKT_DLY_MIN)*krand)); @@ -239,27 +165,44 @@ pkt_params: end process; ------------------------------------------------------------------ -xfer_counter: +pkt_data_gen: + process(clk) + variable data : unsigned(7 downto 0); + begin + if rising_edge(clk) then + tx_din_vld <= fill_en; + if fill_set = '1' then + data := X"00"; + tx_din <= X"03020100"; + elsif fill_en = '1' then + tx_din(7 downto 0) <= data; + data := data + 1; + tx_din(15 downto 8) <= data; + data := data + 1; + tx_din(23 downto 16) <= data; + data := data + 1; + tx_din(31 downto 24) <= data; + data := data + 1; + end if; + end if; + + end process; + +------------------------------------------------------------------ +pkt_data_counter: process(clk) begin if rising_edge(clk) then - if xfer_set = '1' then - xfer_cnt <= pkt_nwords; - xfer_size <= (others => '0'); - xfer_bsy <= '0'; - xfer_pre_rdy <= '0'; - elsif xfer_en = '1' then - xfer_bsy <= '1'; - if xfer_cnt_en = '1' or xfer_bsy = '0' then - if xfer_cnt /= 1 then - xfer_cnt <= xfer_cnt - 1; - xfer_size <= xfer_size + 1; - else - xfer_pre_rdy <= '1'; - end if; - if xfer_pre_rdy = '1' then - xfer_bsy <= '0'; - end if; + if fill_set = '1' then + fill_size <= (others => '0'); + fill_rdy <= '0'; + fill_cnt <= pkt_nwords; + elsif fill_en = '1' then + if fill_cnt /= 0 then + fill_cnt <= fill_cnt - 1; + fill_size <= fill_size + 1; + else + fill_rdy <= '1'; end if; end if; end if; @@ -267,176 +210,26 @@ xfer_counter: end process; ------------------------------------------------------------------ -pkt_data_gen: - process(clk) - variable data : unsigned(7 downto 0); - begin - if rising_edge(clk) then - if xfer_set = '1' then - data := (others => '0'); - elsif xfer_cnt_en = '1' or xfer_bsy = '0' then - pkt_data(7 downto 0) <= data; - data := data + 1; - pkt_data(15 downto 8) <= data; - data := data + 1; - pkt_data(23 downto 16) <= data; - data := data + 1; - pkt_data(31 downto 24) <= data; - data := data + 1; - end if; - end if; - - end process; - ------------------------------------------------------------------- -stream_state_next: - process(mii_tx_clk) - begin - if rising_edge(mii_tx_clk) then - if rst = '1' then - stream_s <= stream_init; - else - stream_s <= stream_sn; - end if; - end if; - end process; - -stream_state: - process(stream_s, ifg_idle, mii_fifo_empty, piso8_din_rdy, piso8_dout_vld) - begin - - piso8_din_vld <= '0'; - mii_fifo_re <= '0'; - preamble_en <= '0'; - preamble_addr <= 0; - - stream_sn <= stream_s; - - case stream_s is - - when stream_init => - if mii_fifo_empty = '1' then - stream_sn <= stream_idle; - end if; - - when stream_idle => - if mii_fifo_empty = '0' and piso8_din_rdy = '1' then - stream_sn <= stream_start; - end if; - - when stream_start => - stream_sn <= stream_preamble0; - - when stream_preamble0 => - preamble_addr <= 0; - preamble_en <= '1'; - piso8_din_vld <= '1'; - if piso8_din_rdy = '1' then - stream_sn <= stream_preamble1; - end if; - - when stream_preamble1 => - preamble_addr <= 1; - preamble_en <= '1'; - piso8_din_vld <= '1'; - if piso8_din_rdy = '1' then - stream_sn <= stream_active; - end if; - - when stream_active => - piso8_din_vld <= not mii_fifo_empty; - mii_fifo_re <= piso8_din_rdy; - if mii_fifo_empty = '1' then - stream_sn <= stream_crc; - end if; - - when stream_crc => - stream_sn <= stream_stop; - - when stream_stop => - if piso8_dout_vld = '0' then - stream_sn <= stream_finish; - end if; - - when stream_finish => - if ifg_idle = '0' then - stream_sn <= stream_idle; - end if; - - when others => - stream_sn <= stream_idle; - end case; - - end process; - ------------------------------------------------------------------- --- Instantiate synchronous FIFO -inst_mii_fifo: entity work.fifo_async +inst_emac_tx : entity work.emac_tx GENERIC MAP ( - addr_width => 4, - data_width => mii_fifo_din'length, - do_last_read_update => true - ) - PORT MAP - ( - rst => rst, - clk_w => clk, - clk_r => 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 => mii_fifo_din, - data_r => mii_fifo_dout - ); - -inst_piso : entity work.piso - GENERIC MAP - ( - data_width_in => 32, - data_width_out => 8, - msb_first => true + f_sysclk => f_sysclk, + RAM_SIZE => TX_RAM_SIZE ) PORT MAP ( + clk => clk, rst => rst, - clk => mii_tx_clk, - din_vld => piso8_din_vld, - din_rdy => piso8_din_rdy, - din_be => piso8_din_be, - din => piso8_din, - dout_vld => piso8_dout_vld, - dout_en => piso8_dout_en, - dout => piso8_dout + din_vld => tx_din_vld, + din => tx_din, + ctrl_in => tx_ctrl_in, + ctrl_out => tx_ctrl_out, + mii_tx_clk => mii_tx_clk, + mii_tx_en => mii_tx_en, + mii_tx_er => mii_tx_er, + mii_tx => mii_tx ); - piso8_dout_en <= piso4_din_rdy and ifg_idle; - -inst_piso_10mbps : entity work.piso - GENERIC MAP - ( - data_width_in => 8, - data_width_out => 4, - msb_first => false - ) - PORT MAP - ( - rst => rst, - clk => mii_tx_clk, - din_vld => piso8_dout_vld, - din_rdy => piso4_din_rdy, - din_be => "11", - din => piso8_dout, - dout_vld => tx_en, - dout_en => '1', - dout => mii_tx(3 downto 0) - - ); - mii_tx_en <= tx_en; - mii_tx(7 downto 4) <= "0000"; end behavior;