------------------------------------------------------------------------- -- 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_jb IS END tb_emac_jb; ARCHITECTURE behavior OF tb_emac_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); signal ACK_O : std_logic; signal INT_O : std_logic; signal MRDY_I : std_logic; 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 shift_sa : integer := 0; signal shift_din_vld : std_logic := '0'; signal shift_din : unsigned(31 downto 0) := (others => '-'); signal shift_dout_vld : std_logic; signal shift_dout : unsigned(31 downto 0); signal piso_din_vld : std_logic := '0'; signal piso_din_rdy : std_logic; signal piso_din_be : unsigned(7 downto 0) := (others => '0'); signal piso_din : unsigned(31 downto 0) := (others => '-'); signal piso_dout_en : std_logic; signal piso_dout : unsigned(3 downto 0); signal sipo_enable : std_logic := '0'; signal sipo_din_en : std_logic := '0'; signal sipo_din : unsigned(3 downto 0) := (others => '-'); signal sipo_dout_vld : std_logic; signal sipo_dout_be : unsigned(7 downto 0); signal sipo_dout : unsigned(31 downto 0); type emac_action_t is (emac_idle, emac_alloc, emac_write, emac_read); signal emac_action : emac_action_t; BEGIN inst_emac_jb : entity work.emac_jb GENERIC MAP ( f_sysclk => 100.0, 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_shifter : entity work.shifter GENERIC MAP ( data_width => 32, aggregate_size => 4, do_pipelined => true ) PORT MAP ( rst => RST, clk => CLK, sa => shift_sa, din_vld => shift_din_vld, din => shift_din, dout_vld => shift_dout_vld, dout => shift_dout ); inst_piso : entity work.piso GENERIC MAP ( data_width_in => 32, data_width_out => 4, msb_first => true ) PORT MAP ( rst => RST, clk => CLK, din_vld => piso_din_vld, din_rdy => piso_din_rdy, din_be => piso_din_be, din => piso_din, dout_en => piso_dout_en, dout => piso_dout ); inst_sipo : entity work.sipo GENERIC MAP ( data_width_in => 4, data_width_out => 32, msb_first => true ) PORT MAP ( rst => RST, clk => CLK, enable => sipo_enable, din_en => sipo_din_en, din => sipo_din, dout_be => sipo_dout_be, dout_vld => sipo_dout_vld, dout => sipo_dout ); sipo_din <= piso_dout; sipo_din_en <= piso_dout_en; 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; -- 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"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'; -- check alloc busy 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(16) = '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; begin wait for 6*MII_CLK_PERIOD; RST <= '0'; wait for 60*CLK_PERIOD; emac_alloc (1536); emac_write (1536); emac_alloc (1536); emac_write (1536); emac_alloc (1536); emac_write (1536); emac_alloc (1536); emac_write (1536); emac_alloc (1536); emac_write (1536); emac_alloc (1536); emac_write (1536); emac_alloc (1536); emac_write (1536); emac_alloc (64); emac_write (64); emac_alloc (512); emac_write (512); emac_alloc (1536); emac_write (1536); emac_alloc (65); emac_write (65); emac_alloc (66); emac_write (66); emac_alloc (67); emac_write (67); emac_alloc (512); emac_write (512); wait for 4000*CLK_PERIOD; wait until rising_edge(CLK); shift_din <= X"12345678"; shift_sa <= 0; shift_din_vld <= '1'; wait until rising_edge(CLK); shift_sa <= shift_sa + 1; wait until rising_edge(CLK); shift_sa <= shift_sa + 1; wait until rising_edge(CLK); shift_sa <= shift_sa + 1; wait until rising_edge(CLK); shift_sa <= shift_sa + 1; wait until rising_edge(CLK); shift_sa <= shift_sa + 1; wait until rising_edge(CLK); shift_sa <= shift_sa + 1; wait until rising_edge(CLK); shift_sa <= shift_sa + 1; wait until rising_edge(CLK); shift_sa <= 0; wait until rising_edge(CLK); shift_sa <= shift_sa - 1; wait until rising_edge(CLK); shift_sa <= shift_sa - 1; wait until rising_edge(CLK); shift_sa <= shift_sa - 1; wait until rising_edge(CLK); shift_sa <= shift_sa - 1; wait until rising_edge(CLK); shift_sa <= shift_sa - 1; wait until rising_edge(CLK); shift_sa <= shift_sa - 1; wait until rising_edge(CLK); shift_sa <= shift_sa - 1; wait until rising_edge(CLK); shift_din_vld <= '0'; for i in 1 to 10 loop wait until rising_edge(CLK); sipo_enable <= '1'; piso_din_vld <= '1'; piso_din <= X"12345678"; piso_din_be <= "11111111"; wait until rising_edge(CLK) and piso_din_rdy = '1'; piso_din <= piso_din + X"12345678"; piso_din_be <= "11100111"; wait until rising_edge(CLK) and piso_din_rdy = '1'; piso_din <= piso_din + X"12345678"; piso_din_be <= "11111100"; wait until rising_edge(CLK) and piso_din_rdy = '1'; piso_din <= piso_din + X"12345678"; piso_din_be <= "00111111"; wait until rising_edge(CLK) and piso_din_rdy = '1'; piso_din <= (others => '-'); piso_din_vld <= '0'; wait until rising_edge(CLK) and sipo_dout_vld = '1'; wait until rising_edge(CLK); wait until rising_edge(CLK) and sipo_dout_vld = '1'; sipo_enable <= '0'; wait for 33*CLK_PERIOD; end loop; wait; end process; END;