------------------------------------------------------------------------- -- 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 := 8 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 => '-'); -- 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; signal loop_back_en : std_logic := '0'; type emac_action_t is (emac_idle, emac_alloc, emac_wait_alloc, emac_write, emac_wait_data, emac_read, emac_free); signal emac_action : emac_action_t; 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 ); 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; mii_rx_clk_board <= mii_rx_clk; mii_tx_clk_board <= 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; mii_rx <= mii_tx when loop_back_en = '1' else (others => 'Z'); mii_rx_dv <= mii_tx_en when loop_back_en = '1' else '0'; mii_rx_er <= mii_tx_er when loop_back_en = '1' else '0'; mii_crs <= '0'; mii_col <= '0'; -- Master STIMULUS: process 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, 16) & X"55AA"; STB_I <= '1'; WE_I <= '1'; ADDR_I <= X"0000_0004"; wait until rising_edge(CLK) and SRDY_O = '1'; STB_I <= '0'; -- set alloc request CYC_I <= '1'; wait until rising_edge(CLK) and SRDY_O = '1'; DAT_I <= X"0002_0000"; STB_I <= '1'; WE_I <= '1'; ADDR_I <= X"0000_0000"; wait until rising_edge(CLK) and SRDY_O = '1'; STB_I <= '0'; WE_I <= '0'; -- check alloc busy emac_action <= emac_wait_alloc; check_bsy: while (true) loop CYC_I <= '1'; wait until rising_edge(CLK) and SRDY_O = '1'; STB_I <= '1'; ADDR_I <= X"0000_0000"; wait until rising_edge(CLK) and SRDY_O = '1'; STB_I <= '0'; wait until rising_edge(CLK) and ACK_O = '1'; wait until rising_edge(CLK); if DAT_O_reg(17) = '0' then exit check_bsy; end if; end loop; emac_action <= emac_idle; end procedure emac_alloc; 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 <= X"0000_0008"; 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_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 <= X"0000_0000"; wait until rising_edge(CLK) and SRDY_O = '1'; STB_I <= '0'; wait until rising_edge(CLK) and ACK_O = '1'; wait until rising_edge(CLK); if DAT_O_reg(16) = '1' then exit check_data_avail; end if; end loop; read_size: CYC_I <= '1'; wait until rising_edge(CLK) and SRDY_O = '1'; WE_I <= '0'; STB_I <= '1'; ADDR_I <= X"0000_0004"; wait until rising_edge(CLK) and SRDY_O = '1'; STB_I <= '0'; wait until rising_edge(CLK) and ACK_O = '1'; wait until rising_edge(CLK); emac_action <= emac_read; -- Read RX data size := size_in; if (size_in = 0) then size := to_integer(DAT_O_reg(15 downto 0)); end if; 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 <= X"0000_0008"; 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 SRDY_O = '1'; 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'; DAT_I <= X"0001_0000"; STB_I <= '1'; WE_I <= '1'; ADDR_I <= X"0000_0000"; wait until rising_edge(CLK) and SRDY_O = '1'; STB_I <= '0'; WE_I <= '0'; emac_action <= emac_idle; end procedure emac_free; begin wait for 6*MII_CLK_PERIOD; RST <= '0'; wait for 60*CLK_PERIOD; loop_back_en <= '1'; emac_alloc (1536); emac_write (1536); emac_read (0); emac_free; emac_alloc (1536); emac_write (1536); emac_read (0); emac_free; emac_alloc (1536); emac_write (1536); emac_read (0); emac_free; emac_alloc (1536); emac_write (1536); emac_read (0); emac_free; emac_alloc (1536); emac_write (1536); emac_read (0); emac_free; emac_alloc (1536); emac_write (1536); emac_read (0); emac_free; emac_alloc (1536); emac_write (1536); emac_read (0); emac_free; emac_alloc (64); emac_write (64); emac_read (0); emac_free; emac_alloc (512); emac_write (512); emac_read (0); emac_free; emac_alloc (1536); emac_write (1536); emac_read (0); emac_free; emac_alloc (65); emac_write (65); emac_read (0); emac_free; emac_alloc (66); emac_write (66); emac_read (0); emac_free; emac_alloc (67); emac_write (67); emac_read (0); emac_free; emac_alloc (512); emac_write (64); emac_alloc (128); emac_write (128); emac_read (0); emac_free; wait; end process; END;