
--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:   20:35:49 10/22/2005
-- Design Name:   ps2_core
-- Module Name:   tb_ps2_core.vhd
-- Project Name:  ps2if
-- Target Device:  
-- Tool versions:  
-- Description:   
-- 
-- VHDL Test Bench Created by ISE for module: ps2_core
--
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
-- Notes: 
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test.  Xilinx recommends 
-- that these types always be used for the top-level I/O of a design in order 
-- to guarantee that the testbench will bind correctly to the post-implementation 
-- simulation model.
--------------------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

ENTITY tb_ps2_core IS
END tb_ps2_core;

ARCHITECTURE behavior OF tb_ps2_core IS 

	--Constants
	constant SYSPERIOD : time := 10 ns;
	constant PS2PERIOD : time := 100 us;

	--Inputs
	SIGNAL rst :  std_logic := '1';
	SIGNAL clk :  std_logic := '0';
	SIGNAL din_vld :  std_logic := '0';
	SIGNAL read_en :  std_logic := '0';
	SIGNAL ps2_clk_rx :  std_logic := '1';
	SIGNAL ps2_data_rx :  std_logic := '1';
	SIGNAL din :  unsigned(7 downto 0) := (others=>'0');

	--Outputs
	SIGNAL dout :  unsigned(7 downto 0);
	SIGNAL dout_reg :  unsigned(7 downto 0);
	SIGNAL tx_empty :  std_logic;
	SIGNAL rx_present :  std_logic;
	SIGNAL rx_err_flag :  std_logic;
	SIGNAL rx_err_par :  std_logic;
	SIGNAL ps2_clk_i :  std_logic := '1';
	SIGNAL ps2_clk_j :  std_logic := '1';
	SIGNAL ps2_clk_tx :  std_logic;
	SIGNAL ps2_data_tx :  std_logic;
	SIGNAl tx_trig : std_logic := '0';

BEGIN

	-- Instantiate the Unit Under Test (UUT)
uut: entity work.ps2_core
	PORT MAP
	(
		rst => rst,
		clk => clk,
		din => din,
		dout => dout,
		tx_empty => tx_empty,
		rx_present => rx_present,
		rx_err_flag => rx_err_flag,
		rx_err_par => rx_err_par,
		din_vld => din_vld,
		read_en => read_en,
		ps2_clk_rx => ps2_clk_rx,
		ps2_data_rx => ps2_data_rx,
		ps2_clk_tx => ps2_clk_tx,
		ps2_data_tx => ps2_data_tx
	);

	ps2_clk_j <= ps2_clk_i after PS2PERIOD/4;
 	tb_pswclk : PROCESS
	BEGIN
		wait until ps2_clk_j'event;  
		ps2_clk_rx <= ps2_clk_j;

--		wait for SYSPERIOD;
--		ps2_clk_rx <= not ps2_clk_j;
--		wait for SYSPERIOD;
--		ps2_clk_rx <= ps2_clk_j;
--		wait for SYSPERIOD;
--		ps2_clk_rx <= not ps2_clk_j;
--		wait for SYSPERIOD;
--		ps2_clk_rx <= ps2_clk_j;
--		wait for SYSPERIOD;
--		ps2_clk_rx <= not ps2_clk_j;
--		wait for SYSPERIOD;
--		ps2_clk_rx <= ps2_clk_j;
--		wait for SYSPERIOD;
--		ps2_clk_rx <= not ps2_clk_j;
--		wait for SYSPERIOD;
--		ps2_clk_rx <= ps2_clk_j;
	END PROCESS;

 	tb_sysclk : PROCESS
	BEGIN
		clk <= not clk;
		wait for SYSPERIOD/2;
	END PROCESS;

	read_en <= rx_present after 1.6 ms;
 	tb_read : PROCESS(clk)
	BEGIN
		if rising_edge(clk) then
			if rx_present = '1' then
				dout_reg <= dout;
			end if;
		end if;

	END PROCESS;

 	tb_write : PROCESS
	BEGIN
		wait until ps2_clk_tx = '0';
		wait for PS2PERIOD;
		wait until ps2_data_tx = '0';
		wait until ps2_clk_tx = '1';
		wait for PS2PERIOD/2;
		tx_trig <= '1';

	END PROCESS;
	
	tb : PROCESS
	BEGIN

		wait for 20*SYSPERIOD;
		rst <= '0';

 	   for iter in 1 to 4 loop
--		wait for 2*PS2PERIOD;
		wait until rising_edge(clk) and ps2_clk_tx = '1';

		--Start bit
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx <= '0';
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		--Data bit 0
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx	<= '1';
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		--Data bit 1
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx	<= '1';
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		--Data bit 2
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx <= '0';
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		--Data bit 3
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx <= '1';
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		--Data bit 4
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx <= '1';
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		--Data bit 5
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx <= '0';
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		--Data bit 6
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx <= '1';
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		--Data bit 7
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx <= '1';
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		--Parity
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx <= '1';
		if iter = 3 then
			ps2_data_rx <= '0';
		end if;	
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		--Stop
		wait for PS2PERIOD/2;
		ps2_clk_i  <= '0';
		ps2_data_rx <= '1';
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;

		end loop;

		ps2_data_rx <= '1';
		ps2_clk_i <= '1';

		wait for PS2PERIOD;
		wait until rising_edge(clk);
 		din     <= x"A5";
		din_vld	<= '1';
		wait until rising_edge(clk);
		din_vld	<= '0';

		wait until tx_trig = '1';
		wait for 2*PS2PERIOD;
		-- Start
		ps2_clk_i <= not ps2_clk_i;
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;
		wait for PS2PERIOD/2;

 	   for iter in 1 to 8 loop
		ps2_clk_i <= not ps2_clk_i;
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;
		wait for PS2PERIOD/2;
		end loop;

		-- Stop
		ps2_clk_i <= not ps2_clk_i;
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;
		wait for PS2PERIOD/2;

		-- Parity
		ps2_clk_i <= not ps2_clk_i;
		wait for PS2PERIOD/2;
		ps2_clk_i <= not ps2_clk_i;
		wait for PS2PERIOD/2;

		ps2_data_rx <= '0';
		ps2_clk_i <= not ps2_clk_i;
		wait for PS2PERIOD/2;

		ps2_clk_i <= not ps2_clk_i;
		wait for PS2PERIOD/2;
		ps2_data_rx <= '1';
		ps2_clk_i <= '1';
		-- Place stimulus here

		wait; -- will wait forever
	END PROCESS;

END;
