Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@891 cc03376c-175c-47c8-b038-4cd826a8556b
231 lines
5.1 KiB
VHDL
231 lines
5.1 KiB
VHDL
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;
|