--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:    15:10:16 10/22/05
-- Design Name:    
-- Module Name:    ps2if_top - Behavioral
-- Project Name:   
-- Target Device:  
-- Tool versions:  
-- Description:
--
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;

entity ps2if_top is
    Port ( sys_rst_n_in : in std_logic;
           sys_clk_in : in std_logic;
           ps2_mouse_clk : inout std_logic;
           ps2_mouse_data : inout std_logic;
           sys_rx : in std_logic;
           sys_tx : out std_logic;
           led : out std_logic_vector(3 downto 0));
end ps2if_top;

architecture Behavioral of ps2if_top is


	COMPONENT ps2_phy
	PORT(
		rst : IN std_logic;
		clk : IN std_logic;
		tx_clk : IN std_logic;
		tx_data : IN std_logic;
		ps2_clk : INOUT std_logic;
		ps2_data : INOUT std_logic;      
		rx_clk : OUT std_logic;
		rx_data : OUT std_logic
		);
	END COMPONENT;

	COMPONENT ps2_core
	GENERIC(f_sys_clk    : integer);
	PORT(
		rst : IN std_logic;
		clk : IN std_logic;
		ce : IN std_logic;
		d_in : IN std_logic_vector(7 downto 0);
		write_en : IN std_logic;
		read_en : IN std_logic;
		ps2_clk_in : IN std_logic;
		ps2_data_in : IN std_logic;          
		d_out : OUT std_logic_vector(7 downto 0);
		input_rdy : OUT std_logic;
		output_rdy : OUT std_logic;
		ps2_clk_out : OUT std_logic;
		ps2_data_out : OUT std_logic
		);
	END COMPONENT;

	COMPONENT uart_rx
	PORT(
		serial_in : IN std_logic;
		read_buffer : IN std_logic;
		reset_buffer : IN std_logic;
		en_16_x_baud : IN std_logic;
		clk : IN std_logic;          
		data_out : OUT std_logic_vector(7 downto 0);
		buffer_data_present : OUT std_logic;
		buffer_full : OUT std_logic;
		buffer_half_full : OUT std_logic
		);
	END COMPONENT;

	COMPONENT uart_tx
	PORT(
		data_in : IN std_logic_vector(7 downto 0);
		write_buffer : IN std_logic;
		reset_buffer : IN std_logic;
		en_16_x_baud : IN std_logic;
		clk : IN std_logic;          
		serial_out : OUT std_logic;
		buffer_full : OUT std_logic;
		buffer_half_full : OUT std_logic
		);
	END COMPONENT;

constant f_sys_clk_c         : real		:= 100.0;
constant uart_baud_c         : integer	:= 115200;
constant uart_count_c        : integer	:= integer(1.0E6*f_sys_clk_c)/(16*uart_baud_c);

signal rst                   : std_logic;
signal clk_in                : std_logic;
signal clk_out               : std_logic;
signal data_in               : std_logic;
signal data_out              : std_logic;
signal ps2_core_data_out     : std_logic_vector(7 downto 0);
signal ps2_core_data_in      : std_logic_vector(7 downto 0);
signal ps2_core_data_out_rdy : std_logic;
signal ps2_core_data_in_rdy  : std_logic;
signal ps2_core_write_en     : std_logic;
signal uart_en_16_x_baud     : std_logic;
signal uart_tx_i             : std_logic;

begin

	Inst_ps2_phy: ps2_phy
	PORT MAP(
		rst => rst,
		clk => sys_clk_in,
		ps2_clk => ps2_mouse_clk,
		ps2_data => ps2_mouse_data,
		rx_clk => clk_in,
		rx_data => data_in,
		tx_clk => clk_out,
		tx_data => data_out
	);

	Inst_ps2_core: ps2_core 
   GENERIC MAP (
		f_sys_clk => f_sys_clk_c)
	PORT MAP(
		rst => rst,
		clk => sys_clk_in,
		ce => '1',
		d_in => ps2_core_data_in,
		d_out => ps2_core_data_out,
		input_rdy => ps2_core_data_in_rdy,
		output_rdy => ps2_core_data_out_rdy,
		write_en => ps2_core_write_en,
		read_en => '1',
		ps2_clk_in => clk_in,
		ps2_data_in => data_in,
		ps2_clk_out => clk_out,
		ps2_data_out => data_out
	);

	Inst_uart_rx: uart_rx 
	PORT MAP(
		serial_in => sys_rx,
		data_out => ps2_core_data_in,
		read_buffer => ps2_core_data_in_rdy,
		reset_buffer => rst,
		en_16_x_baud => uart_en_16_x_baud,
		buffer_data_present => ps2_core_write_en,
		buffer_full => open,
		buffer_half_full => open,
		clk => sys_clk_in
	);

	Inst_uart_tx: uart_tx 
	PORT MAP(
		data_in => ps2_core_data_out,
		write_buffer => ps2_core_data_out_rdy,
		reset_buffer => rst,
		en_16_x_baud => uart_en_16_x_baud,
		serial_out => uart_tx_i,
		buffer_full => open,
		buffer_half_full => open,
		clk => sys_clk_in
	);


  baud_timer: process(sys_clk_in)
  variable baud_count : integer range 0 to uart_count_c-1;
  begin
    if sys_clk_in'event and sys_clk_in='1' then
      if baud_count=uart_count_c-1 then
         baud_count := 0;
         uart_en_16_x_baud <= '1';
       else
         baud_count := baud_count + 1;
         uart_en_16_x_baud <= '0';
      end if;
    end if;
  end process baud_timer;

rst           <= not sys_rst_n_in;
sys_tx        <= uart_tx_i;

led(0)        <= not clk_in;
led(1)        <= not data_in;
led(2)        <= not clk_out;
led(3)        <= not data_out;
end Behavioral;
