Files
vhdl/lib/emac/src/tb_emac_top_jb.vhd
T
jens 9b50ec6a5b - test both 100 Mbps and 1000 Mbps
git-svn-id: http://moon:8086/svn/vhdl/trunk@1333 cc03376c-175c-47c8-b038-4cd826a8556b
2015-12-13 13:18:35 +00:00

820 lines
17 KiB
VHDL

-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: testbench for system test using Xilinx ML-402
-- Copyright (C) 2007 J. Ahrensfeld
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- For questions and ideas, please contact the author at jens@jayfield.org
-----------------------------------------------------------------------
LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY tb_emac_top_jb IS
END tb_emac_top_jb;
ARCHITECTURE behavior OF tb_emac_top_jb IS
constant CLK_PERIOD : time := 10 ns;
constant MII_CLK_PERIOD : time := 37.7 ns;
constant GMII_CLK_PERIOD : time := 8.0 ns;
signal CLK : std_logic := '1';
signal RST : std_logic := '1';
-- Slave
signal CYC_I : std_logic := '0';
signal STB_I : std_logic := '0';
signal WE_I : std_logic := '0';
signal SEL_I : unsigned(3 downto 0) := (others => '1');
signal ACK_O : std_logic;
signal INT_O : std_logic;
signal MRDY_I : std_logic := '0';
signal SRDY_O : std_logic;
signal ADDR_I : unsigned(31 downto 0) := (others => '-');
signal DAT_I : unsigned(31 downto 0) := (others => '-');
signal DAT_O : unsigned(31 downto 0) := (others => '-');
signal DAT_O_reg : unsigned(31 downto 0) := (others => '-');
signal status_reg : unsigned(31 downto 0) := (others => '0');
signal size_reg : unsigned(31 downto 0) := (others => '0');
-- MII signals
signal mii_rx_clk_board : std_logic := '1';
signal mii_tx_clk_board : std_logic := '1';
signal mii_rx_clk : std_logic := '1';
signal mii_tx_clk : std_logic := '1';
signal mii_rx : unsigned(7 downto 0) := (others => '-');
signal mii_tx : unsigned(7 downto 0);
signal mii_rx_dv : std_logic := '0';
signal mii_rx_er : std_logic := '0';
signal mii_tx_en : std_logic;
signal mii_tx_er : std_logic;
signal mii_crs : std_logic := '0';
signal mii_col : std_logic := '0';
signal mii_gtx_clk : std_logic := '0';
signal loop_back_en : std_logic := '0';
signal gigabit_rx_en : std_logic := '0';
signal gigabit_tx_en : std_logic := '0';
signal pktgen_tx : unsigned(7 downto 0);
signal pktgen_tx_en : std_logic;
signal pktgen_tx_er : std_logic;
signal pktgen_en : std_logic := '0';
signal pktgen_gigabit : std_logic := '0';
signal pktgen_fcs_en : std_logic := '0';
signal dat_o_cnt_en : std_logic := '0';
signal dat_o_cnt_rst : std_logic := '1';
signal dat_o_cnt : natural;
signal pkt_count : natural;
type emac_action_t is (emac_idle, emac_alloc, emac_write, emac_commit, emac_wait_data, emac_read, emac_free);
signal emac_action : emac_action_t;
constant RX_STATUS_REG_ADDR : unsigned(31 downto 0) := X"0000_0000";
constant RX_SIZE_REG_ADDR : unsigned(31 downto 0) := X"0000_0004";
constant TX_STATUS_REG_ADDR : unsigned(31 downto 0) := X"0000_0008";
constant TX_SIZE_REG_ADDR : unsigned(31 downto 0) := X"0000_000C";
constant DATA_REG_ADDR : unsigned(31 downto 0) := X"0000_8000";
BEGIN
inst_emac_top_jb : entity work.emac_top_jb
GENERIC MAP
(
f_sysclk => 100.0,
RX_RAM_SIZE => 2048,
TX_RAM_SIZE => 2048
)
PORT MAP
(
CLK_I => CLK,
RST_I => RST,
INT_O => INT_O,
CYC_I => CYC_I,
STB_I => STB_I,
SEL_I => SEL_I,
WE_I => WE_I,
ACK_O => ACK_O,
SRDY_O => SRDY_O,
MRDY_I => MRDY_I,
ADDR_I => ADDR_I,
DAT_I => DAT_I,
DAT_O => DAT_O,
mii_rx_clk => mii_rx_clk_board,
mii_rx_dv => mii_rx_dv,
mii_rx_er => mii_rx_er,
mii_rx => mii_rx,
mii_tx_clk => mii_tx_clk_board,
mii_tx_en => mii_tx_en,
mii_tx_er => mii_tx_er,
mii_tx => mii_tx,
mii_gtx_clk => mii_gtx_clk,
mii_crs => mii_crs,
mii_col => mii_col
);
inst_pkt_gen : entity work.pkt_gen
GENERIC MAP
(
f_sysclk => 100.0,
PKT_SIZE_MIN => 64,
PKT_SIZE_MAX => 1512
)
PORT MAP
(
clk => CLK,
rst => RST,
en => pktgen_en,
gigabit_en => pktgen_gigabit,
fcs_gen_en => pktgen_fcs_en,
mii_tx_clk => mii_tx_clk_board,
mii_tx_en => pktgen_tx_en,
mii_tx_er => pktgen_tx_er,
mii_tx => pktgen_tx
);
CLK_GEN: process
begin
wait for CLK_PERIOD/2;
CLK <= not CLK;
end process;
MII_CLK_GEN: process
begin
wait for MII_CLK_PERIOD/2;
mii_rx_clk <= not mii_rx_clk;
mii_tx_clk <= not mii_tx_clk;
end process;
GMII_CLK_GEN: process
begin
wait for GMII_CLK_PERIOD/2;
mii_gtx_clk <= not mii_gtx_clk;
end process;
mii_rx_clk_board <= mii_gtx_clk when gigabit_rx_en = '1' else mii_rx_clk;
mii_tx_clk_board <= mii_gtx_clk when gigabit_tx_en = '1' else mii_tx_clk;
DAT_O_register:
process(CLK)
begin
if rising_edge(CLK) then
if ACK_O = '1' then
DAT_O_reg <= DAT_O;
end if;
end if;
end process;
DAT_O_count_register:
process(CLK)
begin
if rising_edge(CLK) then
if dat_o_cnt_rst = '1' then
dat_o_cnt <= 0;
elsif ACK_O = '1' and dat_o_cnt_en = '1' then
dat_o_cnt <= dat_o_cnt + 1;
end if;
end if;
end process;
mii_rx <= mii_tx when loop_back_en = '1' else pktgen_tx;
mii_rx_dv <= mii_tx_en when loop_back_en = '1' else pktgen_tx_en;
mii_rx_er <= mii_tx_er when loop_back_en = '1' else pktgen_tx_er;
mii_crs <= '0';
mii_col <= '0';
-- Master
STIMULUS: process
procedure emac_tx_reset_100mbps is
begin
gigabit_tx_en <= '0';
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"A000_0000";
STB_I <= '1';
WE_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
end procedure emac_tx_reset_100mbps;
procedure emac_rx_reset_100mbps is
begin
gigabit_rx_en <= '0';
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"A000_0000";
STB_I <= '1';
WE_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
end procedure emac_rx_reset_100mbps;
procedure emac_tx_reset_1000mbps is
begin
gigabit_tx_en <= '1';
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"E000_0000";
STB_I <= '1';
WE_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
end procedure emac_tx_reset_1000mbps;
procedure emac_rx_reset_1000mbps is
begin
gigabit_rx_en <= '1';
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"E000_0000";
STB_I <= '1';
WE_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
end procedure emac_rx_reset_1000mbps;
procedure emac_alloc (size : natural) is
begin
-- TX-ALLOCATION
-- set TX-size
emac_action <= emac_alloc;
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= to_unsigned(size, 32);
STB_I <= '1';
WE_I <= '1';
ADDR_I <= TX_SIZE_REG_ADDR;
check_alloc_ok:
while(true) loop
-- set alloc request
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"0002_0000" or (not X"0001_0000" and status_reg);
STB_I <= '1';
WE_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
check_bsy:
while (true) loop
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK);
if status_reg(17) = '0' then
exit check_bsy;
end if;
end loop;
if status_reg(16) = '1' then
exit check_alloc_ok;
end if;
end loop;
CYC_I <= '0';
emac_action <= emac_idle;
end procedure emac_alloc;
procedure emac_commit is
begin
-- RX- DEALLOCATION
emac_action <= emac_commit;
-- set free request
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"0001_0000" or (not X"0002_0000" and status_reg);
STB_I <= '1';
WE_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
emac_action <= emac_idle;
end procedure emac_commit;
procedure emac_write (size : natural) is
variable data : unsigned (7 downto 0);
variable num_words : natural;
begin
-- FILL TX data
emac_action <= emac_write;
if (size mod 4) = 0 then
num_words := size/4;
else
num_words := size/4 + 1;
end if;
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
data := X"00";
ADDR_I <= DATA_REG_ADDR;
WE_I <= '1';
for i in 1 to num_words loop
STB_I <= '1';
DAT_I(7 downto 0) <= data;
data := data + 1;
DAT_I(15 downto 8) <= data;
data := data + 1;
DAT_I(23 downto 16) <= data;
data := data + 1;
DAT_I(31 downto 24) <= data;
data := data + 1;
wait until rising_edge(CLK) and SRDY_O = '1';
end loop;
STB_I <= '0';
wait until rising_edge(CLK) and SRDY_O = '1';
emac_commit;
emac_action <= emac_idle;
end procedure emac_write;
procedure emac_read (size_in : natural) is
variable data : unsigned (7 downto 0);
variable size, num_words : natural;
begin
emac_action <= emac_wait_data;
-- check if data available
check_data_avail:
while (true) loop
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK);
if status_reg(17) = '1' and status_reg(16) = '1' then
exit check_data_avail;
end if;
end loop;
read_size:
dat_o_cnt_rst <= '1';
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= RX_SIZE_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
size_reg <= DAT_O;
wait until rising_edge(CLK);
-- set packet request
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"0002_0000" or (not X"0001_0000" and status_reg);
STB_I <= '1';
WE_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
emac_action <= emac_read;
-- Read RX data
size := size_in;
if (size_in = 0) then
size := to_integer(size_reg(15 downto 0));
end if;
if (size mod 4) = 0 then
num_words := size/4;
else
num_words := size/4 + 1;
end if;
dat_o_cnt_rst <= '0';
dat_o_cnt_en <= '1';
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
ADDR_I <= DATA_REG_ADDR;
WE_I <= '0';
STB_I <= '1';
for i in 1 to num_words loop
wait until rising_edge(CLK) and SRDY_O = '1';
end loop;
STB_I <= '0';
wait until rising_edge(CLK) and dat_o_cnt = num_words;
dat_o_cnt_en <= '0';
emac_action <= emac_idle;
end procedure emac_read;
procedure emac_free is
begin
-- RX- DEALLOCATION
emac_action <= emac_free;
-- set free request
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"0001_0000" or (not X"0002_0000" and status_reg);
STB_I <= '1';
WE_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
emac_action <= emac_idle;
end procedure emac_free;
begin
-- 100 Mbps
wait for 6*MII_CLK_PERIOD;
RST <= '0';
wait for 60*CLK_PERIOD;
emac_rx_reset_100mbps;
emac_tx_reset_100mbps;
pktgen_gigabit <= '0';
pktgen_fcs_en <= '1';
wait for 60*CLK_PERIOD;
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
for i in 1 to 1 loop
for j in 1 to 10 loop
emac_alloc (72);
emac_write (72);
end loop;
wait for 1 ms;
end loop;
wait for 60*CLK_PERIOD;
wait until rising_edge(mii_tx_clk_board) and mii_tx_en = '0';
loop_back_en <= '1';
emac_alloc (74);
emac_write (74);
emac_alloc (105);
emac_write (105);
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_alloc (103);
emac_write (103);
emac_read (0);
emac_free;
emac_alloc (71);
emac_write (71);
emac_read (0);
emac_free;
emac_alloc (82);
emac_write (82);
emac_alloc (86);
emac_write (86);
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_alloc (77);
emac_write (77);
emac_alloc (99);
emac_write (99);
emac_alloc (65);
emac_write (65);
emac_alloc (321);
emac_write (321);
emac_read (0);
emac_free;
emac_alloc (1111);
emac_write (1111);
emac_read (0);
emac_free;
emac_alloc (73);
emac_write (73);
emac_alloc (107);
emac_write (107);
emac_alloc (83);
emac_write (83);
emac_read (0);
emac_free;
emac_alloc (72);
emac_write (72);
emac_alloc (1003);
emac_write (1003);
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
wait for 60*CLK_PERIOD;
loop_back_en <= '0';
pktgen_en <= '1';
pkt_count <= 0;
for i in 1 to 500 loop
wait for 1 us;
emac_read (0);
emac_free;
pkt_count <= pkt_count + 1;
end loop;
pktgen_en <= '0';
emac_read (0);
emac_free;
-- 1000 MBps
RST <= '1';
wait for 6*MII_CLK_PERIOD;
RST <= '0';
wait for 60*CLK_PERIOD;
emac_rx_reset_1000mbps;
emac_tx_reset_1000mbps;
pktgen_gigabit <= '1';
pktgen_fcs_en <= '1';
wait for 60*CLK_PERIOD;
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
for i in 1 to 1 loop
for j in 1 to 10 loop
emac_alloc (72);
emac_write (72);
end loop;
wait for 1 ms;
end loop;
wait for 60*CLK_PERIOD;
wait until rising_edge(mii_tx_clk_board) and mii_tx_en = '0';
loop_back_en <= '1';
emac_alloc (74);
emac_write (74);
emac_alloc (105);
emac_write (105);
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_alloc (103);
emac_write (103);
emac_read (0);
emac_free;
emac_alloc (71);
emac_write (71);
emac_read (0);
emac_free;
emac_alloc (82);
emac_write (82);
emac_alloc (86);
emac_write (86);
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_alloc (77);
emac_write (77);
emac_alloc (99);
emac_write (99);
emac_alloc (65);
emac_write (65);
emac_alloc (321);
emac_write (321);
emac_read (0);
emac_free;
emac_alloc (1111);
emac_write (1111);
emac_read (0);
emac_free;
emac_alloc (73);
emac_write (73);
emac_alloc (107);
emac_write (107);
emac_alloc (83);
emac_write (83);
emac_read (0);
emac_free;
emac_alloc (72);
emac_write (72);
emac_alloc (1003);
emac_write (1003);
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
wait for 60*CLK_PERIOD;
loop_back_en <= '0';
pktgen_en <= '1';
pkt_count <= 0;
for i in 1 to 500 loop
wait for 1 us;
emac_read (0);
emac_free;
pkt_count <= pkt_count + 1;
end loop;
pktgen_en <= '0';
emac_read (0);
emac_free;
wait;
end process;
END;