LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; USE IEEE.MATH_REAL.ALL; use std.textio.all; -- Imports the standard textio package. use work.emac_types.all; use work.utils_pkg.all; ENTITY pkt_gen IS Generic ( f_sysclk : real := 100.0; TX_RAM_SIZE : natural := 2048; PKT_SIZE_MIN : natural := 64; PKT_SIZE_MAX : natural := 1518 ); Port ( clk : in STD_LOGIC; rst : in STD_LOGIC; en : in STD_LOGIC; gigabit_en : in STD_LOGIC; fcs_gen_en : in STD_LOGIC; mii_tx_clk : in STD_LOGIC; mii_tx_en : out STD_LOGIC; mii_tx_er : out STD_LOGIC; mii_tx : out unsigned(7 downto 0) ); END pkt_gen; ARCHITECTURE behavior OF pkt_gen IS subtype word_ptr_t is unsigned(15 downto 0); signal pkt_data : unsigned(31 downto 0); signal pkt_nbytes : word_ptr_t := X"0040"; signal pkt_nwords : word_ptr_t := X"0010"; 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 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; 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 ------------------------------------------------------------------ host_state_next: process(clk) begin if rising_edge(clk) then if rst = '1' then host_s <= host_init; else host_s <= host_sn; end if; end if; end process; host_state: process(host_s, tx_ctrl_out, pkt_nbytes, fill_rdy, en, gigabit_en, fcs_gen_en) begin tx_ctrl_in.pkt_alloc_en <= '0'; tx_ctrl_in.pkt_commit_en <= '0'; tx_ctrl_in.reset <= '0'; tx_ctrl_in.Gbps_en <= gigabit_en; tx_ctrl_in.fcs_gen_en <= fcs_gen_en; tx_ctrl_in.tx_size <= pkt_nbytes; fill_set <= '0'; fill_en <= '0'; host_sn <= host_s; case host_s is when host_init => if tx_ctrl_out.reset_busy = '0' then host_sn <= host_idle; end if; 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 => host_sn <= host_idle; end case; end process; ------------------------------------------------------------------ pkt_generator: process(clk) variable size : word_ptr_t; variable krand : real; variable seed1 : integer; variable seed2 : integer; begin if rising_edge(clk) then if rst = '1' then size := to_unsigned(PKT_SIZE_MIN, word_ptr_t'length); seed1 := 31101970; seed2 := 12586901; tx_packets <= 0; tx_bytes <= 0; 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); tx_packets <= tx_packets + 1; tx_bytes <= tx_bytes + to_integer(pkt_nbytes); end if; pkt_nbytes <= size; if size(1 downto 0) = 0 then pkt_nwords <= "00" & size(word_ptr_t'left downto 2); else pkt_nwords <= "00" & size(word_ptr_t'left downto 2) + 1; end if; end if; end process; ------------------------------------------------------------------ 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 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; end process; ------------------------------------------------------------------ inst_emac_tx : entity work.emac_tx GENERIC MAP ( f_sysclk => f_sysclk, RAM_SIZE => TX_RAM_SIZE ) PORT MAP ( clk => clk, rst => rst, 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 ); end behavior;