URL
https://opencores.org/ocsvn/usb1_funct/usb1_funct/trunk
Subversion Repositories usb1_funct
[/] [usb1_funct/] [tags/] [start/] [rtl/] [verilog/] [usb1_pe.v] - Rev 10
Compare with Previous | Blame | View Log
///////////////////////////////////////////////////////////////////// //// //// //// Protocol Engine //// //// Performs automatic protocol functions //// //// //// //// Author: Rudolf Usselmann //// //// rudi@asics.ws //// //// //// //// //// //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// //// //// ///////////////////////////////////////////////////////////////////// //// //// //// Copyright (C) 2000-2002 Rudolf Usselmann //// //// www.asics.ws //// //// rudi@asics.ws //// //// //// //// 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// //// POSSIBILITY OF SUCH DAMAGE. //// //// //// ///////////////////////////////////////////////////////////////////// // CVS Log // // $Id: usb1_pe.v,v 1.1.1.1 2002-09-19 12:07:24 rudi Exp $ // // $Date: 2002-09-19 12:07:24 $ // $Revision: 1.1.1.1 $ // $Author: rudi $ // $Locker: $ // $State: Exp $ // // Change History: // $Log: not supported by cvs2svn $ // // // // // // `include "usb1_defines.v" module usb1_pe( clk, rst, // UTMI Interfaces tx_valid, rx_active, // PID Information pid_OUT, pid_IN, pid_SOF, pid_SETUP, pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA, pid_ACK, pid_PING, // Token Information token_valid, // Receive Data Output rx_data_done, crc16_err, // Packet Assembler Interface send_token, token_pid_sel, data_pid_sel, // IDMA Interface rx_dma_en, tx_dma_en, abort, idma_done, // Register File Interface fsel, ep_sel, match, nse_err, ep_full, ep_empty, int_upid_set, int_crc16_set, int_to_set, int_seqerr_set, csr, send_stall ); input clk, rst; input tx_valid, rx_active; // Packet Disassembler Interface // Decoded PIDs (used when token_valid is asserted) input pid_OUT, pid_IN, pid_SOF, pid_SETUP; input pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; input pid_ACK, pid_PING; input token_valid; // Token is valid input rx_data_done; // Indicates end of a transfer input crc16_err; // Data packet CRC 16 error // Packet Assembler Interface output send_token; output [1:0] token_pid_sel; output [1:0] data_pid_sel; // IDMA Interface output rx_dma_en; // Allows the data to be stored output tx_dma_en; // Allows for data to be retrieved output abort; // Abort Transfer (time_out, crc_err or rx_error) input idma_done; // DMA is done indicator input ep_full; // Indicates the endpoints fifo is full input ep_empty; // Indicates the endpoints fifo is empty // Register File interface input fsel; // This function is selected input [3:0] ep_sel; // Endpoint Number Input input match; // Endpoint Matched output nse_err; // no such endpoint error output int_upid_set; // Set unsupported PID interrupt output int_crc16_set; // Set CRC16 error interrupt output int_to_set; // Set time out interrupt output int_seqerr_set; // Set PID sequence error interrupt input [13:0] csr; // Internal CSR Output input send_stall; // Force sending a STALL during setup /////////////////////////////////////////////////////////////////// // // Local Wires and Registers // // tx token decoding parameter ACK = 0, NACK = 1, STALL = 2, NYET = 3; // State decoding parameter [9:0] // synopsys enum state IDLE = 10'b000000_0001, TOKEN = 10'b000000_0010, IN = 10'b000000_0100, IN2 = 10'b000000_1000, OUT = 10'b000001_0000, OUT2A = 10'b000010_0000, OUT2B = 10'b000100_0000, UPDATEW = 10'b001000_0000, UPDATE = 10'b010000_0000, UPDATE2 = 10'b100000_0000; reg [1:0] token_pid_sel; reg [1:0] token_pid_sel_d; reg send_token; reg send_token_d; reg rx_dma_en, tx_dma_en; reg int_seqerr_set_d; reg int_seqerr_set; reg int_upid_set; reg match_r; // Endpoint Decoding wire IN_ep, OUT_ep, CTRL_ep; // Endpoint Types wire txfr_iso, txfr_bulk, txfr_int; // Transfer Types reg [1:0] uc_dpd; // Buffer checks reg [9:0] /* synopsys enum state */ state, next_state; // synopsys state_vector state // PID next and current decoders reg [1:0] next_dpid; reg [1:0] this_dpid; reg pid_seq_err; wire [1:0] tr_fr_d; wire [13:0] size_next; wire buf_smaller; // After sending Data in response to an IN token from host, the // host must reply with an ack. The host has XXXnS to reply. // "rx_ack_to" indicates when this time has expired. // rx_ack_to_clr, clears the timer reg rx_ack_to_clr; reg rx_ack_to_clr_d; reg rx_ack_to; reg [7:0] rx_ack_to_cnt; // After sending a OUT token the host must send a data packet. // The host has XX nS to send the packet. "tx_data_to" indicates // when this time has expired. // tx_data_to_clr, clears the timer wire tx_data_to_clr; reg tx_data_to; reg [7:0] tx_data_to_cnt; wire [7:0] rx_ack_to_val, tx_data_to_val; wire [1:0] next_bsel; reg uc_stat_set_d; reg uc_dpd_set; reg in_token; reg out_token; reg setup_token; wire in_op, out_op; // Indicate a IN or OUT operation reg [1:0] allow_pid; reg nse_err; reg abort; wire [1:0] ep_type, txfr_type; /////////////////////////////////////////////////////////////////// // // Misc Logic // // Endpoint/CSR Decoding assign IN_ep = csr[9]; assign OUT_ep = csr[10]; assign CTRL_ep = csr[11]; assign txfr_iso = csr[12]; assign txfr_bulk = csr[13]; assign txfr_int = !csr[12] & !csr[13]; assign ep_type = csr[10:9]; assign txfr_type = csr[13:12]; always @(posedge clk) match_r <= #1 match & fsel; // No Such Endpoint Indicator always @(posedge clk) nse_err <= #1 token_valid & (pid_OUT | pid_IN | pid_SETUP) & !match; always @(posedge clk) send_token <= #1 send_token_d; always @(posedge clk) token_pid_sel <= #1 token_pid_sel_d; /////////////////////////////////////////////////////////////////// // // Data Pid Storage // reg [1:0] ep0_dpid, ep1_dpid, ep2_dpid, ep3_dpid; reg [1:0] ep4_dpid, ep5_dpid, ep6_dpid, ep7_dpid; always @(posedge clk or negedge rst) if(!rst) ep0_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h0)) ep0_dpid <= next_dpid; always @(posedge clk or negedge rst) if(!rst) ep1_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h1)) ep1_dpid <= next_dpid; always @(posedge clk or negedge rst) if(!rst) ep2_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h2)) ep2_dpid <= next_dpid; always @(posedge clk or negedge rst) if(!rst) ep3_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h3)) ep3_dpid <= next_dpid; always @(posedge clk or negedge rst) if(!rst) ep4_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h4)) ep4_dpid <= next_dpid; always @(posedge clk or negedge rst) if(!rst) ep5_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h5)) ep5_dpid <= next_dpid; always @(posedge clk or negedge rst) if(!rst) ep6_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h6)) ep6_dpid <= next_dpid; always @(posedge clk or negedge rst) if(!rst) ep7_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h7)) ep7_dpid <= next_dpid; always @(posedge clk) case(ep_sel) 4'h0: uc_dpd <= ep0_dpid; 4'h1: uc_dpd <= ep1_dpid; 4'h2: uc_dpd <= ep2_dpid; 4'h3: uc_dpd <= ep3_dpid; 4'h4: uc_dpd <= ep4_dpid; 4'h5: uc_dpd <= ep5_dpid; 4'h6: uc_dpd <= ep6_dpid; 4'h7: uc_dpd <= ep7_dpid; endcase /////////////////////////////////////////////////////////////////// // // Data Pid Sequencer // assign tr_fr_d = 2'h0; always @(posedge clk) // tr/mf:ep/type:tr/type:last dpd casex({tr_fr_d,ep_type,txfr_type,uc_dpd}) // synopsys full_case parallel_case 8'b0?_01_01_??: next_dpid <= #1 2'b00; // ISO txfr. IN, 1 tr/mf 8'b10_01_01_?0: next_dpid <= #1 2'b01; // ISO txfr. IN, 2 tr/mf 8'b10_01_01_?1: next_dpid <= #1 2'b00; // ISO txfr. IN, 2 tr/mf 8'b11_01_01_00: next_dpid <= #1 2'b01; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_01: next_dpid <= #1 2'b10; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_10: next_dpid <= #1 2'b00; // ISO txfr. IN, 3 tr/mf 8'b0?_10_01_??: next_dpid <= #1 2'b00; // ISO txfr. OUT, 1 tr/mf 8'b10_10_01_??: // ISO txfr. OUT, 2 tr/mf begin // Resynchronize in case of PID error case({pid_MDATA, pid_DATA1}) // synopsys full_case parallel_case 2'b10: next_dpid <= #1 2'b01; 2'b01: next_dpid <= #1 2'b00; endcase end 8'b11_10_01_00: // ISO txfr. OUT, 3 tr/mf begin // Resynchronize in case of PID error case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case 2'b10: next_dpid <= #1 2'b01; 2'b01: next_dpid <= #1 2'b00; endcase end 8'b11_10_01_01: // ISO txfr. OUT, 3 tr/mf begin // Resynchronize in case of PID error case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case 2'b10: next_dpid <= #1 2'b10; 2'b01: next_dpid <= #1 2'b00; endcase end 8'b11_10_01_10: // ISO txfr. OUT, 3 tr/mf begin // Resynchronize in case of PID error case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case 2'b10: next_dpid <= #1 2'b01; 2'b01: next_dpid <= #1 2'b00; endcase end 8'b??_01_00_?0, // IN/OUT endpoint only 8'b??_10_00_?0: next_dpid <= #1 2'b01; // INT transfers 8'b??_01_00_?1, // IN/OUT endpoint only 8'b??_10_00_?1: next_dpid <= #1 2'b00; // INT transfers 8'b??_01_10_?0, // IN/OUT endpoint only 8'b??_10_10_?0: next_dpid <= #1 2'b01; // BULK transfers 8'b??_01_10_?1, // IN/OUT endpoint only 8'b??_10_10_?1: next_dpid <= #1 2'b00; // BULK transfers 8'b??_00_??_??: // CTRL Endpoint casex({setup_token, in_op, out_op, uc_dpd}) // synopsys full_case parallel_case 5'b1_??_??: next_dpid <= #1 2'b11; // SETUP operation 5'b0_10_0?: next_dpid <= #1 2'b11; // IN operation 5'b0_10_1?: next_dpid <= #1 2'b01; // IN operation 5'b0_01_?0: next_dpid <= #1 2'b11; // OUT operation 5'b0_01_?1: next_dpid <= #1 2'b10; // OUT operation endcase endcase // Current PID decoder // Allow any PID for ISO. transfers when mode full speed or tr_fr is zero always @(pid_DATA0 or pid_DATA1 or pid_DATA2 or pid_MDATA) case({pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA} ) // synopsys full_case parallel_case 4'b1000: allow_pid = 2'b00; 4'b0100: allow_pid = 2'b01; 4'b0010: allow_pid = 2'b10; 4'b0001: allow_pid = 2'b11; endcase always @(posedge clk) // tf/mf:ep/type:tr/type:last dpd casex({tr_fr_d,ep_type,txfr_type,uc_dpd}) // synopsys full_case parallel_case 8'b0?_01_01_??: this_dpid <= #1 2'b00; // ISO txfr. IN, 1 tr/mf 8'b10_01_01_?0: this_dpid <= #1 2'b01; // ISO txfr. IN, 2 tr/mf 8'b10_01_01_?1: this_dpid <= #1 2'b00; // ISO txfr. IN, 2 tr/mf 8'b11_01_01_00: this_dpid <= #1 2'b10; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_01: this_dpid <= #1 2'b01; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_10: this_dpid <= #1 2'b00; // ISO txfr. IN, 3 tr/mf 8'b00_10_01_??: this_dpid <= #1 allow_pid; // ISO txfr. OUT, 0 tr/mf 8'b01_10_01_??: this_dpid <= #1 2'b00; // ISO txfr. OUT, 1 tr/mf 8'b10_10_01_?0: this_dpid <= #1 2'b11; // ISO txfr. OUT, 2 tr/mf 8'b10_10_01_?1: this_dpid <= #1 2'b01; // ISO txfr. OUT, 2 tr/mf 8'b11_10_01_00: this_dpid <= #1 2'b11; // ISO txfr. OUT, 3 tr/mf 8'b11_10_01_01: this_dpid <= #1 2'b11; // ISO txfr. OUT, 3 tr/mf 8'b11_10_01_10: this_dpid <= #1 2'b10; // ISO txfr. OUT, 3 tr/mf 8'b??_01_00_?0, // IN/OUT endpoint only 8'b??_10_00_?0: this_dpid <= #1 2'b00; // INT transfers 8'b??_01_00_?1, // IN/OUT endpoint only 8'b??_10_00_?1: this_dpid <= #1 2'b01; // INT transfers 8'b??_01_10_?0, // IN/OUT endpoint only 8'b??_10_10_?0: this_dpid <= #1 2'b00; // BULK transfers 8'b??_01_10_?1, // IN/OUT endpoint only 8'b??_10_10_?1: this_dpid <= #1 2'b01; // BULK transfers 8'b??_00_??_??: // CTRL Endpoint casex({setup_token,in_op, out_op, uc_dpd}) // synopsys full_case parallel_case 5'b1_??_??: this_dpid <= #1 2'b00; // SETUP operation 5'b0_10_0?: this_dpid <= #1 2'b00; // IN operation 5'b0_10_1?: this_dpid <= #1 2'b01; // IN operation 5'b0_01_?0: this_dpid <= #1 2'b00; // OUT operation 5'b0_01_?1: this_dpid <= #1 2'b01; // OUT operation endcase endcase // Assign PID for outgoing packets assign data_pid_sel = this_dpid; // Verify PID for incoming data packets always @(posedge clk) pid_seq_err <= #1 !( (this_dpid==2'b00 & pid_DATA0) | (this_dpid==2'b01 & pid_DATA1) | (this_dpid==2'b10 & pid_DATA2) | (this_dpid==2'b11 & pid_MDATA) ); /////////////////////////////////////////////////////////////////// // // IDMA Setup & src/dst buffer select // // For Control endpoints things are different: // buffer0 is used for OUT (incoming) data packets // buffer1 is used for IN (outgoing) data packets // Keep track of last token for control endpoints always @(posedge clk or negedge rst) if(!rst) in_token <= #1 1'b0; else if(pid_IN) in_token <= #1 1'b1; else if(pid_OUT | pid_SETUP) in_token <= #1 1'b0; always @(posedge clk or negedge rst) if(!rst) out_token <= #1 1'b0; else if(pid_OUT | pid_SETUP) out_token <= #1 1'b1; else if(pid_IN) out_token <= #1 1'b0; always @(posedge clk or negedge rst) if(!rst) setup_token <= #1 1'b0; else if(pid_SETUP) setup_token <= #1 1'b1; else if(pid_OUT | pid_IN) setup_token <= #1 1'b0; // Indicates if we are performing an IN operation assign in_op = IN_ep | (CTRL_ep & in_token); // Indicates if we are performing an OUT operation assign out_op = OUT_ep | (CTRL_ep & out_token); /////////////////////////////////////////////////////////////////// // // Determine if packet is to small or to large // This is used to NACK and ignore packet for OUT endpoints // /////////////////////////////////////////////////////////////////// // // Register File Update Logic // always @(posedge clk) uc_dpd_set <= #1 uc_stat_set_d; // Abort signal always @(posedge clk) abort <= #1 match & fsel & (state != IDLE); /////////////////////////////////////////////////////////////////// // // TIME OUT TIMERS // // After sending Data in response to an IN token from host, the // host must reply with an ack. The host has 622nS in Full Speed // mode and 400nS in High Speed mode to reply. // "rx_ack_to" indicates when this time has expired. // rx_ack_to_clr, clears the timer always @(posedge clk) rx_ack_to_clr <= #1 tx_valid | rx_ack_to_clr_d; always @(posedge clk) if(rx_ack_to_clr) rx_ack_to_cnt <= #1 8'h0; else rx_ack_to_cnt <= #1 rx_ack_to_cnt + 8'h1; always @(posedge clk) rx_ack_to <= #1 (rx_ack_to_cnt == rx_ack_to_val); assign rx_ack_to_val = `USBF_RX_ACK_TO_VAL_FS; // After sending a OUT token the host must send a data packet. // The host has 622nS in Full Speed mode and 400nS in High Speed // mode to send the data packet. // "tx_data_to" indicates when this time has expired. // "tx_data_to_clr" clears the timer assign tx_data_to_clr = rx_active; always @(posedge clk) if(tx_data_to_clr) tx_data_to_cnt <= #1 8'h0; else tx_data_to_cnt <= #1 tx_data_to_cnt + 8'h1; always @(posedge clk) tx_data_to <= #1 (tx_data_to_cnt == tx_data_to_val); assign tx_data_to_val = `USBF_TX_DATA_TO_VAL_FS; /////////////////////////////////////////////////////////////////// // // Interrupts // reg pid_OUT_r, pid_IN_r, pid_PING_r, pid_SETUP_r; always @(posedge clk) pid_OUT_r <= #1 pid_OUT; always @(posedge clk) pid_IN_r <= #1 pid_IN; always @(posedge clk) pid_PING_r <= #1 pid_PING; always @(posedge clk) pid_SETUP_r <= #1 pid_SETUP; always @(posedge clk) int_upid_set <= #1 match_r & !pid_SOF & ( ( OUT_ep & !(pid_OUT_r | pid_PING_r)) | ( IN_ep & !pid_IN_r) | (CTRL_ep & !(pid_IN_r | pid_OUT_r | pid_PING_r | pid_SETUP_r)) ); assign int_to_set = ((state == IN2) & rx_ack_to) | ((state == OUT) & tx_data_to); assign int_crc16_set = rx_data_done & crc16_err; always @(posedge clk) int_seqerr_set <= #1 int_seqerr_set_d; reg send_stall_r; always @(posedge clk or negedge rst) if(!rst) send_stall_r <= #1 1'b0; else if(send_stall) send_stall_r <= #1 1'b1; else if(send_token) send_stall_r <= #1 1'b0; /////////////////////////////////////////////////////////////////// // // Main Protocol State Machine // always @(posedge clk or negedge rst) if(!rst) state <= #1 IDLE; else if(match) state <= #1 IDLE; else state <= #1 next_state; always @(state or pid_seq_err or idma_done or ep_full or ep_empty or token_valid or pid_ACK or rx_data_done or tx_data_to or crc16_err or rx_ack_to or pid_PING or txfr_iso or txfr_int or CTRL_ep or pid_IN or pid_OUT or IN_ep or OUT_ep or pid_SETUP or pid_SOF or match_r or abort or send_stall_r ) begin next_state = state; token_pid_sel_d = ACK; send_token_d = 1'b0; rx_dma_en = 1'b0; tx_dma_en = 1'b0; uc_stat_set_d = 1'b0; rx_ack_to_clr_d = 1'b1; int_seqerr_set_d = 1'b0; case(state) // synopsys full_case parallel_case IDLE: begin // synopsys translate_off `ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state IDLE (%t)", $time); `endif `ifdef USBF_DEBUG if(rst & match_r & !pid_SOF) begin if(match_r === 1'bx) $display("ERROR: IDLE: match_r is unknown. (%t)", $time); if(pid_SOF === 1'bx) $display("ERROR: IDLE: pid_SOF is unknown. (%t)", $time); if(CTRL_ep === 1'bx) $display("ERROR: IDLE: CTRL_ep is unknown. (%t)", $time); if(pid_IN === 1'bx) $display("ERROR: IDLE: pid_IN is unknown. (%t)", $time); if(pid_OUT === 1'bx) $display("ERROR: IDLE: pid_OUT is unknown. (%t)", $time); if(pid_SETUP === 1'bx) $display("ERROR: IDLE: pid_SETUP is unknown. (%t)", $time); if(pid_PING === 1'bx) $display("ERROR: IDLE: pid_PING is unknown. (%t)", $time); if(IN_ep === 1'bx) $display("ERROR: IDLE: IN_ep is unknown. (%t)", $time); if(OUT_ep === 1'bx) $display("ERROR: IDLE: OUT_ep is unknown. (%t)", $time); end `endif // synopsys translate_on if(match_r & !pid_SOF) begin /* if(ep_stall) // Halt Forced send STALL begin token_pid_sel_d = STALL; send_token_d = 1'b1; next_state = TOKEN; end else */ if(IN_ep | (CTRL_ep & pid_IN)) begin if(txfr_int & ep_empty) begin token_pid_sel_d = NACK; send_token_d = 1'b1; next_state = TOKEN; end else begin tx_dma_en = 1'b1; next_state = IN; end end else if(OUT_ep | (CTRL_ep & (pid_OUT | pid_SETUP))) begin rx_dma_en = 1'b1; next_state = OUT; end end end TOKEN: begin // synopsys translate_off `ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state TOKEN (%t)", $time); `endif // synopsys translate_on next_state = IDLE; end IN: begin // synopsys translate_off `ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state IN (%t)", $time); `endif `ifdef USBF_DEBUG if(idma_done === 1'bx) $display("ERROR: IN: idma_done is unknown. (%t)", $time); if(txfr_iso === 1'bx) $display("ERROR: IN: txfr_iso is unknown. (%t)", $time); `endif // synopsys translate_on rx_ack_to_clr_d = 1'b0; if(idma_done) begin if(txfr_iso) next_state = UPDATE; else next_state = IN2; end end IN2: begin // synopsys translate_off `ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state IN2 (%t)", $time); `endif `ifdef USBF_DEBUG if(rx_ack_to === 1'bx) $display("ERROR: IN2: rx_ack_to is unknown. (%t)", $time); if(token_valid === 1'bx)$display("ERROR: IN2: token_valid is unknown. (%t)", $time); if(pid_ACK === 1'bx) $display("ERROR: IN2: pid_ACK is unknown. (%t)", $time); `endif // synopsys translate_on rx_ack_to_clr_d = 1'b0; // Wait for ACK from HOST or Timeout if(rx_ack_to) next_state = IDLE; else if(token_valid & pid_ACK) begin next_state = UPDATE; end end OUT: begin // synopsys translate_off `ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state OUT (%t)", $time); `endif `ifdef USBF_DEBUG if(tx_data_to === 1'bx) $display("ERROR: OUT: tx_data_to is unknown. (%t)", $time); if(crc16_err === 1'bx) $display("ERROR: OUT: crc16_err is unknown. (%t)", $time); if(abort === 1'bx) $display("ERROR: OUT: abort is unknown. (%t)", $time); if(rx_data_done === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); if(txfr_iso === 1'bx) $display("ERROR: OUT: txfr_iso is unknown. (%t)", $time); if(pid_seq_err === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); `endif // synopsys translate_on if(tx_data_to | crc16_err | abort ) next_state = IDLE; else if(rx_data_done) begin // Send Ack if(txfr_iso) begin if(pid_seq_err) int_seqerr_set_d = 1'b1; next_state = UPDATEW; end else next_state = OUT2A; end end OUT2B: begin // This is a delay State to NACK to small or to // large packets. this state could be skipped // synopsys translate_off `ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state OUT2B (%t)", $time); `endif `ifdef USBF_DEBUG if(abort === 1'bx) $display("ERROR: OUT2A: abort is unknown. (%t)", $time); `endif // synopsys translate_on if(abort) next_state = IDLE; else next_state = OUT2B; end OUT2A: begin // Send ACK/NACK/NYET // synopsys translate_off `ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state OUT2A (%t)", $time); `endif `ifdef USBF_DEBUG if(abort === 1'bx) $display("ERROR: OUT2A: abort is unknown. (%t)", $time); if(pid_seq_err === 1'bx)$display("ERROR: OUT2A: rx_data_done is unknown. (%t)", $time); `endif // synopsys translate_on if(abort) next_state = IDLE; else if(send_stall_r) begin token_pid_sel_d = STALL; send_token_d = 1'b1; next_state = IDLE; end else if(ep_full) begin token_pid_sel_d = NACK; send_token_d = 1'b1; next_state = IDLE; end else begin token_pid_sel_d = ACK; send_token_d = 1'b1; if(pid_seq_err) next_state = IDLE; else next_state = UPDATE; end end UPDATEW: begin // synopsys translate_off `ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state UPDATEW (%t)", $time); `endif // synopsys translate_on next_state = UPDATE; end UPDATE: begin // synopsys translate_off `ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state UPDATE (%t)", $time); `endif // synopsys translate_on uc_stat_set_d = 1'b1; next_state = IDLE; end endcase end endmodule