----------------------------------------------------------------------------------
--									Test bench pro mac_core	  			  	  		  		  	  --
----------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
 
ENTITY mac_core_tb IS
END mac_core_tb;
 
ARCHITECTURE behavior OF mac_core_tb IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT mac_core
    PORT(
         GTXCLK : IN  std_logic;
         PHY_COL : IN  std_logic;
         PHY_CS : IN  std_logic;
         PHY_TXD : OUT  std_logic_vector(7 downto 0);
         PHY_TXEN : OUT  std_logic;
         PHY_TXER : OUT  std_logic;
         PHY_TXCLK : IN  std_logic;
         PHY_GTXCLK : OUT  std_logic;
         PHY_RXD : IN  std_logic_vector(7 downto 0);
         PHY_RXDV : IN  std_logic;
         PHY_RXER : IN  std_logic;
         PHY_RXCLK : IN  std_logic;
         PHY_RESET : OUT  std_logic;
         TX_CLK : OUT  std_logic;
         TX_DATA : IN  std_logic_vector(7 downto 0);
         TX_DATA_VLD : IN  std_logic;
         TX_DATA_ACK : OUT  std_logic;
         RX_CLK : OUT  std_logic;
         RX_DATA : OUT  std_logic_vector(7 downto 0);
         RX_DATA_VLD : OUT  std_logic;
         RX_DATA_GOOD : OUT  std_logic;
         RX_DATA_BAD : OUT  std_logic;
         COLLISION : OUT  std_logic;
         IFG : IN  std_logic_vector(7 downto 0);
         FULL_DUPLEX : IN  std_logic;
         SPEED1G : OUT  std_logic;
         RESET : IN  std_logic
        );
    END COMPONENT;
    

   --Inputs
   signal GTXCLK : std_logic := '0';
   signal PHY_COL : std_logic := '0';
   signal PHY_CS : std_logic := '0';
   signal PHY_TXCLK : std_logic := '0';
   signal PHY_RXD : std_logic_vector(7 downto 0) := (others => '0');
   signal PHY_RXDV : std_logic := '0';
   signal PHY_RXER : std_logic := '0';
   signal PHY_RXCLK : std_logic := '0';
   signal TX_DATA : std_logic_vector(7 downto 0) := (others => '0');
   signal TX_DATA_VLD : std_logic := '0';
   signal IFG : std_logic_vector(7 downto 0) := (others => '0');
   signal FULL_DUPLEX : std_logic := '0';
   signal RESET : std_logic := '0';

 	--Outputs
   signal PHY_TXD : std_logic_vector(7 downto 0);
   signal PHY_TXEN : std_logic;
   signal PHY_TXER : std_logic;
   signal PHY_GTXCLK : std_logic;
   signal PHY_RESET : std_logic;
   signal TX_CLK : std_logic;
   signal TX_DATA_ACK : std_logic;
   signal RX_CLK : std_logic;
   signal RX_DATA : std_logic_vector(7 downto 0);
   signal RX_DATA_VLD : std_logic;
   signal RX_DATA_GOOD : std_logic;
   signal RX_DATA_BAD : std_logic;
   signal COLLISION : std_logic;
   signal SPEED1G : std_logic;

   -- Clock period definitions
   constant GTXCLK_period : time := 8 ns;
   constant PHY_TXCLK_period : time := 8 ns;
   constant PHY_RXCLK_period : time := 8 ns;

	-- typ pro data 
	type data_typ is record
      data : bit_vector(7 downto 0); 
      valid : bit;                    
      error : bit;                    
	end record;
	type frame_typ is array (natural range <>) of data_typ;

  ----------------------------------------------------------------------
  -- Frame data 
  ----------------------------------------------------------------------
  constant IP_frame : frame_typ := (
        0      => ( DATA => X"AA", VALID => '1', ERROR => '0'), 	-- version + 
        1      => ( DATA => X"BB", VALID => '1', ERROR => '0'),	-- TOS
        2      => ( DATA => X"CC", VALID => '1', ERROR => '0'),	-- Total len H
        3      => ( DATA => X"DD", VALID => '1', ERROR => '0'),	-- Total len L
        4      => ( DATA => X"EE", VALID => '1', ERROR => '0'),	-- ID H
        5      => ( DATA => X"FF", VALID => '1', ERROR => '0'),	-- ID L
        6      => ( DATA => X"AB", VALID => '1', ERROR => '0'), 	-- flags + fragmentation
        7      => ( DATA => X"CD", VALID => '1', ERROR => '0'),	-- fragmentation
        8      => ( DATA => X"EF", VALID => '1', ERROR => '0'),	-- TTL
        9      => ( DATA => X"AA", VALID => '1', ERROR => '0'),	-- Protocol
       10      => ( DATA => X"BB", VALID => '1', ERROR => '0'),	-- Checksum H
       11      => ( DATA => X"CC", VALID => '1', ERROR => '0'),	-- Checksum L
       12      => ( DATA => X"08", VALID => '1', ERROR => '0'), 	-- Source IP
       13      => ( DATA => X"00", VALID => '1', ERROR => '0'), 	-- Source IP   
        14      => ( DATA => X"45", VALID => '1', ERROR => '0'), 	-- version + 
        15      => ( DATA => X"00", VALID => '1', ERROR => '0'),	-- TOS
        16      => ( DATA => X"00", VALID => '1', ERROR => '0'),	-- Total len H
        17     => ( DATA => X"16", VALID => '1', ERROR => '0'),	-- Total len L
        18     => ( DATA => X"00", VALID => '1', ERROR => '0'),	-- ID H
        19     => ( DATA => X"0A", VALID => '1', ERROR => '0'),	-- ID L
        20     => ( DATA => X"00", VALID => '1', ERROR => '0'), 	-- flags + fragmentation
        21     => ( DATA => X"00", VALID => '1', ERROR => '0'),	-- fragmentation
        22     => ( DATA => X"03", VALID => '1', ERROR => '0'),	-- TTL
        23     => ( DATA => X"11", VALID => '1', ERROR => '0'),	-- Protocol
       24     => ( DATA => X"5D", VALID => '1', ERROR => '0'),	-- Checksum H
       25      => ( DATA => X"F0", VALID => '1', ERROR => '0'),	-- Checksum L
       26      => ( DATA => X"C0", VALID => '1', ERROR => '0'), 	-- Source IP
       27      => ( DATA => X"A8", VALID => '1', ERROR => '0'), 	-- Source IP
       28      => ( DATA => X"00", VALID => '1', ERROR => '0'), 	-- Source IP
       29      => ( DATA => X"01", VALID => '1', ERROR => '0'), 	-- Source IP
       30      => ( DATA => X"0A", VALID => '1', ERROR => '0'), 	-- Dest. IP
       31      => ( DATA => X"14", VALID => '1', ERROR => '0'),	-- Dest. IP
       32      => ( DATA => X"02", VALID => '1', ERROR => '0'),	-- Dest. IP
       33      => ( DATA => X"D5", VALID => '1', ERROR => '0'), 	-- Dest. IP
       34      => ( DATA => X"DD", VALID => '1', ERROR => '0'),	-- data bajt 0 ------------------
       35      => ( DATA => X"01", VALID => '1', ERROR => '0'), 
       36      => ( DATA => X"AB", VALID => '1', ERROR => '0'),
       37      => ( DATA => X"CD", VALID => '1', ERROR => '0'), 
       38      => ( DATA => X"EF", VALID => '1', ERROR => '0'),
       39      => ( DATA => X"AA", VALID => '1', ERROR => '0'),
       40      => ( DATA => X"BB", VALID => '1', ERROR => '0'),
       41      => ( DATA => X"CC", VALID => '1', ERROR => '0'),
       42      => ( DATA => X"01", VALID => '1', ERROR => '0'), 
       43      => ( DATA => X"23", VALID => '1', ERROR => '0'),
       44      => ( DATA => X"45", VALID => '1', ERROR => '0'),
       45      => ( DATA => X"67", VALID => '1', ERROR => '0'), 
       46      => ( DATA => X"00", VALID => '1', ERROR => '0'),
       47      => ( DATA => X"14", VALID => '1', ERROR => '0'),
       48      => ( DATA => X"15", VALID => '1', ERROR => '0'),
       49      => ( DATA => X"16", VALID => '1', ERROR => '0'),
       50      => ( DATA => X"17", VALID => '1', ERROR => '0'),
       51      => ( DATA => X"18", VALID => '1', ERROR => '0'),
       52      => ( DATA => X"19", VALID => '1', ERROR => '0'),
       53      => ( DATA => X"1A", VALID => '1', ERROR => '0'),
       54      => ( DATA => X"1B", VALID => '1', ERROR => '0'),
       55      => ( DATA => X"1C", VALID => '1', ERROR => '0'),
       56      => ( DATA => X"1D", VALID => '1', ERROR => '0'),
       57      => ( DATA => X"1E", VALID => '1', ERROR => '0'),
       58      => ( DATA => X"1F", VALID => '1', ERROR => '0'),
       59      => ( DATA => X"20", VALID => '1', ERROR => '0'),
       60      => ( DATA => X"21", VALID => '1', ERROR => '0'),
       61      => ( DATA => X"22", VALID => '1', ERROR => '0'),
       62      => ( DATA => X"23", VALID => '1', ERROR => '0'),
       63      => ( DATA => X"24", VALID => '1', ERROR => '0'),
       64      => ( DATA => X"25", VALID => '1', ERROR => '0'),
       65      => ( DATA => X"26", VALID => '1', ERROR => '0'),
       66      => ( DATA => X"27", VALID => '1', ERROR => '0'),
       67      => ( DATA => X"28", VALID => '1', ERROR => '0'),
       68      => ( DATA => X"29", VALID => '1', ERROR => '0'),
       69      => ( DATA => X"2A", VALID => '1', ERROR => '0'),
       70      => ( DATA => X"2B", VALID => '1', ERROR => '0'),
       71      => ( DATA => X"2C", VALID => '1', ERROR => '0'),
       72      => ( DATA => X"2D", VALID => '1', ERROR => '0'),
       73      => ( DATA => X"2E", VALID => '1', ERROR => '0'),
       74      => ( DATA => X"39", VALID => '1', ERROR => '0'),	-- vypocitany crc
       75      => ( DATA => X"5D", VALID => '1', ERROR => '0'),
       76      => ( DATA => X"5B", VALID => '1', ERROR => '0'),
       77      => ( DATA => X"8A", VALID => '1', ERROR => '0'));


BEGIN
 
	-- Instantiate the Unit Under Test (UUT)
   uut: mac_core PORT MAP (
          GTXCLK => GTXCLK,
          PHY_COL => PHY_COL,
          PHY_CS => PHY_CS,
          PHY_TXD => PHY_TXD,
          PHY_TXEN => PHY_TXEN,
          PHY_TXER => PHY_TXER,
          PHY_TXCLK => PHY_TXCLK,
          PHY_GTXCLK => PHY_GTXCLK,
          PHY_RXD => PHY_RXD,
          PHY_RXDV => PHY_RXDV,
          PHY_RXER => PHY_RXER,
          PHY_RXCLK => PHY_RXCLK,
          PHY_RESET => PHY_RESET,
          TX_CLK => TX_CLK,
          TX_DATA => TX_DATA,
          TX_DATA_VLD => TX_DATA_VLD,
          TX_DATA_ACK => TX_DATA_ACK,
          RX_CLK => RX_CLK,
          RX_DATA => RX_DATA,
          RX_DATA_VLD => RX_DATA_VLD,
          RX_DATA_GOOD => RX_DATA_GOOD,
          RX_DATA_BAD => RX_DATA_BAD,
          COLLISION => COLLISION,
          IFG => IFG,
          FULL_DUPLEX => FULL_DUPLEX,
          SPEED1G => SPEED1G,
          RESET => RESET
        );

   -- Clock process definitions
   GTXCLK_process :process
   begin
		GTXCLK <= '0';
		wait for GTXCLK_period/2;
		GTXCLK <= '1';
		wait for GTXCLK_period/2;
   end process;
 
   PHY_TXCLK_process :process
   begin
		PHY_TXCLK <= '0';
		wait for PHY_TXCLK_period/2;
		PHY_TXCLK <= '1';
		wait for PHY_TXCLK_period/2;
   end process;
 
 
   PHY_RXCLK_process :process
   begin
		PHY_RXCLK <= '0';
		wait for PHY_RXCLK_period/2;
		PHY_RXCLK <= '1';
		wait for PHY_RXCLK_period/2;
   end process;
 

   -- Stimulus process
   stim_proc: process 
   begin		
      -- hold reset state for 100 ns.
      wait for 100 ns;	
		wait for GTXCLK_period*10;
		
		--------------------------------------------------------------
		-- simulace prijeti dat pri full duplexu, rychlost 1Gb/s		
		--------------------------------------------------------------
		PHY_RXDV <= '1';
		for i in 0 to 6 loop		-- preamble
			PHY_RXD <= x"55";
			wait for 8 ns;
		end loop;
		PHY_RXD <= x"D5";			-- SFD
		wait for 8 ns;

		for i in  0 to 77 loop
			PHY_RXD <= to_stdlogicvector(ip_frame(i).data);
			PHY_RXDV	<= to_stdUlogic(ip_frame(i).valid);
			wait for 8ns;
		end loop; 	
		
		PHY_RXDV <= '0';
		PHY_RXD <= x"00";
		wait for 100ns;
		--------------------------------------------------------------
		-- simulace odeslani 30B dat pri full duplexu, rychlost 1Gb/s
		--------------------------------------------------------------
		TX_DATA_VLD <= '1';
		TX_DATA <= x"00";
		wait until TX_DATA_ACK = '1';
		wait for 8ns;	-- nasledujici data budou odeslany
		for i in 1 to 30 loop
			TX_DATA <= conv_std_logic_vector(i,8);
			wait for 8ns;
		end loop;
		TX_DATA_VLD <= '0';
		TX_DATA <= x"00";
		-------------------------------------------------------------

      wait;
   end process;

END;
