module USB_ARBITER( CLK , RST , RXF_N , TXE_N , RD_N , WR , BUS_BUSY ,TG_READY , USB_DATA , TG_DO, TG_DI, TG_RD, TG_WR ); input CLK, RST; input RXF_N, TXE_N; output RD_N, WR; output BUS_BUSY; input TG_READY; inout [7:0] USB_DATA; output [7:0] TG_DO; input [7:0] TG_DI; output TG_RD; input TG_WR; reg [1:0] RD_STATE, WR_STATE; reg RD_N, WR; reg [7:0] TG_DO; reg TG_RD; reg DIR; reg RXF_REG, TXE_REG; reg [7:0] USB_DATA_REG; parameter S0 = 2'b00; parameter S1 = 2'b01; parameter S2 = 2'b10; parameter S3 = 2'b11; always @( posedge CLK or posedge RST ) begin if ( RST ) begin RXF_REG <= 0; TXE_REG <= 0; end else begin RXF_REG <= ~RXF_N; TXE_REG <= ~TXE_N; end end assign USB_DATA = (DIR==1) ? USB_DATA_REG : 8'bz; assign BUS_BUSY = (WR_STATE==0 && RD_STATE==0) ? 1'b0 : 1'b1; /*** */ /** READ STATE MACHINE **/ /* ***/ always @( posedge CLK or posedge RST ) begin if ( RST ) begin TG_DO <= 0; TG_RD <= 0; RD_N <= 1; RD_STATE <= S0; end else begin case( RD_STATE ) S0 : begin if( RXF_REG==1 && TG_READY==1 && WR_STATE==0 ) begin RD_N <= 0; RD_STATE <= S1; end else begin RD_STATE <= S0; end end S1 : begin TG_DO <= USB_DATA; RD_STATE <= S2; end S2 : begin RD_N <= 1; TG_RD <= 1; RD_STATE <= S3; end S3 : begin TG_RD <= 0; RD_STATE <= S0; end default : RD_STATE <= S0; endcase end end /*** */ /** WRITE STATE MACHINE **/ /* ***/ always @( posedge CLK or posedge RST ) begin if( RST ) begin WR <= 1; DIR <= 0; WR_STATE <= S0; end else begin case( WR_STATE ) S0 : begin if( TG_WR==1 ) begin USB_DATA_REG <= TG_DI; WR_STATE <= S1; end else begin WR_STATE <= S0; end end S1 : begin if( TXE_REG==1 && RD_STATE==0) begin WR <= 1; DIR <=1; WR_STATE <= S2; end else begin WR_STATE <= S1; end end S2 : begin WR <= 0; DIR <= 1; WR_STATE <= S3; end S3 : begin WR <= 1; DIR <= 0; WR_STATE <= S0; end default : WR_STATE <= S0; endcase end end endmodule