----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    13:30:41 03/25/2016 
-- Design Name: 
-- Module Name:    phy_io - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

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


entity phy_io is
	port (
		PhyRxClk						: in  std_logic;
		PhyRxDv						: in  std_logic;
		PhyRxd						: in  std_logic_vector(3 downto 0);
		PhyRxEr						: in  std_logic;
		rx_clk						: out std_logic;
		rx_data_valid				: out std_logic;
		rx_data						: out std_logic_vector(3 downto 0);
		rx_data_error				: out std_logic;
		PhyTxClk						: in  std_logic;
		PhyTxEn						: out std_logic;
      PhyTxd						: out std_logic_vector(3 downto 0);
		PhyTxEr						: out std_logic;
		tx_clk						: out std_logic;
		tx_data_enable				: in  std_logic;
		tx_data						: in  std_logic_vector(3 downto 0)
	);
end phy_io;


architecture Behavioral of phy_io is

	signal phy_rx_clk_pin						: std_logic;
	signal phy_rx_clk_bufio						: std_logic;
	signal rx_clk_i								: std_logic;
	
	signal phy_rx_dv_pin							: std_logic;
	signal phy_rxd_pin							: std_logic_vector(3 downto 0);
	signal phy_rxer_pin							: std_logic;
	signal phy_rx_dv_delay						: std_logic;
	signal phy_rxd_delay							: std_logic_vector(3 downto 0);
	signal phy_rxer_delay						: std_logic;
	
	signal rx_data_valid_i						: std_logic;
	signal rx_data_i								: std_logic_vector(3 downto 0);
	signal rx_data_error_i						: std_logic;
	
	signal phy_tx_clk_pin						: std_logic;
	signal phy_tx_clk_delay						: std_logic;
	signal tx_clk_i								: std_logic;
	
	signal phy_tx_en_pin							: std_logic;
	signal phy_txd_pin							: std_logic_vector(3 downto 0);
	
	signal phy_tx_en_i							: std_logic := '0';
	signal phy_txd_i								: std_logic_vector(3 downto 0) := (others => '0');

begin
	PhyTxEr <= '0';		-- DO NOT LEAVE FLOATING


   PhyRxClk_IBUFG : IBUFG
   generic map (
      IBUF_LOW_PWR => FALSE,
		IOSTANDARD => "LVCMOS33"
	)
   port map (
      O => phy_rx_clk_pin,
      I => PhyRxClk
   );
	
	phy_rx_clk_bufio_BUFIO2 : BUFIO2
	port map  (
		DIVCLK			=> open,
		I					=> phy_rx_clk_pin,
		IOCLK				=> phy_rx_clk_bufio,
		SERDESSTROBE	=> open
	);
	
	rx_clk <= rx_clk_i;
	
	phy_rx_clk_BUFG : BUFG
	port map (
		O => rx_clk_i,
		I => phy_rx_clk_pin		-- phy_rx_clk_delay
	);
	
	
	phy_rx_dv_IBUF : IBUF
	generic map (
		IBUF_LOW_PWR => FALSE,
		IOSTANDARD => "LVCMOS33"
	)
	port map (
		O => phy_rx_dv_pin,
		I => PhyRxDv
	);
	
	phy_rx_dv_IODELAY2 : IODELAY2
	generic map (
		IDELAY_TYPE    => "FIXED",
		DELAY_SRC      => "IDATAIN"
   )
   port map (
		BUSY		=> open,
		DATAOUT	=> phy_rx_dv_delay,
		DATAOUT2	=> open,
		DOUT		=> open,
		TOUT		=> open,
		CAL		=> '0',
		CE			=> '0',
		CLK		=> '0',
		IDATAIN	=> phy_rx_dv_pin,
		INC		=> '0',
		IOCLK0	=> '0',
		IOCLK1	=> '0',
		ODATAIN	=> '0',
		RST		=> '0',
		T			=> '1'
	);
	
	
	phy_rxd_0_IBUF : IBUF
	generic map (
		IBUF_LOW_PWR => FALSE,
		IOSTANDARD => "LVCMOS33"
	)
	port map (
		O => phy_rxd_pin(0),
		I => PhyRxd(0)
	);
	
	phy_rxd_0_IODELAY2 : IODELAY2
	generic map (
		IDELAY_TYPE    => "FIXED",
		DELAY_SRC      => "IDATAIN"
   )
   port map (
		BUSY		=> open,
		DATAOUT	=> phy_rxd_delay(0),
		DATAOUT2	=> open,
		DOUT		=> open,
		TOUT		=> open,
		CAL		=> '0',
		CE			=> '0',
		CLK		=> '0',
		IDATAIN	=> phy_rxd_pin(0),
		INC		=> '0',
		IOCLK0	=> '0',
		IOCLK1	=> '0',
		ODATAIN	=> '0',
		RST		=> '0',
		T			=> '1'
	);
	
	
	phy_rxd_1_IBUF : IBUF
	generic map (
		IBUF_LOW_PWR => FALSE,
		IOSTANDARD => "LVCMOS33"
	)
	port map (
		O => phy_rxd_pin(1),
		I => PhyRxd(1)
	);
	
	phy_rxd_1_IODELAY2 : IODELAY2
	generic map (
		IDELAY_TYPE    => "FIXED",
		DELAY_SRC      => "IDATAIN"
   )
   port map (
		BUSY		=> open,
		DATAOUT	=> phy_rxd_delay(1),
		DATAOUT2	=> open,
		DOUT		=> open,
		TOUT		=> open,
		CAL		=> '0',
		CE			=> '0',
		CLK		=> '0',
		IDATAIN	=> phy_rxd_pin(1),
		INC		=> '0',
		IOCLK0	=> '0',
		IOCLK1	=> '0',
		ODATAIN	=> '0',
		RST		=> '0',
		T			=> '1'
	);
	
	
	phy_rxd_2_IBUF : IBUF
	generic map (
		IBUF_LOW_PWR => FALSE,
		IOSTANDARD => "LVCMOS33"
	)
	port map (
		O => phy_rxd_pin(2),
		I => PhyRxd(2)
	);
	
	phy_rxd_2_IODELAY2 : IODELAY2
	generic map (
		IDELAY_TYPE    => "FIXED",
		DELAY_SRC      => "IDATAIN"
   )
   port map (
		BUSY		=> open,
		DATAOUT	=> phy_rxd_delay(2),
		DATAOUT2	=> open,
		DOUT		=> open,
		TOUT		=> open,
		CAL		=> '0',
		CE			=> '0',
		CLK		=> '0',
		IDATAIN	=> phy_rxd_pin(2),
		INC		=> '0',
		IOCLK0	=> '0',
		IOCLK1	=> '0',
		ODATAIN	=> '0',
		RST		=> '0',
		T			=> '1'
	);
	
	
	phy_rxd_3_IBUF : IBUF
	generic map (
		IBUF_LOW_PWR => FALSE,
		IOSTANDARD => "LVCMOS33"
	)
	port map (
		O => phy_rxd_pin(3),
		I => PhyRxd(3)
	);
	
	phy_rxd_3_IODELAY2 : IODELAY2
	generic map (
		IDELAY_TYPE    => "FIXED",
		DELAY_SRC      => "IDATAIN"
   )
   port map (
		BUSY		=> open,
		DATAOUT	=> phy_rxd_delay(3),
		DATAOUT2	=> open,
		DOUT		=> open,
		TOUT		=> open,
		CAL		=> '0',
		CE			=> '0',
		CLK		=> '0',
		IDATAIN	=> phy_rxd_pin(3),
		INC		=> '0',
		IOCLK0	=> '0',
		IOCLK1	=> '0',
		ODATAIN	=> '0',
		RST		=> '0',
		T			=> '1'
	);
	
	
	phy_rxd_error_IBUF : IBUF
	generic map (
		IBUF_LOW_PWR => FALSE,
		IOSTANDARD => "LVCMOS33"
	)
	port map (
		O => phy_rxer_pin,
		I => PhyRxEr
	);
	
	phy_rxd_error_IODELAY2 : IODELAY2
	generic map (
		IDELAY_TYPE    => "FIXED",
		DELAY_SRC      => "IDATAIN"
   )
   port map (
		BUSY		=> open,
		DATAOUT	=> phy_rxer_delay,
		DATAOUT2	=> open,
		DOUT		=> open,
		TOUT		=> open,
		CAL		=> '0',
		CE			=> '0',
		CLK		=> '0',
		IDATAIN	=> phy_rxer_pin,
		INC		=> '0',
		IOCLK0	=> '0',
		IOCLK1	=> '0',
		ODATAIN	=> '0',
		RST		=> '0',
		T			=> '1'
	);
	
	
	
	rx_data_valid <= rx_data_valid_i;
	rx_data <= rx_data_i;
	rx_data_error <= rx_data_error_i;
	
	
	rx_iob_proc: process (rx_clk_i)
	begin
		if rising_edge(rx_clk_i) then
			rx_data_valid_i <= phy_rx_dv_delay;
			rx_data_i <= phy_rxd_delay;
			rx_data_error_i <= phy_rxer_delay;
		end if;
	end process rx_iob_proc;

	
   PhyTxClk_IBUFG : IBUFG
   generic map (
      IBUF_LOW_PWR => FALSE
	)
   port map (
      O => phy_tx_clk_pin,
      I => PhyTxClk
   );
	
	tx_clk <= tx_clk_i;
	
	phy_tx_clk_BUFG : BUFG
	port map (
		O => tx_clk_i,
		I => phy_tx_clk_pin	--phy_tx_clk_delay
	);
	
	
	PhyTxEn_OBUF : OBUF
	generic map (
		DRIVE => 12,
		IOSTANDARD => "LVCMOS33",
		SLEW => "FAST"
	)
	port map (
		O => PhyTxEn,
		I => phy_tx_en_pin
   );
	
	
	PhyTxd_0_OBUF : OBUF
	generic map (
		DRIVE => 12,
		IOSTANDARD => "LVCMOS33",
		SLEW => "FAST"
	)
	port map (
		O => PhyTxd(0),
		I => phy_txd_pin(0)
   );
	
	PhyTxd_1_OBUF : OBUF
	generic map (
		DRIVE => 12,
		IOSTANDARD => "LVCMOS33",
		SLEW => "FAST"
	)
	port map (
		O => PhyTxd(1),
		I => phy_txd_pin(1)
   );
	
	PhyTxd_2_OBUF : OBUF
	generic map (
		DRIVE => 12,
		IOSTANDARD => "LVCMOS33",
		SLEW => "FAST"
	)
	port map (
		O => PhyTxd(2),
		I => phy_txd_pin(2)
   );
	
	PhyTxd_3_OBUF : OBUF
	generic map (
		DRIVE => 12,
		IOSTANDARD => "LVCMOS33",
		SLEW => "FAST"
	)
	port map (
		O => PhyTxd(3),
		I => phy_txd_pin(3)
   );
	
	
	tx_iob_proc : process (tx_clk_i)
	begin
		if rising_edge(tx_clk_i) then
			phy_tx_en_pin <= tx_data_enable;
			phy_txd_pin <= tx_data;
		end if;
	end process tx_iob_proc;

end Behavioral;

