--*** *-- --** USB_ARBITER **-- --* ***-- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity USB_ARBITER is Port ( CLK : in std_logic; RST : in std_logic; RXF_N : in std_logic; TXE_N : in std_logic; RD_N : out std_logic; WR : out std_logic; BUS_BUSY : out std_logic; TG_READY : in std_logic; USB_DATA : inout std_logic_vector( 7 downto 0 ); TG_DO : out std_logic_vector( 7 downto 0 ); TG_DI : in std_logic_vector( 7 downto 0 ); TG_RD : out std_logic; TG_WR : in std_logic ); end USB_ARBITER; architecture RTL of USB_ARBITER is signal RXF_REG : std_logic; signal TXE_REG : std_logic; signal USB_DATA_REG : std_logic_vector( 7 downto 0 ); signal DIR : std_logic; signal RD_STATE : std_logic_vector( 1 downto 0 ); signal WR_STATE : std_logic_vector( 1 downto 0 ); constant S0 : std_logic_vector := "00"; constant S1 : std_logic_vector := "01"; constant S2 : std_logic_vector := "10"; constant S3 : std_logic_vector := "11"; begin USB_DATA <= USB_DATA_REG when( DIR = '1') else "ZZZZZZZZ"; BUS_BUSY <= '0' when( WR_STATE="00" and RD_STATE="00" ) else '1'; process( CLK, RST ) begin if ( RST ='1') then RXF_REG <= '0'; TXE_REG <= '0'; elsif( CLK'event and CLK='1') then RXF_REG <= not RXF_N; TXE_REG <= not TXE_N; else NULL; end if; end process; --*** *-- --** READ STATE MACHINE **-- --* ***-- process( CLK, RST ) begin if ( RST ='1') then TG_DO <= "XXXXXXXX"; TG_RD <= '0'; RD_N <= '1'; RD_STATE <= S0; elsif( CLK'event and CLK='1') then case RD_STATE is when S0 => if( RXF_REG='1' and TG_READY='1' and WR_STATE="00") then RD_N <= '0'; RD_STATE <= S1; else RD_STATE <= S0; end if; when S1 => TG_DO <= USB_DATA; RD_STATE <= S2; when S2 => RD_N <= '1'; TG_RD <= '1'; RD_STATE <= S3; when S3 => TG_RD <= '0'; RD_STATE <= S0; when others => RD_STATE <= S0; end case; end if; end process; --*** *-- --** WRITE STATE MACHINE **-- --* ***-- process( CLK, RST ) begin if( RST ='1') then WR <= '1'; WR_STATE <= S0; DIR <= '0'; elsif( CLK'event and CLK='1') then case WR_STATE is when S0 => if( TG_WR='1') then USB_DATA_REG <= TG_DI; WR_STATE <= S1; else WR_STATE <= S0; end if; when S1 => if( TXE_REG='1' and RD_STATE="00") then WR <= '1'; DIR <='1'; WR_STATE <= S2; else WR_STATE <= S1; end if; when S2 => WR <= '0'; DIR <= '1'; WR_STATE <= S3; when S3 => WR <= '1'; DIR <= '0'; WR_STATE <= S0; when others => WR_STATE <= S0; end case; end if; end process; end RTL;