-- -------------------------------------------------------------------------- -- -- TRASHERNET - A Trashy Ethernet Stack for FPGAs -- -- -------------------------------------------------------------------------- -- -- top_mac_test.vhd: Test design to verify the functionality of the MAC core -- Sends a broadcast with 100 decrementing numbers every 250 ms or when a -- button is pushed. It will also directly reply with that content to any -- packet addressed to us. -- -- Target: Lattice Brevia 2 (LFXP2-5E) -- -------------------------------------------------------------------------- -- -- Author : Markus Koch -- Contributors : None -- License : Mozilla Public License (MPL) Version 2 -- -------------------------------------------------------------------------- -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; library trashernet; use trashernet.trashernet_pkg.all; entity top_mac_test is port( clk : in std_logic; rst_n : in std_logic; rx_p : in std_logic; tx_p : out std_logic; tx_n : out std_logic; led_n : out std_logic_vector(7 downto 0); button_n : in std_logic_vector(3 downto 0); debug_data : out std_logic_vector(7 downto 0) ); end entity top_mac_test; architecture rtl of top_mac_test is component pll0 port( CLK : in std_logic; CLKOP : out std_logic; LOCK : out std_logic ); end component pll0; constant F_CLK : integer := 50000000; constant F_CLK_PHY : integer := 140000000; constant LED_BLINK : boolean_vector(led_n'range) := ( 6 downto 2 => true, others => false ); constant ETH_CONFIG : configuration_t := ( mac_address => (x"00", x"ff", x"ff", x"11", x"22", x"33") ); signal rst : std_logic; signal clk_phy : std_logic; signal phy_pll_lock : std_logic; signal led_sig : std_logic_vector(led_n'range); signal phy_out : phy_out_t; signal phy_in : phy_in_t; signal mac_out : mac_out_t; signal mac_in : mac_in_t; type status_t is (IDLE, TX); signal state : status_t; constant BYTE_CNT_MAX : integer := 100; signal byte_cnt : integer range 0 to BYTE_CNT_MAX; signal button_n_sync : std_logic_vector(button_n'range); signal button : std_logic_vector(button_n'range); constant TMO_MAX : integer := integer(round((real(F_CLK) * 0.25))) - 1; signal tmo : integer range 0 to TMO_MAX; begin trashernet_mac_inst : entity trashernet.trashernet_mac port map( clk => clk, rst => rst, phy_out => phy_out, phy_in => phy_in, mac_out => mac_out, mac_in => mac_in ); pll0_inst : pll0 port map( CLK => clk, CLKOP => clk_phy, LOCK => phy_pll_lock ); trashernet_phy_cdc_inst : entity trashernet.trashernet_phy_cdc generic map( F_CLK => F_CLK, F_CLK_PHY => F_CLK_PHY ) port map( clk => clk, phy_clk => clk_phy, rst => rst, phy_out => phy_out, phy_in => phy_in, rx_p => rx_p, tx_p => tx_p, tx_n => tx_n ); reset_sync : process(clk, rst_n) is begin if (rst_n = '0') then rst <= '1'; elsif (rising_edge(clk)) then rst <= '0'; end if; end process reset_sync; ledcon_inst : entity work.ledcon generic map( F_CLK => F_CLK, BLINK => LED_BLINK ) port map( clk => clk, rst => rst, sig => led_sig, led_n => led_n ); led_sig <= ( 0 => phy_pll_lock, 1 => phy_out.carrier_detect, 2 => phy_out.rx_active, 3 => phy_out.rx_error, 4 => mac_out.rx_mac_crc_ok, 5 => mac_out.rx_mac_crc_error, 6 => mac_out.tx_active, 7 => '0' ); synchronizer_inst : entity trashernet.synchronizer generic map( SIZE => 2 ) port map( clk => clk, rst => rst, data_in => button_n(0), data_out => button_n_sync(0) ); button <= not button_n_sync; receiver : process(clk, rst) is begin if rst then state <= IDLE; mac_in.tx_mac_data_en <= '0'; tmo <= 0; elsif rising_edge(clk) then if (tmo /= 0) then tmo <= tmo - 1; end if; case state is when IDLE => if mac_out.rx_mac_crc_ok then if (mac_out.rx_header.mac_destination = ETH_CONFIG.mac_address) then -- Note: We won't respond to broadcasts! state <= TX; byte_cnt <= BYTE_CNT_MAX; mac_in.tx_header.mac_destination <= mac_out.rx_header.mac_source; end if; end if; if (tmo = 0) or (button(0) = '1') then state <= TX; byte_cnt <= BYTE_CNT_MAX; mac_in.tx_header.mac_destination <= (others => x"FF"); end if; when TX => tmo <= TMO_MAX; mac_in.tx_header.mac_ethertype <= (x"00", std_logic_vector(to_unsigned(BYTE_CNT_MAX, 8))); mac_in.tx_mac_data_en <= '1'; mac_in.tx_mac_data <= std_logic_vector(to_unsigned(byte_cnt, 8)); if mac_out.tx_mac_data_ack then if byte_cnt = 1 then mac_in.tx_mac_data_en <= '0'; state <= IDLE; else byte_cnt <= byte_cnt - 1; end if; end if; end case; end if; end process receiver; mac_in.tx_header.mac_source <= ETH_CONFIG.mac_address; debug_data(0) <= tx_p; debug_data(1) <= tx_n; end architecture rtl;