URL
https://opencores.org/ocsvn/usb_device_core/usb_device_core/trunk
Subversion Repositories usb_device_core
[/] [usb_device_core/] [trunk/] [src_v/] [usbf_device_core.v] - Rev 5
Compare with Previous | Blame | View Log
//----------------------------------------------------------------- // USB Device Core // V1.0 // Ultra-Embedded.com // Copyright 2014-2019 // // Email: admin@ultra-embedded.com // // License: GPL // If you would like a version with a more permissive license for // use in closed source commercial applications please contact me // for details. //----------------------------------------------------------------- // // This file is open source HDL; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of // the License, or (at your option) any later version. // // This file 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 General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this file; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA //----------------------------------------------------------------- //----------------------------------------------------------------- // Generated File //----------------------------------------------------------------- module usbf_device_core ( // Inputs input clk_i ,input rst_i ,input [ 7:0] utmi_data_i ,input utmi_txready_i ,input utmi_rxvalid_i ,input utmi_rxactive_i ,input utmi_rxerror_i ,input [ 1:0] utmi_linestate_i ,input ep0_stall_i ,input ep0_iso_i ,input ep0_cfg_int_rx_i ,input ep0_cfg_int_tx_i ,input ep0_rx_space_i ,input ep0_tx_ready_i ,input ep0_tx_data_valid_i ,input ep0_tx_data_strb_i ,input [ 7:0] ep0_tx_data_i ,input ep0_tx_data_last_i ,input ep1_stall_i ,input ep1_iso_i ,input ep1_cfg_int_rx_i ,input ep1_cfg_int_tx_i ,input ep1_rx_space_i ,input ep1_tx_ready_i ,input ep1_tx_data_valid_i ,input ep1_tx_data_strb_i ,input [ 7:0] ep1_tx_data_i ,input ep1_tx_data_last_i ,input ep2_stall_i ,input ep2_iso_i ,input ep2_cfg_int_rx_i ,input ep2_cfg_int_tx_i ,input ep2_rx_space_i ,input ep2_tx_ready_i ,input ep2_tx_data_valid_i ,input ep2_tx_data_strb_i ,input [ 7:0] ep2_tx_data_i ,input ep2_tx_data_last_i ,input ep3_stall_i ,input ep3_iso_i ,input ep3_cfg_int_rx_i ,input ep3_cfg_int_tx_i ,input ep3_rx_space_i ,input ep3_tx_ready_i ,input ep3_tx_data_valid_i ,input ep3_tx_data_strb_i ,input [ 7:0] ep3_tx_data_i ,input ep3_tx_data_last_i ,input reg_chirp_en_i ,input reg_int_en_sof_i ,input reg_sts_rst_clr_i ,input [ 6:0] reg_dev_addr_i // Outputs ,output intr_o ,output [ 7:0] utmi_data_o ,output utmi_txvalid_o ,output rx_strb_o ,output [ 7:0] rx_data_o ,output rx_last_o ,output rx_crc_err_o ,output ep0_rx_setup_o ,output ep0_rx_valid_o ,output ep0_tx_data_accept_o ,output ep1_rx_setup_o ,output ep1_rx_valid_o ,output ep1_tx_data_accept_o ,output ep2_rx_setup_o ,output ep2_rx_valid_o ,output ep2_tx_data_accept_o ,output ep3_rx_setup_o ,output ep3_rx_valid_o ,output ep3_tx_data_accept_o ,output reg_sts_rst_o ,output [ 10:0] reg_sts_frame_num_o ); //----------------------------------------------------------------- // Defines: //----------------------------------------------------------------- `include "usbf_defs.v" `define USB_RESET_CNT_W 15 localparam STATE_W = 3; localparam STATE_RX_IDLE = 3'd0; localparam STATE_RX_DATA = 3'd1; localparam STATE_RX_DATA_READY = 3'd2; localparam STATE_RX_DATA_IGNORE = 3'd3; localparam STATE_TX_DATA = 3'd4; localparam STATE_TX_DATA_COMPLETE = 3'd5; localparam STATE_TX_HANDSHAKE = 3'd6; localparam STATE_TX_CHIRP = 3'd7; reg [STATE_W-1:0] state_q; //----------------------------------------------------------------- // Reset detection //----------------------------------------------------------------- reg [`USB_RESET_CNT_W-1:0] se0_cnt_q; always @ (posedge clk_i or posedge rst_i) if (rst_i) se0_cnt_q <= `USB_RESET_CNT_W'b0; else if (utmi_linestate_i == 2'b0) begin if (!se0_cnt_q[`USB_RESET_CNT_W-1]) se0_cnt_q <= se0_cnt_q + `USB_RESET_CNT_W'd1; end else se0_cnt_q <= `USB_RESET_CNT_W'b0; wire usb_rst_w = se0_cnt_q[`USB_RESET_CNT_W-1]; //----------------------------------------------------------------- // Wire / Regs //----------------------------------------------------------------- `define USB_FRAME_W 11 wire [`USB_FRAME_W-1:0] frame_num_w; wire frame_valid_w; `define USB_DEV_W 7 wire [`USB_DEV_W-1:0] token_dev_w; `define USB_EP_W 4 wire [`USB_EP_W-1:0] token_ep_w; `define USB_PID_W 8 wire [`USB_PID_W-1:0] token_pid_w; wire token_valid_w; wire rx_data_valid_w; wire rx_data_complete_w; wire rx_handshake_w; reg tx_data_valid_r; reg tx_data_strb_r; reg [7:0] tx_data_r; reg tx_data_last_r; wire tx_data_accept_w; reg tx_valid_q; reg [7:0] tx_pid_q; wire tx_accept_w; reg rx_space_q; reg rx_space_r; reg tx_ready_r; reg ep_data_bit_r; reg ep_stall_r; reg ep_iso_r; reg rx_enable_q; reg rx_setup_q; reg ep0_data_bit_q; reg ep1_data_bit_q; reg ep2_data_bit_q; reg ep3_data_bit_q; wire status_stage_w; reg [`USB_DEV_W-1:0] current_addr_q; //----------------------------------------------------------------- // SIE - TX //----------------------------------------------------------------- usbf_sie_tx u_sie_tx ( .clk_i(clk_i), .rst_i(rst_i), .enable_i(~usb_rst_w), .chirp_i(reg_chirp_en_i), // UTMI Interface .utmi_data_o(utmi_data_o), .utmi_txvalid_o(utmi_txvalid_o), .utmi_txready_i(utmi_txready_i), // Request .tx_valid_i(tx_valid_q), .tx_pid_i(tx_pid_q), .tx_accept_o(tx_accept_w), // Data .data_valid_i(tx_data_valid_r), .data_strb_i(tx_data_strb_r), .data_i(tx_data_r), .data_last_i(tx_data_last_r), .data_accept_o(tx_data_accept_w) ); always @ * begin tx_data_valid_r = 1'b0; tx_data_strb_r = 1'b0; tx_data_r = 8'b0; tx_data_last_r = 1'b0; case (token_ep_w) 4'd0: begin tx_data_valid_r = ep0_tx_data_valid_i; tx_data_strb_r = ep0_tx_data_strb_i; tx_data_r = ep0_tx_data_i; tx_data_last_r = ep0_tx_data_last_i; end 4'd1: begin tx_data_valid_r = ep1_tx_data_valid_i; tx_data_strb_r = ep1_tx_data_strb_i; tx_data_r = ep1_tx_data_i; tx_data_last_r = ep1_tx_data_last_i; end 4'd2: begin tx_data_valid_r = ep2_tx_data_valid_i; tx_data_strb_r = ep2_tx_data_strb_i; tx_data_r = ep2_tx_data_i; tx_data_last_r = ep2_tx_data_last_i; end 4'd3: begin tx_data_valid_r = ep3_tx_data_valid_i; tx_data_strb_r = ep3_tx_data_strb_i; tx_data_r = ep3_tx_data_i; tx_data_last_r = ep3_tx_data_last_i; end default: ; endcase end assign ep0_tx_data_accept_o = tx_data_accept_w & (token_ep_w == 4'd0); assign ep1_tx_data_accept_o = tx_data_accept_w & (token_ep_w == 4'd1); assign ep2_tx_data_accept_o = tx_data_accept_w & (token_ep_w == 4'd2); assign ep3_tx_data_accept_o = tx_data_accept_w & (token_ep_w == 4'd3); always @ * begin rx_space_r = 1'b0; tx_ready_r = 1'b0; ep_data_bit_r = 1'b0; ep_stall_r = 1'b0; ep_iso_r = 1'b0; case (token_ep_w) 4'd0: begin rx_space_r = ep0_rx_space_i; tx_ready_r = ep0_tx_ready_i; ep_data_bit_r = ep0_data_bit_q | status_stage_w; ep_stall_r = ep0_stall_i; ep_iso_r = ep0_iso_i; end 4'd1: begin rx_space_r = ep1_rx_space_i; tx_ready_r = ep1_tx_ready_i; ep_data_bit_r = ep1_data_bit_q | status_stage_w; ep_stall_r = ep1_stall_i; ep_iso_r = ep1_iso_i; end 4'd2: begin rx_space_r = ep2_rx_space_i; tx_ready_r = ep2_tx_ready_i; ep_data_bit_r = ep2_data_bit_q | status_stage_w; ep_stall_r = ep2_stall_i; ep_iso_r = ep2_iso_i; end 4'd3: begin rx_space_r = ep3_rx_space_i; tx_ready_r = ep3_tx_ready_i; ep_data_bit_r = ep3_data_bit_q | status_stage_w; ep_stall_r = ep3_stall_i; ep_iso_r = ep3_iso_i; end default: ; endcase end always @ (posedge clk_i or posedge rst_i) if (rst_i) rx_space_q <= 1'b0; else if (state_q == STATE_RX_IDLE) rx_space_q <= rx_space_r; //----------------------------------------------------------------- // SIE - RX //----------------------------------------------------------------- usbf_sie_rx u_sie_rx ( .clk_i(clk_i), .rst_i(rst_i), .enable_i(~usb_rst_w && ~reg_chirp_en_i), // UTMI Interface .utmi_data_i(utmi_data_i), .utmi_rxvalid_i(utmi_rxvalid_i), .utmi_rxactive_i(utmi_rxactive_i), .current_addr_i(current_addr_q), .pid_o(token_pid_w), .frame_valid_o(frame_valid_w), .frame_number_o(reg_sts_frame_num_o), .token_valid_o(token_valid_w), .token_addr_o(token_dev_w), .token_ep_o(token_ep_w), .token_crc_err_o(), .handshake_valid_o(rx_handshake_w), .data_valid_o(rx_data_valid_w), .data_strb_o(rx_strb_o), .data_o(rx_data_o), .data_last_o(rx_last_o), .data_complete_o(rx_data_complete_w), .data_crc_err_o(rx_crc_err_o) ); assign ep0_rx_valid_o = rx_enable_q & rx_data_valid_w & (token_ep_w == 4'd0); assign ep0_rx_setup_o = rx_setup_q & (token_ep_w == 4'd0); assign ep1_rx_valid_o = rx_enable_q & rx_data_valid_w & (token_ep_w == 4'd1); assign ep1_rx_setup_o = rx_setup_q & (token_ep_w == 4'd0); assign ep2_rx_valid_o = rx_enable_q & rx_data_valid_w & (token_ep_w == 4'd2); assign ep2_rx_setup_o = rx_setup_q & (token_ep_w == 4'd0); assign ep3_rx_valid_o = rx_enable_q & rx_data_valid_w & (token_ep_w == 4'd3); assign ep3_rx_setup_o = rx_setup_q & (token_ep_w == 4'd0); //----------------------------------------------------------------- // Next state //----------------------------------------------------------------- reg [STATE_W-1:0] next_state_r; always @ * begin next_state_r = state_q; //----------------------------------------- // State Machine //----------------------------------------- case (state_q) //----------------------------------------- // IDLE //----------------------------------------- STATE_RX_IDLE : begin // Token received (OUT, IN, SETUP, PING) if (token_valid_w) begin //------------------------------- // IN transfer (device -> host) //------------------------------- if (token_pid_w == `PID_IN) begin // Stalled endpoint? if (ep_stall_r) next_state_r = STATE_TX_HANDSHAKE; // Some data to TX? else if (tx_ready_r) next_state_r = STATE_TX_DATA; // No data to TX else next_state_r = STATE_TX_HANDSHAKE; end //------------------------------- // PING transfer (device -> host) //------------------------------- else if (token_pid_w == `PID_PING) begin next_state_r = STATE_TX_HANDSHAKE; end //------------------------------- // OUT transfer (host -> device) //------------------------------- else if (token_pid_w == `PID_OUT) begin // Stalled endpoint? if (ep_stall_r) next_state_r = STATE_RX_DATA_IGNORE; // Some space to rx else if (rx_space_r) next_state_r = STATE_RX_DATA; // No rx space, ignore receive else next_state_r = STATE_RX_DATA_IGNORE; end //------------------------------- // SETUP transfer (host -> device) //------------------------------- else if (token_pid_w == `PID_SETUP) begin // Some space to rx if (rx_space_r) next_state_r = STATE_RX_DATA; // No rx space, ignore receive else next_state_r = STATE_RX_DATA_IGNORE; end end else if (reg_chirp_en_i) next_state_r = STATE_TX_CHIRP; end //----------------------------------------- // RX_DATA //----------------------------------------- STATE_RX_DATA : begin // TODO: Exit data state handling? // TODO: Sort out ISO data bit handling // Check for expected DATAx PID if ((token_pid_w == `PID_DATA0 && ep_data_bit_r && !ep_iso_r) || (token_pid_w == `PID_DATA1 && !ep_data_bit_r && !ep_iso_r)) next_state_r = STATE_RX_DATA_IGNORE; // Receive complete else if (rx_data_valid_w && rx_last_o) next_state_r = STATE_RX_DATA_READY; end //----------------------------------------- // RX_DATA_IGNORE //----------------------------------------- STATE_RX_DATA_IGNORE : begin // Receive complete if (rx_data_valid_w && rx_last_o) next_state_r = STATE_RX_DATA_READY; end //----------------------------------------- // RX_DATA_READY //----------------------------------------- STATE_RX_DATA_READY : begin if (rx_data_complete_w) begin // No response on CRC16 error if (rx_crc_err_o) next_state_r = STATE_RX_IDLE; // ISO endpoint, no response? else if (ep_iso_r) next_state_r = STATE_RX_IDLE; else next_state_r = STATE_TX_HANDSHAKE; end end //----------------------------------------- // TX_DATA //----------------------------------------- STATE_TX_DATA : begin if (!tx_valid_q || tx_accept_w) if (tx_data_valid_r && tx_data_last_r && tx_data_accept_w) next_state_r = STATE_TX_DATA_COMPLETE; end //----------------------------------------- // TX_HANDSHAKE //----------------------------------------- STATE_TX_DATA_COMPLETE : begin next_state_r = STATE_RX_IDLE; end //----------------------------------------- // TX_HANDSHAKE //----------------------------------------- STATE_TX_HANDSHAKE : begin if (tx_accept_w) next_state_r = STATE_RX_IDLE; end //----------------------------------------- // TX_CHIRP //----------------------------------------- STATE_TX_CHIRP : begin if (!reg_chirp_en_i) next_state_r = STATE_RX_IDLE; end default : ; endcase //----------------------------------------- // USB Bus Reset (HOST->DEVICE) //----------------------------------------- if (usb_rst_w && !reg_chirp_en_i) next_state_r = STATE_RX_IDLE; end // Update state always @ (posedge clk_i or posedge rst_i) if (rst_i) state_q <= STATE_RX_IDLE; else state_q <= next_state_r; //----------------------------------------------------------------- // Response //----------------------------------------------------------------- reg tx_valid_r; reg [7:0] tx_pid_r; always @ * begin tx_valid_r = 1'b0; tx_pid_r = 8'b0; case (state_q) //----------------------------------------- // IDLE //----------------------------------------- STATE_RX_IDLE : begin // Token received (OUT, IN, SETUP, PING) if (token_valid_w) begin //------------------------------- // IN transfer (device -> host) //------------------------------- if (token_pid_w == `PID_IN) begin // Stalled endpoint? if (ep_stall_r) begin tx_valid_r = 1'b1; tx_pid_r = `PID_STALL; end // Some data to TX? else if (tx_ready_r) begin tx_valid_r = 1'b1; // TODO: Handle MDATA for ISOs tx_pid_r = ep_data_bit_r ? `PID_DATA1 : `PID_DATA0; end // No data to TX else begin tx_valid_r = 1'b1; tx_pid_r = `PID_NAK; end end //------------------------------- // PING transfer (device -> host) //------------------------------- else if (token_pid_w == `PID_PING) begin // Stalled endpoint? if (ep_stall_r) begin tx_valid_r = 1'b1; tx_pid_r = `PID_STALL; end // Data ready to RX else if (rx_space_r) begin tx_valid_r = 1'b1; tx_pid_r = `PID_ACK; end // No data to TX else begin tx_valid_r = 1'b1; tx_pid_r = `PID_NAK; end end end end //----------------------------------------- // RX_DATA_READY //----------------------------------------- STATE_RX_DATA_READY : begin // Receive complete if (rx_data_complete_w) begin // No response on CRC16 error if (rx_crc_err_o) ; // ISO endpoint, no response? else if (ep_iso_r) ; // Send STALL? else if (ep_stall_r) begin tx_valid_r = 1'b1; tx_pid_r = `PID_STALL; end // DATAx bit mismatch else if ( (token_pid_w == `PID_DATA0 && ep_data_bit_r) || (token_pid_w == `PID_DATA1 && !ep_data_bit_r) ) begin // Ack transfer to resync tx_valid_r = 1'b1; tx_pid_r = `PID_ACK; end // Send NAK else if (!rx_space_q) begin tx_valid_r = 1'b1; tx_pid_r = `PID_NAK; end // TODO: USB 2.0, no more buffer space, return NYET else begin tx_valid_r = 1'b1; tx_pid_r = `PID_ACK; end end end //----------------------------------------- // TX_CHIRP //----------------------------------------- STATE_TX_CHIRP : begin tx_valid_r = 1'b1; tx_pid_r = 8'b0; end default : ; endcase end always @ (posedge clk_i or posedge rst_i) if (rst_i) tx_valid_q <= 1'b0; else if (!tx_valid_q || tx_accept_w) tx_valid_q <= tx_valid_r; always @ (posedge clk_i or posedge rst_i) if (rst_i) tx_pid_q <= 8'b0; else if (!tx_valid_q || tx_accept_w) tx_pid_q <= tx_pid_r; //----------------------------------------------------------------- // Receive enable //----------------------------------------------------------------- always @ (posedge clk_i or posedge rst_i) if (rst_i) rx_enable_q <= 1'b0; else if (usb_rst_w ||reg_chirp_en_i) rx_enable_q <= 1'b0; else rx_enable_q <= (state_q == STATE_RX_DATA); //----------------------------------------------------------------- // Receive SETUP: Pulse on SETUP packet receive //----------------------------------------------------------------- always @ (posedge clk_i or posedge rst_i) if (rst_i) rx_setup_q <= 1'b0; else if (usb_rst_w ||reg_chirp_en_i) rx_setup_q <= 1'b0; else if ((state_q == STATE_RX_IDLE) && token_valid_w && (token_pid_w == `PID_SETUP) && (token_ep_w == 4'd0)) rx_setup_q <= 1'b1; else rx_setup_q <= 1'b0; //----------------------------------------------------------------- // Set Address //----------------------------------------------------------------- reg addr_update_pending_q; wire ep0_tx_zlp_w = ep0_tx_data_valid_i && (ep0_tx_data_strb_i == 1'b0) && ep0_tx_data_last_i && ep0_tx_data_accept_o; always @ (posedge clk_i or posedge rst_i) if (rst_i) addr_update_pending_q <= 1'b0; else if (ep0_tx_zlp_w || usb_rst_w) addr_update_pending_q <= 1'b0; // TODO: Use write strobe else if (reg_dev_addr_i != current_addr_q) addr_update_pending_q <= 1'b1; always @ (posedge clk_i or posedge rst_i) if (rst_i) current_addr_q <= `USB_DEV_W'b0; else if (usb_rst_w) current_addr_q <= `USB_DEV_W'b0; else if (ep0_tx_zlp_w && addr_update_pending_q) current_addr_q <= reg_dev_addr_i; //----------------------------------------------------------------- // SETUP request tracking //----------------------------------------------------------------- reg ep0_dir_in_q; reg ep0_dir_out_q; always @ (posedge clk_i or posedge rst_i) if (rst_i) ep0_dir_in_q <= 1'b0; else if (usb_rst_w ||reg_chirp_en_i) ep0_dir_in_q <= 1'b0; else if ((state_q == STATE_RX_IDLE) && token_valid_w && (token_pid_w == `PID_SETUP) && (token_ep_w == 4'd0)) ep0_dir_in_q <= 1'b0; else if ((state_q == STATE_RX_IDLE) && token_valid_w && (token_pid_w == `PID_IN) && (token_ep_w == 4'd0)) ep0_dir_in_q <= 1'b1; always @ (posedge clk_i or posedge rst_i) if (rst_i) ep0_dir_out_q <= 1'b0; else if (usb_rst_w ||reg_chirp_en_i) ep0_dir_out_q <= 1'b0; else if ((state_q == STATE_RX_IDLE) && token_valid_w && (token_pid_w == `PID_SETUP) && (token_ep_w == 4'd0)) ep0_dir_out_q <= 1'b0; else if ((state_q == STATE_RX_IDLE) && token_valid_w && (token_pid_w == `PID_OUT) && (token_ep_w == 4'd0)) ep0_dir_out_q <= 1'b1; assign status_stage_w = ep0_dir_in_q && ep0_dir_out_q && (token_ep_w == 4'd0); //----------------------------------------------------------------- // Endpoint data bit toggle //----------------------------------------------------------------- reg new_data_bit_r; always @ * begin new_data_bit_r = ep_data_bit_r; case (state_q) //----------------------------------------- // RX_DATA_READY //----------------------------------------- STATE_RX_DATA_READY : begin // Receive complete if (rx_data_complete_w) begin // No toggle on CRC16 error if (rx_crc_err_o) ; // ISO endpoint, no response? else if (ep_iso_r) ; // TODO: HS handling // STALL? else if (ep_stall_r) ; // DATAx bit mismatch else if ( (token_pid_w == `PID_DATA0 && ep_data_bit_r) || (token_pid_w == `PID_DATA1 && !ep_data_bit_r) ) ; // NAKd else if (!rx_space_q) ; // Data accepted - toggle data bit else new_data_bit_r = !ep_data_bit_r; end end //----------------------------------------- // RX_IDLE //----------------------------------------- STATE_RX_IDLE : begin // Token received (OUT, IN, SETUP, PING) if (token_valid_w) begin // SETUP packets always start with DATA0 if (token_pid_w == `PID_SETUP) new_data_bit_r = 1'b0; end // ACK received else if (rx_handshake_w && token_pid_w == `PID_ACK) begin new_data_bit_r = !ep_data_bit_r; end end default: ; endcase end always @ (posedge clk_i or posedge rst_i) if (rst_i) ep0_data_bit_q <= 1'b0; else if (usb_rst_w) ep0_data_bit_q <= 1'b0; else if (token_ep_w == 4'd0) ep0_data_bit_q <= new_data_bit_r; always @ (posedge clk_i or posedge rst_i) if (rst_i) ep1_data_bit_q <= 1'b0; else if (usb_rst_w) ep1_data_bit_q <= 1'b0; else if (token_ep_w == 4'd1) ep1_data_bit_q <= new_data_bit_r; always @ (posedge clk_i or posedge rst_i) if (rst_i) ep2_data_bit_q <= 1'b0; else if (usb_rst_w) ep2_data_bit_q <= 1'b0; else if (token_ep_w == 4'd2) ep2_data_bit_q <= new_data_bit_r; always @ (posedge clk_i or posedge rst_i) if (rst_i) ep3_data_bit_q <= 1'b0; else if (usb_rst_w) ep3_data_bit_q <= 1'b0; else if (token_ep_w == 4'd3) ep3_data_bit_q <= new_data_bit_r; //----------------------------------------------------------------- // Reset event //----------------------------------------------------------------- reg rst_event_q; always @ (posedge clk_i or posedge rst_i) if (rst_i) rst_event_q <= 1'b0; else if (usb_rst_w) rst_event_q <= 1'b1; else if (reg_sts_rst_clr_i) rst_event_q <= 1'b0; assign reg_sts_rst_o = rst_event_q; //----------------------------------------------------------------- // Interrupts //----------------------------------------------------------------- reg intr_q; reg cfg_int_rx_r; reg cfg_int_tx_r; always @ * begin cfg_int_rx_r = 1'b0; cfg_int_tx_r = 1'b0; case (token_ep_w) 4'd0: begin cfg_int_rx_r = ep0_cfg_int_rx_i; cfg_int_tx_r = ep0_cfg_int_tx_i; end 4'd1: begin cfg_int_rx_r = ep1_cfg_int_rx_i; cfg_int_tx_r = ep1_cfg_int_tx_i; end 4'd2: begin cfg_int_rx_r = ep2_cfg_int_rx_i; cfg_int_tx_r = ep2_cfg_int_tx_i; end 4'd3: begin cfg_int_rx_r = ep3_cfg_int_rx_i; cfg_int_tx_r = ep3_cfg_int_tx_i; end default: ; endcase end always @ (posedge clk_i or posedge rst_i) if (rst_i) intr_q <= 1'b0; // SOF else if (frame_valid_w && reg_int_en_sof_i) intr_q <= 1'b1; // Reset event else if (!rst_event_q && usb_rst_w) intr_q <= 1'b1; // Rx ready else if (state_q == STATE_RX_DATA_READY && rx_space_q && cfg_int_rx_r) intr_q <= 1'b1; // Tx complete else if (state_q == STATE_TX_DATA_COMPLETE && cfg_int_tx_r) intr_q <= 1'b1; else intr_q <= 1'b0; assign intr_o = intr_q; //------------------------------------------------------------------- // Debug //------------------------------------------------------------------- `ifdef verilator /* verilator lint_off WIDTH */ reg [79:0] dbg_state; always @ * begin dbg_state = "-"; case (state_q) STATE_RX_IDLE: dbg_state = "IDLE"; STATE_RX_DATA: dbg_state = "RX_DATA"; STATE_RX_DATA_READY: dbg_state = "RX_DATA_READY"; STATE_RX_DATA_IGNORE: dbg_state = "RX_IGNORE"; STATE_TX_DATA: dbg_state = "TX_DATA"; STATE_TX_DATA_COMPLETE: dbg_state = "TX_DATA_COMPLETE"; STATE_TX_HANDSHAKE: dbg_state = "TX_HANDSHAKE"; STATE_TX_CHIRP: dbg_state = "CHIRP"; endcase end reg [79:0] dbg_pid; reg [7:0] dbg_pid_r; always @ * begin dbg_pid = "-"; if (tx_valid_q && tx_accept_w) dbg_pid_r = tx_pid_q; else if (token_valid_w || rx_handshake_w || rx_data_valid_w) dbg_pid_r = token_pid_w; else dbg_pid_r = 8'b0; case (dbg_pid_r) // Token `PID_OUT: dbg_pid = "OUT"; `PID_IN: dbg_pid = "IN"; `PID_SOF: dbg_pid = "SOF"; `PID_SETUP: dbg_pid = "SETUP"; `PID_PING: dbg_pid = "PING"; // Data `PID_DATA0: dbg_pid = "DATA0"; `PID_DATA1: dbg_pid = "DATA1"; `PID_DATA2: dbg_pid = "DATA2"; `PID_MDATA: dbg_pid = "MDATA"; // Handshake `PID_ACK: dbg_pid = "ACK"; `PID_NAK: dbg_pid = "NAK"; `PID_STALL: dbg_pid = "STALL"; `PID_NYET: dbg_pid = "NYET"; // Special `PID_PRE: dbg_pid = "PRE/ERR"; `PID_SPLIT: dbg_pid = "SPLIT"; default: ; endcase end /* verilator lint_on WIDTH */ `endif endmodule