//////////////////////////////////////////////////////////////////////
//// ////
//// EP0.v ////
//// ////
//// This file is part of the usbHostSlave opencores effort.
//// ////
//// ////
//// Module Description: ////
//// Implements EP0 control endpoint
//// Responds to 8-byte SETUP packets
//// of type GET_STATUS, GET_DESCRIPTOR and
//// SET_ADDRESS
//// ////
//// To Do: ////
////
//// ////
//// Author(s): ////
//// - Steve Fielding, sfielding@base2designs.com ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2008 Steve Fielding and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from ////
//// ////
//////////////////////////////////////////////////////////////////////
//
`include "timescale.v"
`include "usbHostSlaveReg_define.v"
`include "usbDevice_define.v"
module EP0 (clk, initComplete, memAddr, memData, memRdEn, rst, wb_ack, wb_addr, wb_data_i, wb_data_o, wb_stb, wb_we, wbBusGnt, wbBusReq);
input clk;
input [7:0]memData;
input rst;
input wb_ack;
input [7:0]wb_data_i;
input wbBusGnt;
output initComplete;
output [7:0]memAddr;
output memRdEn;
output [7:0]wb_addr;
output [7:0]wb_data_o;
output wb_stb;
output wb_we;
output wbBusReq;
wire clk;
reg initComplete, next_initComplete;
reg [7:0]memAddr, next_memAddr;
wire [7:0]memData;
reg memRdEn, next_memRdEn;
wire rst;
wire wb_ack;
reg [7:0]wb_addr, next_wb_addr;
wire [7:0]wb_data_i;
reg [7:0]wb_data_o, next_wb_data_o;
reg wb_stb, next_wb_stb;
reg wb_we, next_wb_we;
wire wbBusGnt;
reg wbBusReq, next_wbBusReq;
// diagram signals declarations
reg bm_req_dir, next_bm_req_dir;
reg [4:0]bm_req_recp, next_bm_req_recp;
reg [1:0]bm_req_type, next_bm_req_type;
reg [7:0]bRequest, next_bRequest;
reg [7:0]cnt, next_cnt;
reg dataSeq, next_dataSeq;
reg [7:0]epStatus, next_epStatus;
reg [7:0]epTransType, next_epTransType;
reg localRst, next_localRst;
reg [15:0]rxDataSize, next_rxDataSize;
reg transDone, next_transDone;
reg [7:0]txDataIndex, next_txDataIndex;
reg [7:0]txDataSize, next_txDataSize;
reg [7:0]txPacketRemSize, next_txPacketRemSize;
reg updateUSBAddress, next_updateUSBAddress;
reg [7:0]USBAddress, next_USBAddress;
reg [15:0]wIndex, next_wIndex;
reg [15:0]wLength, next_wLength;
reg [15:0]wValue, next_wValue;
// BINARY ENCODED state machine: EP0St
// State codes definitions:
`define INIT_RST 6'b000000
`define INIT_WT_GNT 6'b000001
`define INIT_WT_RST 6'b000010
`define INIT_WT_VBUS 6'b000011
`define INIT_FIN 6'b000100
`define DO_TRANS_WT_GNT 6'b000101
`define DO_TRANS_TX_EMPTY 6'b000110
`define DO_TRANS_WR_TX_FIFO 6'b000111
`define DO_TRANS_RD_MEM 6'b001000
`define DO_TRANS_CHK_TX_DONE 6'b001001
`define DO_TRANS_TRANS_GO 6'b001010
`define DO_TRANS_WT_TRANS_DONE_WT_GNT 6'b001011
`define DO_TRANS_WT_TRANS_DONE_GET_RDY_STS 6'b001100
`define DO_TRANS_WT_TRANS_DONE_WT_UNGNT 6'b001101
`define DO_TRANS_WT_TRANS_DONE_CHK_DONE 6'b001110
`define CHK_TRANS_RD_STAT 6'b001111
`define CHK_TRANS_WT_GNT 6'b010000
`define CHK_TRANS_RD_RX_SIZE1 6'b010001
`define CHK_TRANS_RD_RX_SIZE2 6'b010010
`define CHK_TRANS_RD_TRANS_TYPE 6'b010011
`define CHK_TRANS_WT_UNGNT 6'b010100
`define SETUP_CHK_ERR 6'b010101
`define SETUP_GET_DATA_DAT1 6'b010110
`define SETUP_GET_DATA_WT_GNT 6'b010111
`define SETUP_GET_DATA_DAT2 6'b011000
`define SETUP_GET_DATA_DAT3 6'b011001
`define SETUP_GET_DATA_DAT4 6'b011010
`define SETUP_GET_DATA_DAT6 6'b011011
`define SETUP_GET_DATA_DAT5 6'b011100
`define SETUP_GET_DATA_DAT8 6'b011101
`define SETUP_GET_DATA_DAT7 6'b011110
`define SETUP_GET_DATA_WT_UNGNT 6'b011111
`define SETUP_GET_STAT 6'b100000
`define SETUP_SET_ADDR 6'b100001
`define SETUP_GET_DESC_S1 6'b100010
`define SETUP_CHK_MAX_LEN 6'b100011
`define OUT_CHK_SEQ 6'b100100
`define IN_CHK_ACK 6'b100101
`define IN_SET_PTR 6'b100110
`define IN_SET_ADDR 6'b100111
`define IN_WT_GNT 6'b101000
`define IN_WT_UNGNT 6'b101001
`define DO_TRANS_RX_EMPTY 6'b101010
`define DO_TRANS_WT_TRANS_DONE_DEL 6'b101011
`define START 6'b101100
`define INIT_CONN 6'b101101
`define INIT_WT_CONN 6'b101110
`define DO_TRANS_DEL 6'b101111
`define SETUP_PTR_SET 6'b110000
reg [5:0]CurrState_EP0St, NextState_EP0St;
// Diagram actions (continuous assignments allowed only: assign ...)
// diagram ACTION
// Machine: EP0St
// NextState logic (combinatorial)
always @ (wb_ack or wbBusGnt or cnt or wb_data_i or memData or txDataIndex or txDataSize or transDone or epStatus or epTransType or rxDataSize or bRequest or wValue or wLength or dataSeq or updateUSBAddress or txPacketRemSize or USBAddress or wb_addr or wb_data_o or wb_stb or wb_we or wbBusReq or initComplete or memAddr or memRdEn or bm_req_dir or bm_req_type or bm_req_recp or wIndex or CurrState_EP0St)
begin
NextState_EP0St <= CurrState_EP0St;
// Set default values for outputs and signals
next_wb_addr <= wb_addr;
next_wb_data_o <= wb_data_o;
next_wb_stb <= wb_stb;
next_wb_we <= wb_we;
next_cnt <= cnt;
next_wbBusReq <= wbBusReq;
next_initComplete <= initComplete;
next_memAddr <= memAddr;
next_memRdEn <= memRdEn;
next_txDataSize <= txDataSize;
next_txDataIndex <= txDataIndex;
next_transDone <= transDone;
next_epStatus <= epStatus;
next_rxDataSize <= rxDataSize;
next_epTransType <= epTransType;
next_bm_req_dir <= bm_req_dir;
next_bm_req_type <= bm_req_type;
next_bm_req_recp <= bm_req_recp;
next_bRequest <= bRequest;
next_wValue <= wValue;
next_wIndex <= wIndex;
next_wLength <= wLength;
next_txPacketRemSize <= txPacketRemSize;
next_USBAddress <= USBAddress;
next_updateUSBAddress <= updateUSBAddress;
next_dataSeq <= dataSeq;
case (CurrState_EP0St) // synopsys parallel_case full_case
`START:
begin
next_initComplete <= 1'b0;
next_wbBusReq <= 1'b0;
next_wb_addr <= 8'h00;
next_wb_data_o <= 8'h00;
next_wb_stb <= 1'b0;
next_wb_we <= 1'b0;
next_txPacketRemSize <= 8'h00;
next_txDataSize <= 8'h00;
next_txDataIndex <= 8'h00;
next_epTransType <= 8'h00;
next_epStatus <= 8'h00;
next_rxDataSize <= 16'h0000;
next_cnt <= 8'h00;
next_memRdEn <= 1'b0;
next_memAddr <= 8'h00;
next_updateUSBAddress <= 1'b0;
next_transDone <= 1'b0;
next_bm_req_type <= 2'b00;
next_bm_req_dir <= 1'b0;
next_bm_req_recp <= 5'b00000;
next_bRequest <= 8'h00;
next_wLength <= 16'h0000;
next_wIndex <= 16'h0000;
next_wValue <= 16'h0000;
next_dataSeq <= 1'b0;
next_USBAddress <= 8'h00;
NextState_EP0St <= `INIT_WT_GNT;
end
`CHK_TRANS_RD_STAT:
begin
next_wb_addr <= `RA_EP0_STATUS_REG;
next_wb_stb <= 1'b1;
next_wb_we <= 1'b0;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `CHK_TRANS_RD_RX_SIZE1;
next_wb_stb <= 1'b0;
next_epStatus <= wb_data_i;
end
end
`CHK_TRANS_WT_GNT:
begin
if (wbBusGnt == 1'b1)
begin
NextState_EP0St <= `CHK_TRANS_RD_STAT;
end
end
`CHK_TRANS_RD_RX_SIZE1:
begin
next_wb_addr <= `RA_EP0_RX_FIFO_DATA_COUNT_MSB;
next_wb_stb <= 1'b1;
next_wb_we <= 1'b0;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `CHK_TRANS_RD_RX_SIZE2;
next_wb_stb <= 1'b0;
next_rxDataSize[15:8] <= wb_data_i;
end
end
`CHK_TRANS_RD_RX_SIZE2:
begin
next_wb_addr <= `RA_EP0_RX_FIFO_DATA_COUNT_LSB;
next_wb_stb <= 1'b1;
next_wb_we <= 1'b0;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `CHK_TRANS_RD_TRANS_TYPE;
next_wb_stb <= 1'b0;
next_rxDataSize[7:0] <= wb_data_i;
end
end
`CHK_TRANS_RD_TRANS_TYPE:
begin
next_wb_addr <= `RA_EP0_TRANSTYPE_STATUS_REG;
next_wb_stb <= 1'b1;
next_wb_we <= 1'b0;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `CHK_TRANS_WT_UNGNT;
next_wb_stb <= 1'b0;
next_epTransType <= wb_data_i;
end
end
`CHK_TRANS_WT_UNGNT:
begin
next_wbBusReq <= 1'b0;
if ((wbBusGnt == 1'b0) && ((epStatus & 8'h0f) != 8'h00))
begin
NextState_EP0St <= `DO_TRANS_WT_GNT;
end
else if ((wbBusGnt == 1'b0) && (epTransType == `SC_SETUP_TRANS))
begin
NextState_EP0St <= `SETUP_CHK_ERR;
end
else if ((wbBusGnt == 1'b0) && (epTransType == `SC_IN_TRANS))
begin
NextState_EP0St <= `IN_CHK_ACK;
end
else if ((wbBusGnt == 1'b0) && (epTransType == `SC_OUTDATA_TRANS))
begin
NextState_EP0St <= `OUT_CHK_SEQ;
end
else if (wbBusGnt == 1'b0)
begin
NextState_EP0St <= `DO_TRANS_WT_GNT;
end
end
`DO_TRANS_WT_GNT:
begin
next_wbBusReq <= 1'b1;
if (wbBusGnt == 1'b1)
begin
NextState_EP0St <= `DO_TRANS_TX_EMPTY;
end
end
`DO_TRANS_TX_EMPTY:
begin
next_wb_addr <= `RA_EP0_TX_FIFO_CONTROL_REG;
next_wb_data_o <= 8'h01;
//force tx fifo empty
next_wb_stb <= 1'b1;
next_wb_we <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `DO_TRANS_RX_EMPTY;
next_wb_stb <= 1'b0;
end
end
`DO_TRANS_WR_TX_FIFO:
begin
next_wb_data_o <= memData;
next_wb_addr <= `RA_EP0_TX_FIFO_DATA_REG;
next_wb_stb <= 1'b1;
next_wb_we <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `DO_TRANS_CHK_TX_DONE;
next_wb_stb <= 1'b0;
end
end
`DO_TRANS_RD_MEM:
begin
next_memAddr <= txDataIndex;
next_memRdEn <= 1'b1;
next_txDataSize <= txDataSize - 1'b1;
next_txDataIndex <= txDataIndex + 1'b1;
NextState_EP0St <= `DO_TRANS_DEL;
end
`DO_TRANS_CHK_TX_DONE:
begin
if (txDataSize == 8'h00)
begin
NextState_EP0St <= `DO_TRANS_TRANS_GO;
end
else
begin
NextState_EP0St <= `DO_TRANS_RD_MEM;
end
end
`DO_TRANS_TRANS_GO:
begin
next_wb_addr <= `RA_EP0_CONTROL_REG;
if (dataSeq == 1'b1)
next_wb_data_o <= 8'h07;
else
next_wb_data_o <= 8'h03;
next_wb_stb <= 1'b1;
next_wb_we <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `DO_TRANS_WT_TRANS_DONE_WT_GNT;
next_wb_stb <= 1'b0;
next_transDone <= 1'b0;
end
end
`DO_TRANS_RX_EMPTY:
begin
next_wb_addr <= `RA_EP0_RX_FIFO_CONTROL_REG;
next_wb_data_o <= 8'h01;
//force rx fifo empty
next_wb_stb <= 1'b1;
next_wb_we <= 1'b1;
if ((wb_ack == 1'b1) && (txDataSize != 8'h00))
begin
NextState_EP0St <= `DO_TRANS_RD_MEM;
next_wb_stb <= 1'b0;
end
else if (wb_ack == 1'b1)
begin
NextState_EP0St <= `DO_TRANS_TRANS_GO;
next_wb_stb <= 1'b0;
end
end
`DO_TRANS_DEL:
begin
next_memRdEn <= 1'b0;
NextState_EP0St <= `DO_TRANS_WR_TX_FIFO;
end
`DO_TRANS_WT_TRANS_DONE_WT_GNT:
begin
next_wbBusReq <= 1'b1;
if (wbBusGnt == 1'b1)
begin
NextState_EP0St <= `DO_TRANS_WT_TRANS_DONE_GET_RDY_STS;
end
end
`DO_TRANS_WT_TRANS_DONE_GET_RDY_STS:
begin
next_wb_addr <= `RA_EP0_CONTROL_REG;
next_wb_stb <= 1'b1;
next_wb_we <= 1'b0;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `DO_TRANS_WT_TRANS_DONE_WT_UNGNT;
next_wb_stb <= 1'b0;
next_transDone <= ~wb_data_i[`ENDPOINT_READY_BIT];
end
end
`DO_TRANS_WT_TRANS_DONE_WT_UNGNT:
begin
next_wbBusReq <= 1'b0;
if (wbBusGnt == 1'b0)
begin
NextState_EP0St <= `DO_TRANS_WT_TRANS_DONE_CHK_DONE;
end
end
`DO_TRANS_WT_TRANS_DONE_CHK_DONE:
begin
if (transDone == 1'b1)
begin
NextState_EP0St <= `CHK_TRANS_WT_GNT;
next_wbBusReq <= 1'b1;
end
else
begin
NextState_EP0St <= `DO_TRANS_WT_TRANS_DONE_DEL;
next_cnt <= 8'h00;
end
end
`DO_TRANS_WT_TRANS_DONE_DEL:
begin
next_cnt <= cnt + 1'b1;
if (cnt == `ONE_USEC_DEL)
begin
NextState_EP0St <= `DO_TRANS_WT_TRANS_DONE_WT_GNT;
end
end
`SETUP_CHK_ERR:
begin
if (rxDataSize != 16'h0008)
begin
NextState_EP0St <= `DO_TRANS_WT_GNT;
end
else
begin
NextState_EP0St <= `SETUP_GET_DATA_WT_GNT;
next_wbBusReq <= 1'b1;
next_txDataSize <= 8'h00;
next_txPacketRemSize <= 8'h00;
//default tx packet size
next_dataSeq <= 1'b1;
next_wb_addr <= `RA_EP0_RX_FIFO_DATA_REG;
next_wb_we <= 1'b0;
end
end
`SETUP_GET_STAT:
begin
if (bm_req_type == 2'b00) begin
next_txPacketRemSize <= 8'h02;
if (bm_req_recp == 5'b00000)
next_txDataIndex <= `ONE_ZERO_STAT_INDEX;
else
next_txDataIndex <= `ZERO_ZERO_STAT_INDEX;
end
else if (bm_req_type == 2'b10) begin
next_txDataIndex <= `VENDOR_DATA_STAT_INDEX;
next_txPacketRemSize <= 8'h02;
end
NextState_EP0St <= `SETUP_CHK_MAX_LEN;
end
`SETUP_SET_ADDR:
begin
if ( (wValue[15:7] == {9{1'b0}}) && (wIndex == 16'h0000) && (wLength == 16'h0000) ) begin
next_USBAddress <= wValue[7:0];
next_updateUSBAddress <= 1'b1;
end
NextState_EP0St <= `SETUP_CHK_MAX_LEN;
end
`SETUP_CHK_MAX_LEN:
begin
if (txPacketRemSize > wLength)
next_txPacketRemSize <= wLength;
NextState_EP0St <= `SETUP_PTR_SET;
end
`SETUP_PTR_SET:
begin
if (txPacketRemSize > `MAX_RESP_SIZE) begin
next_txDataSize <= `MAX_RESP_SIZE;
next_txPacketRemSize <= txPacketRemSize - `MAX_RESP_SIZE;
end
else begin
next_txDataSize <= txPacketRemSize;
next_txPacketRemSize <= 8'h00;
end
NextState_EP0St <= `DO_TRANS_WT_GNT;
end
`SETUP_GET_DATA_DAT1:
begin
next_wb_stb <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `SETUP_GET_DATA_DAT2;
next_wb_stb <= 1'b0;
next_bm_req_dir <= wb_data_i[7];
next_bm_req_type <= wb_data_i[6:5];
next_bm_req_recp <= wb_data_i[4:0];
end
end
`SETUP_GET_DATA_WT_GNT:
begin
if (wbBusGnt == 1'b1)
begin
NextState_EP0St <= `SETUP_GET_DATA_DAT1;
end
end
`SETUP_GET_DATA_DAT2:
begin
next_wb_stb <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `SETUP_GET_DATA_DAT3;
next_wb_stb <= 1'b0;
next_bRequest <= wb_data_i;
end
end
`SETUP_GET_DATA_DAT3:
begin
next_wb_stb <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `SETUP_GET_DATA_DAT4;
next_wb_stb <= 1'b0;
next_wValue[7:0] <= wb_data_i;
end
end
`SETUP_GET_DATA_DAT4:
begin
next_wb_stb <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `SETUP_GET_DATA_DAT5;
next_wb_stb <= 1'b0;
next_wValue[15:8] <= wb_data_i;
end
end
`SETUP_GET_DATA_DAT6:
begin
next_wb_stb <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `SETUP_GET_DATA_DAT7;
next_wb_stb <= 1'b0;
next_wIndex[15:8] <= wb_data_i;
end
end
`SETUP_GET_DATA_DAT5:
begin
next_wb_stb <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `SETUP_GET_DATA_DAT6;
next_wb_stb <= 1'b0;
next_wIndex[7:0] <= wb_data_i;
end
end
`SETUP_GET_DATA_DAT8:
begin
next_wb_stb <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `SETUP_GET_DATA_WT_UNGNT;
next_wb_stb <= 1'b0;
next_wLength[15:8] <= wb_data_i;
next_wbBusReq <= 1'b0;
end
end
`SETUP_GET_DATA_DAT7:
begin
next_wb_stb <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `SETUP_GET_DATA_DAT8;
next_wb_stb <= 1'b0;
next_wLength[7:0] <= wb_data_i;
end
end
`SETUP_GET_DATA_WT_UNGNT:
begin
if ((wbBusGnt == 1'b0) && (bRequest == `GET_STATUS))
begin
NextState_EP0St <= `SETUP_GET_STAT;
end
else if ((wbBusGnt == 1'b0) && (bRequest == `GET_DESCRIPTOR))
begin
NextState_EP0St <= `SETUP_GET_DESC_S1;
end
else if ((wbBusGnt == 1'b0) && (bRequest == `SET_ADDRESS))
begin
NextState_EP0St <= `SETUP_SET_ADDR;
end
else if (wbBusGnt == 1'b0)
begin
NextState_EP0St <= `DO_TRANS_WT_GNT;
end
end
`SETUP_GET_DESC_S1:
begin
case (wValue[15:8])
`DEV_DESC: begin
next_txPacketRemSize <= `DEV_DESC_SIZE;
next_txDataIndex <= `DEV_DESC_INDEX;
end
`CFG_DESC: begin
next_txPacketRemSize <= `CFG_DESC_SIZE;
next_txDataIndex <= `CFG_DESC_INDEX;
end
`REP_DESC: begin
next_txPacketRemSize <= `REP_DESC_SIZE;
next_txDataIndex <= `REP_DESC_INDEX;
end
`STRING_DESC: begin
case (wValue[3:0])
4'h0: begin
next_txPacketRemSize <= `LANGID_DESC_SIZE;
next_txDataIndex <= `LANGID_DESC_INDEX;
end
4'h1: begin
next_txPacketRemSize <= `STRING1_DESC_SIZE;
next_txDataIndex <= `STRING1_DESC_INDEX;
end
4'h2: begin
next_txPacketRemSize <= `STRING2_DESC_SIZE;
next_txDataIndex <= `STRING2_DESC_INDEX;
end
4'h3: begin
next_txPacketRemSize <= `STRING3_DESC_SIZE;
next_txDataIndex <= `STRING3_DESC_INDEX;
end
endcase
end
endcase
NextState_EP0St <= `SETUP_CHK_MAX_LEN;
end
`IN_CHK_ACK:
begin
if (epStatus[`SC_ACK_RXED_BIT] != 1'b1)
begin
NextState_EP0St <= `DO_TRANS_WT_GNT;
end
else if (updateUSBAddress == 1'b1)
begin
NextState_EP0St <= `IN_WT_GNT;
end
else
begin
NextState_EP0St <= `IN_SET_PTR;
end
end
`IN_SET_PTR:
begin
if (txPacketRemSize > `MAX_RESP_SIZE) begin
next_txDataSize <= `MAX_RESP_SIZE;
next_txPacketRemSize <= txPacketRemSize - `MAX_RESP_SIZE;
end
else begin
next_txDataSize <= txPacketRemSize;
next_txPacketRemSize <= 8'h00;
end
NextState_EP0St <= `DO_TRANS_WT_GNT;
end
`IN_SET_ADDR:
begin
next_wb_addr <= `RA_SC_ADDRESS;
next_wb_data_o <= USBAddress;
next_wb_stb <= 1'b1;
next_wb_we <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `IN_WT_UNGNT;
next_wb_stb <= 1'b0;
next_wbBusReq <= 1'b0;
end
end
`IN_WT_GNT:
begin
next_wbBusReq <= 1'b1;
next_updateUSBAddress <= 1'b0;
if (wbBusGnt == 1'b1)
begin
NextState_EP0St <= `IN_SET_ADDR;
end
end
`IN_WT_UNGNT:
begin
if (wbBusGnt == 1'b0)
begin
NextState_EP0St <= `IN_SET_PTR;
end
end
`OUT_CHK_SEQ:
begin
if (epStatus[`SC_DATA_SEQUENCE_BIT] != dataSeq)
begin
NextState_EP0St <= `DO_TRANS_WT_GNT;
end
else
begin
NextState_EP0St <= `DO_TRANS_WT_GNT;
next_dataSeq <= ~dataSeq;
end
end
`INIT_RST:
begin
next_wb_addr <= `RA_HOST_SLAVE_MODE;
next_wb_data_o <= 8'h2;
//reset usbHostSlave
next_wb_stb <= 1'b1;
next_wb_we <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `INIT_WT_RST;
next_wb_stb <= 1'b0;
next_cnt <= 8'h00;
end
end
`INIT_WT_GNT:
begin
next_wbBusReq <= 1'b1;
if (wbBusGnt == 1'b1)
begin
NextState_EP0St <= `INIT_RST;
end
end
`INIT_WT_RST:
begin
next_cnt <= cnt + 1'b1;
if (cnt == 8'hff)
begin
NextState_EP0St <= `INIT_WT_VBUS;
end
end
`INIT_WT_VBUS:
begin
next_wb_addr <= `RA_SC_LINE_STATUS_REG;
next_wb_stb <= 1'b1;
next_wb_we <= 1'b0;
if ((wb_ack == 1'b1) && (wb_data_i[`VBUS_PRES_BIT] == 1'b1))
begin
NextState_EP0St <= `INIT_CONN;
next_wb_stb <= 1'b0;
end
end
`INIT_FIN:
begin
next_wbBusReq <= 1'b0;
next_initComplete <= 1'b1;
if (wbBusGnt == 1'b0)
begin
NextState_EP0St <= `DO_TRANS_WT_GNT;
end
end
`INIT_CONN:
begin
next_wb_addr <= `RA_SC_CONTROL_REG;
next_wb_data_o <= 8'h71;
//connect to host, full speed
next_wb_stb <= 1'b1;
next_wb_we <= 1'b1;
if (wb_ack == 1'b1)
begin
NextState_EP0St <= `INIT_WT_CONN;
next_wb_stb <= 1'b0;
end
end
`INIT_WT_CONN:
begin
next_wb_addr <= `RA_SC_LINE_STATUS_REG;
next_wb_stb <= 1'b1;
next_wb_we <= 1'b0;
if ((wb_ack == 1'b1) && (wb_data_i[1:0] == `FULL_SPEED_CONNECT))
begin
NextState_EP0St <= `INIT_FIN;
next_wb_stb <= 1'b0;
end
end
endcase
end
// Current State Logic (sequential)
always @ (posedge clk)
begin
if (rst == 1'b1)
CurrState_EP0St <= `START;
else
CurrState_EP0St <= NextState_EP0St;
end
// Registered outputs logic
always @ (posedge clk)
begin
if (rst == 1'b1)
begin
wb_addr <= 8'h00;
wb_data_o <= 8'h00;
wb_stb <= 1'b0;
wb_we <= 1'b0;
wbBusReq <= 1'b0;
initComplete <= 1'b0;
memAddr <= 8'h00;
memRdEn <= 1'b0;
cnt <= 8'h00;
txDataSize <= 8'h00;
txDataIndex <= 8'h00;
transDone <= 1'b0;
epStatus <= 8'h00;
rxDataSize <= 16'h0000;
epTransType <= 8'h00;
bm_req_dir <= 1'b0;
bm_req_type <= 2'b00;
bm_req_recp <= 5'b00000;
bRequest <= 8'h00;
wValue <= 16'h0000;
wIndex <= 16'h0000;
wLength <= 16'h0000;
txPacketRemSize <= 8'h00;
USBAddress <= 8'h00;
updateUSBAddress <= 1'b0;
dataSeq <= 1'b0;
end
else
begin
wb_addr <= next_wb_addr;
wb_data_o <= next_wb_data_o;
wb_stb <= next_wb_stb;
wb_we <= next_wb_we;
wbBusReq <= next_wbBusReq;
initComplete <= next_initComplete;
memAddr <= next_memAddr;
memRdEn <= next_memRdEn;
cnt <= next_cnt;
txDataSize <= next_txDataSize;
txDataIndex <= next_txDataIndex;
transDone <= next_transDone;
epStatus <= next_epStatus;
rxDataSize <= next_rxDataSize;
epTransType <= next_epTransType;
bm_req_dir <= next_bm_req_dir;
bm_req_type <= next_bm_req_type;
bm_req_recp <= next_bm_req_recp;
bRequest <= next_bRequest;
wValue <= next_wValue;
wIndex <= next_wIndex;
wLength <= next_wLength;
txPacketRemSize <= next_txPacketRemSize;
USBAddress <= next_USBAddress;
updateUSBAddress <= next_updateUSBAddress;
dataSeq <= next_dataSeq;
end
end
endmodule