-------------------------------------------------------------
--	Filename:  USB20ULPI.VHD
-- Authors: 
--		Alain Zarembowitch / MSS, 
--	Version: 1
--	Date last modified: 8-20-10
-- Inheritance: 	none
--
-- description:  USB 2.0 Serial Interface Engine (SIE) implementation
-- 14-pin ULPI reduced-pinout interface with USB 2.0 PHY IC
-- Support for HS/FS modes only.
-- Uses one global buffer for USB_CLK60G
-- 60 MHz clock, 8-bit wide data transfer.
--
-- Implementation: this is a ULPI wrapper around the UMTI code.
--  Low-power mode is not implemented (because it would stop the reference 60 MHz clock)
----------------------------------------------------------------------------------
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 USB20ULPI is
    port ( 
			--// Clocks Resets
			SYNC_RESET: in std_logic;
				-- reset, synchronous with 60 MHz clock
			USB_CLK60G: in std_logic;	
				-- reference clock. 60 MHz. Regenerated by PLL.
				-- 0deg offet w.r.t. the USB PHY (CLK0UT)clock 
				-- Generally not used outside of this component.
				-- Global clock (PLL and BUFG MUST be instantiated outside).
			CLK_P: in std_logic;
				-- Main processing or I/O clock used outside of this component.
				-- All application interface signals are synchronous with CLK_p
				-- Key assumption: CLK_P is slightly faster than USB_CLK60G/2.
				-- Other key assumption: CLK_P < 4 * CLK60G

	 
			--// USB PHY interface: ULPI 12-pin interface 
			-- Direct connection between the USB20ULPI component and the USB PHY IC
			-- such as SMSC GT3300.
			-- Synchronous with USB_CLK60G clock (from PHY through BUFG). 
			-- See ULPI.ORG for specifications
			USB_ULPI_DATA: inout std_logic_vector(7 downto 0);
			USB_ULPI_STP: out std_logic;  -- high after power-on reset
			USB_ULPI_NXT: in std_logic;
				-- NXT is time critical
			USB_ULPI_DIR: in std_logic;
			
			
			--// Data Stream 1
			-- Synchronous with CLK_P clock
			DATA1_OUT: out std_logic_vector(7 downto 0);
			DATA1_OUT_SAMPLE_CLK: out std_logic;
				-- read DATA1_OUT at rising edge of CLK_P when DATA1_OUT_SAMPLE_CLK = '1'
				-- The latency from a DATA1_OUT_SAMPLE_CLK_REQ input pulse to the DATA1_OUT_SAMPLE_CLK
				-- output pulse is 2 CLK_P.
			DATA1_OUT_BUFFER_EMPTY: out std_logic;
			DATA1_OUT_SAMPLE_CLK_REQ: in std_logic;	
				-- requests data. If no data is available in the buffer, the
				-- DATA1_OUT_SAMPLE_CLK will stay low.
				-- (flow control)
			
			DATA1_IN: in std_logic_vector(7 downto 0);
			DATA1_IN_SAMPLE_CLK: in std_logic;
				-- read DATA1_IN at rising edge of CLK_P when DATA1_IN_SAMPLE_CLK = '1'
			DATA1_IN_SAMPLE_CLK_REQ: out std_logic;
				-- requests data when the input elastic buffer is less than half full. 
				-- (flow control)

			--// Data Stream 2
			-- Synchronous with CLK_P clock
			DATA2_OUT: out std_logic_vector(7 downto 0);
			DATA2_OUT_SAMPLE_CLK: out std_logic;
				-- read DATA2_OUT at rising edge of CLK_P when DATA2_OUT_SAMPLE_CLK = '1'
			DATA2_OUT_BUFFER_EMPTY: out std_logic;
			DATA2_OUT_SAMPLE_CLK_REQ: in std_logic;	
				-- requests data. If no data is available in the buffer, the
				-- DATA2_OUT_SAMPLE_CLK will stay low.
				-- (flow control)
			
			DATA2_IN: in std_logic_vector(7 downto 0);
			DATA2_IN_SAMPLE_CLK: in std_logic;
				-- read DATA2_IN at rising edge of CLK_P when DATA2_IN_SAMPLE_CLK = '1'
			DATA2_IN_SAMPLE_CLK_REQ: out std_logic;
				-- requests data when the input elastic buffer is less than half full. 
				-- (flow control)


			--// Test Points
			PHY_VENDOR_ID: out std_logic_vector(7 downto 0);
				-- hardware check vendor ID (should be x24). Useful for post-production test.
			CS1: out std_logic_vector(7 downto 0);
			CS1_CLK: out std_logic;
			CS2: out std_logic_vector(7 downto 0);
			CS2_CLK: out std_logic;
			CS3: out std_logic_vector(7 downto 0);
			CS3_CLK: out std_logic;
			T1: out std_logic;
			T1_CLK: out std_logic;
			T2: out std_logic;
			T2_CLK: out std_logic;
			USB_TP: out std_logic_vector(20 downto 1)
			
			);
end entity;

architecture Behavioral of USB20ULPI is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------
	COMPONENT USB20
	PORT(
		ASYNC_RESET : IN std_logic;
		USB_CLK60G : IN std_logic;
		CLK_P : IN std_logic;
		USB_LINESTATE : IN std_logic_vector(1 downto 0);
		USB_TXREADY : IN std_logic;
		USB_RXVALID : IN std_logic;
		USB_RXACTIVE : IN std_logic;
		USB_RXERROR : IN std_logic;
		USB_DATA_IN : IN std_logic_vector(7 downto 0);
		USB_VBUS_SENSE : IN std_logic;
		DATA1_OUT_SAMPLE_CLK_REQ : IN std_logic;
		DATA1_IN : IN std_logic_vector(7 downto 0);
		DATA1_IN_SAMPLE_CLK : IN std_logic;
		DATA2_OUT_SAMPLE_CLK_REQ : IN std_logic;
		DATA2_IN : IN std_logic_vector(7 downto 0);
		DATA2_IN_SAMPLE_CLK : IN std_logic;          
		USB_RESET : OUT std_logic;
		USB_DATABUS16_8 : OUT std_logic;
		USB_SUSPENDN : OUT std_logic;
		USB_XCVRSELECT : OUT std_logic;
		USB_TERMSELECT : OUT std_logic;
		USB_OPMODE : OUT std_logic_vector(1 downto 0);
		USB_TXVALID : OUT std_logic;
		USB_DATA_OUT : OUT std_logic_vector(7 downto 0);
		DATA1_OUT : OUT std_logic_vector(7 downto 0);
		DATA1_OUT_SAMPLE_CLK : OUT std_logic;
		DATA1_OUT_BUFFER_EMPTY : OUT std_logic;
		DATA1_IN_SAMPLE_CLK_REQ : OUT std_logic;
		DATA2_OUT : OUT std_logic_vector(7 downto 0);
		DATA2_OUT_SAMPLE_CLK : OUT std_logic;
		DATA2_OUT_BUFFER_EMPTY : OUT std_logic;
		DATA2_IN_SAMPLE_CLK_REQ : OUT std_logic;
		USB_TP : OUT std_logic_vector(10 downto 1)
		);
	END COMPONENT;
--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------
-- Suffix _D indicates a one clock delay

--// ULPI Link state machine (low-level transactions)
signal STATE: integer range 0 to 12;
signal STATE_D: integer range 0 to 12;
signal TO_CNTR: integer range 0 to 15;
constant TO_VAL: integer := 10;
signal USB_ULPI_STP_LOCAL: std_logic;
signal TRIGGER_REGISTER_WRITE: std_logic;
signal TRIGGER_REGISTER_WRITE_ACK: std_logic;
signal TRIGGER_REGISTER_READ: std_logic;
signal TRIGGER_REGISTER_READ_ACK: std_logic;
signal TRIGGER_EXIT_LOWPOWER: std_logic;
signal REGISTER_WRITE_DATA: std_logic_vector(7 downto 0);
signal REGISTER_READ_DATA: std_logic_vector(7 downto 0);
signal REGISTER_READ_SAMPLE_CLK: std_logic;
signal RXD_CMD: std_logic_vector(7 downto 0);
signal TXD_CMD: std_logic_vector(7 downto 0);
signal USB_ULPI_DATA_LOCAL: std_logic_vector(7 downto 0);
signal USB_ULPI_DATA_IN: std_logic_vector(7 downto 0);
signal USB_ULPI_DATA_OUT: std_logic_vector(7 downto 0);
signal USB_ULPI_DIR_D: std_logic;
signal USB_RXVALID: std_logic;
signal USB_RXVALID_D: std_logic;
signal USB_DATA_IN: std_logic_vector(7 downto 0);
signal USB_TXVALID: std_logic;
signal USB_TXVALID_D: std_logic;
signal USB_TXREADY: std_logic;
signal USB_DATA_OUT: std_logic_vector(7 downto 0);
signal USB_LINESTATE : std_logic_vector(1 downto 0);
signal USB_RXACTIVE : std_logic;
signal USB_RXERROR : std_logic;
signal USB_VBUS_SENSE : std_logic;
signal USB_ID: std_logic;
signal USB_HOSTDISCONNECT: std_logic;
signal USB_RESET: std_logic;
signal USB_SUSPENDN: std_logic;
signal USB_OPMODE: std_logic_vector(1 downto 0);
signal USB_TERMSELECT: std_logic;
signal USB_XCVRSELECT: std_logic_vector(1 downto 0);
signal CTRL: std_logic_vector(7 downto 0);
signal CTRL_D: std_logic_vector(7 downto 0);
signal RXD_CMD_SAMPLE_CLK: std_logic;
signal USB_TP_LOCAL: std_logic_vector(10 downto 1);
signal REGVAL: std_logic_vector(7 downto 0);
signal RX_MESSAGE_TOGGLE: std_logic;

--// ULPI Link state machine (higher-level transactions)
signal STATE2: integer range 0 to 5;


--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin

--//---------------------------------------------------
--// ULPI Link state machine for low-level transactions
--//---------------------------------------------------
-- 0 = Link is idle
-- 1-3 = ULPI register write transaction
-- 5-6 = ULPI register read transaction
-- 9 = PHY initiates a data read transaction
-- 12 = Link initiates a data write transaction

-- oversize timeout counters... Timeout is just a safety to guarantee that
-- we do not get stuck in any non-idle state due to external conditions beyond our control.
STATE_001: process(USB_CLK60G)
begin
	if rising_edge(USB_CLK60G) then
		STATE_D <= STATE;
		USB_TXVALID_D <= USB_TXVALID;
		
		if(SYNC_RESET = '1') then
			STATE <= 0;
			TO_CNTR <= 0;
			CTRL_D <= "01000001";		-- default USB3300 PHY configuration
		elsif(STATE = 0) then
			-- Idle state
			if (USB_ULPI_DIR = '1') then
				-- PHY initiates a ULPI receive transaction
				-- In the ULPI protocol, a received packet has the priority
				STATE <= 9;
				TO_CNTR <= 0;
			else
				if (CTRL /= CTRL_D) then
					-- detected changes in XcvrSelect (speed), termselect, OpMode, Reset
					-- Function Control
					STATE <= 1;
					TO_CNTR <= TO_VAL; -- time-out counter
					CTRL_D <= CTRL and x"5F";  -- remember the previous state (except for self-clearing reset)
				elsif (TRIGGER_REGISTER_WRITE = '1') then
					-- need to overwrite the USB3300 default DP/DM pulldown (disabled for peripheral)
					STATE <= 1;
					TO_CNTR <= TO_VAL; -- time-out counter
				elsif (TRIGGER_REGISTER_READ = '1') then
					-- Start register read transaction. wait until USB_ULPI_DIR = 0
					STATE <= 5;
					TO_CNTR <= TO_VAL; -- time-out counter
				elsif (USB_TXVALID_D = '1') then
					-- Link initiates a data write transaction
					-- Delay 1 CLK at start to make sure it does not arrive before a change in CTRL !!!!!
					STATE <= 12;
					-- no timeout here (could be a long message) TBC
				end if;
			end if;
		elsif(STATE_D = 0) and (USB_ULPI_DIR = '1') then
			-- race condition. The Link started a transaction at the same time as 
			-- the PHY started a ULPI receive transaction.PHY has right of way
			STATE <= 9;
			TO_CNTR <= 0;
		elsif(STATE = 1) and (USB_ULPI_NXT = '1') then
				-- Link to drive the register data on the bus
				STATE <= 2;
		elsif(STATE = 1) and (TO_CNTR = 0) then
				-- timeout waiting for NXT. return to idle
				STATE <= 0;
		elsif(STATE = 2) then
			STATE <= 3;
		elsif(STATE = 3) then
			-- completed the ULPI register write transaction. return to idle
			STATE <= 0;
		elsif(STATE = 5) and (USB_ULPI_DIR = '1') then
				-- about to receive Reg data
				STATE <= 6;
		elsif(STATE = 5) and (TO_CNTR = 0) then
				-- abnormal case: timeout waiting for DIR. return to idle
				STATE <= 0;
		elsif(STATE = 6) then
				-- read reg data. return to idle.
				-- completed the ULPI register read transaction. return to idle.
				STATE <= 0;
		elsif(STATE = 9) and (USB_ULPI_DIR = '0') then
			-- PHY terminates the ULPI receive transaction. return to idle.
			STATE <= 0;
		elsif(STATE = 12) and (USB_TXVALID = '0') and (USB_ULPI_NXT = '1') then
			-- packet is complete. back to idle.
			-- Note: link cannot assert STP with NXT de-asserted since the PHY is expecting to fetch another byte from the link in this state 
			STATE <= 0;
		else
			-- timeout counter
			if(TO_CNTR /= 1) then
				TO_CNTR <= TO_CNTR - 1;
			end if;
		end if;
	end if;
end process;

TRIGGER_REGISTER_READ_ACK <= '1' when (STATE = 5) and (USB_ULPI_DIR = '0') else '0';
TRIGGER_REGISTER_WRITE_ACK <= '1' when (STATE = 0) and (USB_ULPI_DIR = '0') and (CTRL = CTRL_D) 
	and (TRIGGER_REGISTER_WRITE = '1') else '0';

--// synchronous mode, write to PHY
-- reclock USB_DATA_OUT from SIE because of critical timing
WRITE_PHY_001: process(USB_CLK60G)
begin
	if rising_edge(USB_CLK60G) then
	
		if(SYNC_RESET = '1') then
			USB_ULPI_DATA_LOCAL <= x"00";	-- idle. no read/write with PHY
		elsif(STATE = 0) then 
			USB_ULPI_STP_LOCAL <= '0';  -- Link is now ready
			if (USB_ULPI_DIR = '0') then
				if (CTRL /= CTRL_D) then
					-- detected changes in XcvrSelect (speed), termselect, OpMode, Reset
					USB_ULPI_DATA_LOCAL <= "10" & "000100"; -- register write, address 04h;
					REGVAL <= CTRL;
				elsif (TRIGGER_REGISTER_WRITE = '1') then
					-- write to OTG control register
					-- Peripheral settings: DPPULLDOWN = 0, DMPULLDOWN = 0
					USB_ULPI_DATA_LOCAL <= "10" & "001010"; -- register write, address 0Ah;
					REGVAL <= x"00";	
				elsif (TRIGGER_REGISTER_READ = '1') then
					-- starts register read transaction
					USB_ULPI_DATA_LOCAL <= TXD_CMD;
				elsif (USB_TXVALID_D = '1') then
					-- Link initiates a data write transaction
					USB_ULPI_DATA_LOCAL <= "0100" & USB_DATA_OUT(3 downto 0);  
						-- TX CMD: USB tx + PID (PID is in the lower half, PID# in the upper half of USB_DATA_OUT)
				else
					-- idle. nothing going on. actively drive data out with idle (00h)
					USB_ULPI_DATA_LOCAL <= (others => '0');
				end if;
			end if;
		elsif(STATE_D = 0) and (USB_ULPI_DIR = '1') then
			-- race condition. The Link started a transaction at the same time as 
			-- the PHY started a ULPI receive transaction.PHY has right of way
			-- return to idle TXD_CMD (00h). nothing going on. 
			USB_ULPI_DATA_LOCAL <= (others => '0');
		elsif(STATE = 1) and (USB_ULPI_NXT = '1') then
			-- control register value
			USB_ULPI_DATA_LOCAL <= REGVAL;
		elsif(STATE = 2) then
			-- send idle, or else the PHY may decode the value as a ULPI command.
			USB_ULPI_DATA_LOCAL <= (others => '0');  
			USB_ULPI_STP_LOCAL <= '1';
		elsif(STATE = 3) then
			-- completed the ULPI register write transaction. return to idle
			USB_ULPI_STP_LOCAL <= '0';
		elsif(STATE = 5) and (USB_ULPI_NXT = '1') then
			-- Link ready to accept the data transfer. set output to idle now.
			USB_ULPI_DATA_LOCAL <= (others => '0');  
		elsif(STATE = 12) and (USB_TXVALID = '1') and (USB_ULPI_NXT = '1') then
			USB_ULPI_DATA_LOCAL <= USB_DATA_OUT;  
		elsif(STATE = 12) and (USB_TXVALID = '0') and (USB_ULPI_NXT = '1') then
			-- ULPI transmit packet is complete. return to idle
			USB_ULPI_DATA_LOCAL <= (others => '0');  
			USB_ULPI_STP_LOCAL <= '1';
		end if;
	end if;
end process;
USB_ULPI_DATA_OUT <= USB_ULPI_DATA_LOCAL;

-- Ask for the next tx data byte from the SIE. 
USB_TXREADY <= '1' when (USB_ULPI_DIR = '0') and (STATE = 12) and (STATE_D = 0) else  -- read 1 byte ahead at the start (when no tx/rx conflict)
					USB_ULPI_NXT when (USB_ULPI_DIR = '0') and (STATE = 12) and (USB_TXVALID = '1') else
					'0';


-- XST has problems with tristating with 'Z'. Use the Xilinx primitive instead
-- Time critical. Set to "FAST" instead of the default "SLOW"
USB_ULPI_DATA_GEN: for I in 0 to 7 generate
   IOBUF_inst : IOBUF
   generic map (
      DRIVE => 12,
      IOSTANDARD => "DEFAULT",
      SLEW => "FAST")
   port map (
      O => USB_ULPI_DATA_IN(I),     -- Buffer output
      IO => USB_ULPI_DATA(I),   -- Buffer inout port (connect directly to top-level port)
      I => USB_ULPI_DATA_OUT(I),     -- Buffer input
      T => USB_ULPI_DIR      -- 3-state enable input, high=input, low=output 
   );
end generate;
						
OBUF_inst : OBUF
generic map (
	DRIVE => 12,
	IOSTANDARD => "DEFAULT",
	SLEW => "FAST")
port map (
	O => USB_ULPI_STP,     -- Buffer output (connect directly to top-level port)
	I => USB_ULPI_STP_LOCAL      -- Buffer input 
);

--// synchronous mode, read from PHY
READ_PHY_001: process(USB_CLK60G)
begin
	if rising_edge(USB_CLK60G) then
		if(STATE = 6) then
			-- read register data
			REGISTER_READ_DATA <= USB_ULPI_DATA_IN;
			REGISTER_READ_SAMPLE_CLK <= '1';
		else
			REGISTER_READ_SAMPLE_CLK <= '0';
		end if;
	end if;
end process;

READ_PHY_002: process(USB_CLK60G)
begin
	if rising_edge(USB_CLK60G) then
		if(STATE = 9) and (USB_ULPI_DIR = '1') and (USB_ULPI_NXT = '0') then
			-- RXD CMD. The link must be able to accept any number of continuous back to back RX_CMDs
			RXD_CMD <= USB_ULPI_DATA_IN;
			RXD_CMD_SAMPLE_CLK <= '1';
			USB_RXVALID <= '0';
		elsif(STATE = 9) and (USB_ULPI_DIR = '1') and (USB_ULPI_NXT = '1') then
			-- PID, DATA
			USB_DATA_IN <= USB_ULPI_DATA_IN;
			USB_RXVALID <= '1';
			RXD_CMD_SAMPLE_CLK <= '0';
		else
			USB_RXVALID <= '0';
			RXD_CMD_SAMPLE_CLK <= '0';
		end if;
	end if;
end process;

-- toggle at end of message (debugging)
DEBUG_001: process (USB_CLK60G)
begin
	if rising_edge(USB_CLK60G) then
		USB_RXVALID_D <= USB_RXVALID;
		if(USB_RXVALID = '0') and (USB_RXVALID_D = '1') then
			RX_MESSAGE_TOGGLE <= not RX_MESSAGE_TOGGLE;
		end if;
	end if;
end process;
		

--// decode RXD_CMD
USB_LINESTATE <= RXD_CMD(1 downto 0);
USB_VBUS_SENSE <= RXD_CMD(3);  -- RXD_CMD(3:2) = 10 or 11
USB_RXERROR <= '1' when (RXD_CMD(5 downto 4) = "11") else '0';
USB_HOSTDISCONNECT <= '1' when (RXD_CMD(5 downto 4) = "10") else '0';  
	-- must be ignored in peripheral mode.
USB_ID <= RXD_CMD(6);  -- A device (0), B device (1)

--// RXACTIVE logic
RXACTIVE_GEN_001: process(USB_CLK60G)
begin
	if rising_edge(USB_CLK60G) then
		USB_ULPI_DIR_D <= USB_ULPI_DIR;
		
		if(USB_ULPI_DIR = '1') and (USB_ULPI_DIR_D = '0') and (USB_ULPI_NXT = '1') then
			-- if DIR was previously low, the PHY will assert both DIR and NXT so that the link knows immediately
			-- that this is a USB receive packet
			USB_RXACTIVE <= '1';
		elsif(STATE = 9) and (USB_ULPI_DIR = '1') and (USB_ULPI_NXT = '0') then
			-- RXD CMD. RXACTIVE in bit 4
			USB_RXACTIVE <= USB_ULPI_DATA_IN(4);
		elsif(USB_ULPI_DIR = '0') then
			USB_RXACTIVE <= '0';
		end if;
	end if;
end process;
	

-- 
--//---------------------------------------------------
--// ULPI Link (higher-level) state machine
--//---------------------------------------------------
CTRL <= "0" & USB_SUSPENDN & USB_RESET & USB_OPMODE & USB_TERMSELECT & USB_XCVRSELECT;

STATE2_GEN: process(USB_CLK60G)
begin
	if rising_edge(USB_CLK60G) then

		if(SYNC_RESET = '1') then
			-- soft reset
			STATE2 <= 0;
			TXD_CMD <= x"00";	-- idle
			TRIGGER_REGISTER_READ <= '0';
			TRIGGER_REGISTER_WRITE <= '0';
		elsif(STATE2 = 0) then
			-- for test purposes, read SMSC vendor ID low (should be x24)
			TXD_CMD <= "11" & "000000"; -- register read, address 00h
			TRIGGER_REGISTER_READ <= '1';
			STATE2 <= STATE2 + 1;
		elsif(STATE2 = 1) and (TRIGGER_REGISTER_READ_ACK = '1') then
			TXD_CMD <= x"00";	-- idle
			TRIGGER_REGISTER_READ <= '0';
			STATE2 <= STATE2 + 1;
		elsif(STATE2 = 2) and (REGISTER_READ_SAMPLE_CLK = '1') then
			-- received result. move onto next state2.
			-- register value read into REGISTER_READ_DATA  (Vendor ID low = x24)
			STATE2 <= STATE2 + 1;
			-- save the PHY vendor ID 
			PHY_VENDOR_ID <= REGISTER_READ_DATA;
		elsif(STATE2 = 3) then
			-- configure OTC control register for peripheral settings
			TRIGGER_REGISTER_WRITE <= '1';
			STATE2 <= STATE2 + 1;
		elsif(STATE2 = 4) and (TRIGGER_REGISTER_WRITE_ACK = '1') then
			STATE2 <= STATE2 + 1;
			TRIGGER_REGISTER_WRITE <= '0';
		end if;
	end if;
end process;


--// UTMI wrapper
	Inst_USB20: USB20 PORT MAP(
		ASYNC_RESET => SYNC_RESET,
		USB_CLK60G => USB_CLK60G,
		CLK_P => CLK_P,
		USB_RESET => USB_RESET,
		USB_DATABUS16_8 => open,
		USB_SUSPENDN => USB_SUSPENDN,
		USB_XCVRSELECT => USB_XCVRSELECT(0),
		USB_TERMSELECT => USB_TERMSELECT,
		USB_OPMODE => USB_OPMODE,
		USB_LINESTATE => USB_LINESTATE,
		USB_TXVALID => USB_TXVALID,
		USB_TXREADY => USB_TXREADY,
		USB_RXVALID => USB_RXVALID,
		USB_RXACTIVE => USB_RXACTIVE,
		USB_RXERROR => USB_RXERROR,
		USB_DATA_IN => USB_DATA_IN,
		USB_DATA_OUT => USB_DATA_OUT,
		USB_VBUS_SENSE => USB_VBUS_SENSE,
		DATA1_OUT => DATA1_OUT,
		DATA1_OUT_SAMPLE_CLK => DATA1_OUT_SAMPLE_CLK,
		DATA1_OUT_BUFFER_EMPTY => DATA1_OUT_BUFFER_EMPTY,
		DATA1_OUT_SAMPLE_CLK_REQ => DATA1_OUT_SAMPLE_CLK_REQ,
		DATA1_IN => DATA1_IN,
		DATA1_IN_SAMPLE_CLK => DATA1_IN_SAMPLE_CLK,
		DATA1_IN_SAMPLE_CLK_REQ => DATA1_IN_SAMPLE_CLK_REQ,
		DATA2_OUT => DATA2_OUT,
		DATA2_OUT_SAMPLE_CLK => DATA2_OUT_SAMPLE_CLK,
		DATA2_OUT_BUFFER_EMPTY => DATA2_OUT_BUFFER_EMPTY,
		DATA2_OUT_SAMPLE_CLK_REQ => DATA2_OUT_SAMPLE_CLK_REQ,
		DATA2_IN => DATA2_IN,
		DATA2_IN_SAMPLE_CLK => DATA2_IN_SAMPLE_CLK,
		DATA2_IN_SAMPLE_CLK_REQ => DATA2_IN_SAMPLE_CLK_REQ,
		USB_TP => USB_TP_LOCAL
	);
USB_XCVRSELECT(1) <= '0';

--// ComScope probes ---------------
CS1 <= USB_DATA_IN;
CS1_CLK <= USB_RXVALID;

CS2 <= USB_ULPI_DATA_OUT;
CS2_CLK <= '1';

--CS3(0) <= USB_ULPI_DIR;
--CS3(1) <= USB_ULPI_NXT;
--CS3(2) <= USB_ULPI_STP_LOCAL;
--CS3(3) <= USB_TXVALID;
--CS3(4) <= USB_TXREADY;
--CS3(5) <= USB_XCVRSELECT(0);
--CS3(6) <= USB_TERMSELECT;
--CS3(7) <= RX_MESSAGE_TOGGLE;
CS3_CLK <= USB_RXVALID;
CS3 <= RX_MESSAGE_TOGGLE & "0000000";

T1 <= TRIGGER_REGISTER_WRITE;
T1_CLK <= '1';
T2 <= TRIGGER_REGISTER_READ;
T2_CLK <= '1';

--// Test points ---------------------

---- tps for ULPI register read
--USB_TP(1) <= '1' when (STATE = 5) else '0';
--USB_TP(2) <= TRIGGER_REGISTER_READ_ACK;
--USB_TP(3) <= USB_ULPI_DIR;
--USB_TP(4) <= USB_ULPI_NXT;
--USB_TP(5) <= '1' when (USB_ULPI_DATA_LOCAL  = x"C0") else '0';
--USB_TP(6) <= '1' when (USB_ULPI_DATA_IN = x"C0") else '0';
--USB_TP(7) <= '1' when (USB_ULPI_DATA_IN = x"24") else '0';
--USB_TP(8) <= USB_TXREADY;
--USB_TP(9) <= TRIGGER_REGISTER_READ;
--USB_TP(10) <= TRIGGER_REGISTER_WRITE;

-- tps for ULPI receive
USB_TP(1) <= '1' when (STATE = 9) else '0';
USB_TP(2) <= USB_ULPI_STP_LOCAL;
USB_TP(3) <= USB_ULPI_DIR;
USB_TP(4) <= USB_ULPI_NXT;
USB_TP(5) <= '1' when (USB_DATA_IN  = x"2D") else '0'; -- SETUP PID
USB_TP(6) <= USB_RXACTIVE;
USB_TP(7) <= USB_RXVALID;
USB_TP(8) <= RXD_CMD_SAMPLE_CLK;
USB_TP(9) <= USB_VBUS_SENSE;
USB_TP(10) <= USB_RXERROR;

-- tps for ULPI transmit
--USB_TP(1) <= '1' when (STATE = 12) else '0';
--USB_TP(2) <= USB_TXVALID;
--USB_TP(3) <= USB_ULPI_DIR;
--USB_TP(4) <= USB_ULPI_NXT;
--USB_TP(5) <= USB_TXREADY;
--USB_TP(6) <= '1' when (USB_ULPI_DATA_LOCAL  = x"42") else '0'; -- ACK PID
--USB_TP(7) <= USB_ULPI_STP_LOCAL;
--USB_TP(8) <= RXD_CMD_SAMPLE_CLK;
--USB_TP(9) <= USB_VBUS_SENSE;
--USB_TP(10) <= USB_RXERROR;

USB_TP(20 downto 11) <= USB_TP_LOCAL(10 downto 1);

end Behavioral;

