----------------------------------------------------------------------------------
--									Test bench pro icmp_core	  		  	  		  		  	  --
----------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.STD_LOGIC_1164.ALL;
use work.my_constants.all;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
 
ENTITY icmp_core_tb IS
END icmp_core_tb;
 
ARCHITECTURE behavior OF icmp_core_tb IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT icmp_core
    PORT(
         CLK_RX : IN  std_logic;
         CLK_TX : IN  std_logic;
         DATA_TO_IP : OUT  std_logic_vector(7 downto 0);
         DATA_TO_IP_ACK : IN  std_logic;
         DATA_TO_IP_LEN : OUT  std_logic_vector(10 downto 0);
         DATA_TO_IP_VLD : OUT  std_logic;
         DATA_FROM_IP : IN  std_logic_vector(7 downto 0);
         DATA_FROM_IP_VLD : IN  std_logic;
         DATA_FROM_IP_BAD : IN  std_logic;
         DATA_FROM_IP_GOOD : IN  std_logic;
         SOURCE_ADDRESS : IN  std_logic_vector(31 downto 0);
         DESTINATION_ADDRESS : OUT  std_logic_vector(31 downto 0);
         RESET : IN  std_logic
        );
    END COMPONENT;
    

   --Inputs
   signal CLK_RX : std_logic := '0';
   signal CLK_TX : std_logic := '0';
   signal DATA_TO_IP_ACK : std_logic := '0';
   signal DATA_FROM_IP : std_logic_vector(7 downto 0) := (others => '0');
   signal DATA_FROM_IP_VLD : std_logic := '0';
   signal DATA_FROM_IP_BAD : std_logic := '0';
   signal DATA_FROM_IP_GOOD : std_logic := '0';
   signal SOURCE_ADDRESS : std_logic_vector(31 downto 0) := (others => '0');
   signal RESET : std_logic := '0';

 	--Outputs
   signal DATA_TO_IP : std_logic_vector(7 downto 0);
   signal DATA_TO_IP_LEN : std_logic_vector(10 downto 0);
   signal DATA_TO_IP_VLD : std_logic;
   signal DESTINATION_ADDRESS : std_logic_vector(31 downto 0);

   -- Clock period definitions
   constant CLK_RX_period : time := 8 ns;
   constant CLK_TX_period : time := 8 ns;

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

  ----------------------------------------------------------------------
  -- Frame data 
  ----------------------------------------------------------------------
   constant icmp_frame : frame_typ := (
   -------------
   -- Frame 0
   -------------
    
        0      => ( DATA => X"08", VALID => '1', ERROR => '0'), -- typ request
        1      => ( DATA => X"00", VALID => '1', ERROR => '0'), -- kod
        2      => ( DATA => X"E6", VALID => '1', ERROR => '0'), -- checksum 
        3      => ( DATA => X"FD", VALID => '1', ERROR => '0'), 
        4      => ( DATA => X"0D", VALID => '1', ERROR => '0'), -- ID
        5      => ( DATA => X"00", VALID => '1', ERROR => '0'), 
        6      => ( DATA => X"01", VALID => '1', ERROR => '0'), -- Vlastni data
        7      => ( DATA => X"02", VALID => '1', ERROR => '0'),
        8      => ( DATA => X"03", VALID => '1', ERROR => '0'),
        9      => ( DATA => X"04", VALID => '1', ERROR => '0'),
       10      => ( DATA => X"05", VALID => '1', ERROR => '0'),
       11      => ( DATA => X"06", VALID => '1', ERROR => '0'),
       12      => ( DATA => X"07", VALID => '1', ERROR => '0'), 
       13      => ( DATA => X"08", VALID => '1', ERROR => '0'), 
       14      => ( DATA => X"09", VALID => '1', ERROR => '0'), 
       15      => ( DATA => X"0A", VALID => '1', ERROR => '0'), 
       16      => ( DATA => X"0B", VALID => '1', ERROR => '0'), 
       17      => ( DATA => X"0C", VALID => '1', ERROR => '0'), 
       18      => ( DATA => X"0D", VALID => '1', ERROR => '0'), 
       19      => ( DATA => X"0E", VALID => '1', ERROR => '0'), 
       20      => ( DATA => X"0F", VALID => '1', ERROR => '0'));
 
BEGIN
 
	-- Instantiate the Unit Under Test (UUT)
   uut: icmp_core PORT MAP (
          CLK_RX => CLK_RX,
          CLK_TX => CLK_TX,
          DATA_TO_IP => DATA_TO_IP,
          DATA_TO_IP_ACK => DATA_TO_IP_ACK,
          DATA_TO_IP_LEN => DATA_TO_IP_LEN,
          DATA_TO_IP_VLD => DATA_TO_IP_VLD,
          DATA_FROM_IP => DATA_FROM_IP,
          DATA_FROM_IP_VLD => DATA_FROM_IP_VLD,
          DATA_FROM_IP_BAD => DATA_FROM_IP_BAD,
          DATA_FROM_IP_GOOD => DATA_FROM_IP_GOOD,
          SOURCE_ADDRESS => SOURCE_ADDRESS,
          DESTINATION_ADDRESS => DESTINATION_ADDRESS,
          RESET => RESET
        );

   -- Clock process definitions
   CLK_RX_process :process
   begin
		CLK_RX <= '0';
		wait for CLK_RX_period/2;
		CLK_RX <= '1';
		wait for CLK_RX_period/2;
   end process;
 
   CLK_TX_process :process
   begin
		CLK_TX <= '0';
		wait for CLK_TX_period/2;
		CLK_TX <= '1';
		wait for CLK_TX_period/2;
   end process;
 

   -- Stimulus process
   stim_proc: process
   begin		
      -- hold reset state for 100 ns.
      wait for 100 ns;	
      wait for CLK_RX_period*10;
		wait for 3ns;
		----------------------------------------------------------------
		-- prijeti echo request -----------------------------------------
		SOURCE_ADDRESS <= x"0A1402D6";
		for i in  0 to 8 loop
			DATA_FROM_IP <= to_stdlogicvector(icmp_frame(i).data);
			DATA_FROM_IP_VLD	<= to_stdUlogic(icmp_frame(i).valid);
			wait for 8ns;
		end loop;
		
		DATA_FROM_IP_VLD <= '0';
		DATA_FROM_IP <= x"00";
		wait for 16ns;
		DATA_FROM_IP_GOOD <= '1';
		wait for 8ns;
		DATA_FROM_IP_GOOD <= '0';
		SOURCE_ADDRESS <= x"00000000";
		----------------------------------------------------------------
		
		wait until DATA_TO_IP_VLD = '1';
		wait for 8ns;
		DATA_TO_IP_ACK <= '1';
		wait for 8ns;
		DATA_TO_IP_ACK <= '0';



      wait;
   end process;

END;
