| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 | //-----------------------------------------------------------------//                       USB Serial Port//                            V0.1//                     Ultra-Embedded.com//                       Copyright 2020////                 Email: admin@ultra-embedded.com////                         License: LGPL//-----------------------------------------------------------------//// 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, write to the // Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA  02111-1307  USA//-----------------------------------------------------------------//-----------------------------------------------------------------//                          Generated File//-----------------------------------------------------------------module usbf_sie_rx(    // Inputs     input           clk_i    ,input           rst_i    ,input           enable_i    ,input  [  7:0]  utmi_data_i    ,input           utmi_rxvalid_i    ,input           utmi_rxactive_i    ,input  [  6:0]  current_addr_i    // Outputs    ,output [  7:0]  pid_o    ,output          frame_valid_o    ,output [ 10:0]  frame_number_o    ,output          token_valid_o    ,output [  6:0]  token_addr_o    ,output [  3:0]  token_ep_o    ,output          token_crc_err_o    ,output          handshake_valid_o    ,output          data_valid_o    ,output          data_strb_o    ,output [  7:0]  data_o    ,output          data_last_o    ,output          data_crc_err_o    ,output          data_complete_o);//-----------------------------------------------------------------// Defines://-----------------------------------------------------------------`include "usbf_defs.v"localparam STATE_W                       = 4;localparam STATE_RX_IDLE                 = 4'd0;localparam STATE_RX_TOKEN2               = 4'd1;localparam STATE_RX_TOKEN3               = 4'd2;localparam STATE_RX_TOKEN_COMPLETE       = 4'd3;localparam STATE_RX_SOF2                 = 4'd4;localparam STATE_RX_SOF3                 = 4'd5;localparam STATE_RX_DATA                 = 4'd6;localparam STATE_RX_DATA_COMPLETE        = 4'd7;localparam STATE_RX_IGNORED              = 4'd8;reg [STATE_W-1:0] state_q;//-----------------------------------------------------------------// Wire / Regs//-----------------------------------------------------------------`define USB_FRAME_W    11reg [`USB_FRAME_W-1:0]      frame_num_q;`define USB_DEV_W      7reg [`USB_DEV_W-1:0]        token_dev_q;`define USB_EP_W       4reg [`USB_EP_W-1:0]         token_ep_q;`define USB_PID_W      8reg [`USB_PID_W-1:0]        token_pid_q;//-----------------------------------------------------------------// Data delay (to strip the CRC16 trailing bytes)//-----------------------------------------------------------------reg [31:0] data_buffer_q;reg [3:0]  data_valid_q;reg [3:0]  rx_active_q;wire shift_en_w = (utmi_rxvalid_i & utmi_rxactive_i) || !utmi_rxactive_i;always @ (posedge clk_i or posedge rst_i)if (rst_i)    data_buffer_q <= 32'b0;else if (shift_en_w)    data_buffer_q <= {utmi_data_i, data_buffer_q[31:8]};always @ (posedge clk_i or posedge rst_i)if (rst_i)    data_valid_q <= 4'b0;else if (shift_en_w)    data_valid_q <= {(utmi_rxvalid_i & utmi_rxactive_i), data_valid_q[3:1]};else    data_valid_q <= {data_valid_q[3:1], 1'b0};reg [1:0] data_crc_q;always @ (posedge clk_i or posedge rst_i)if (rst_i)    data_crc_q <= 2'b0;else if (shift_en_w)    data_crc_q <= {!utmi_rxactive_i, data_crc_q[1]};always @ (posedge clk_i or posedge rst_i)if (rst_i)    rx_active_q <= 4'b0;else    rx_active_q <= {utmi_rxactive_i, rx_active_q[3:1]};wire [7:0] data_w       = data_buffer_q[7:0];wire       data_ready_w = data_valid_q[0];wire       crc_byte_w   = data_crc_q[0];wire       rx_active_w  = rx_active_q[0];wire       address_match_w = (token_dev_q == current_addr_i);//-----------------------------------------------------------------// Next state//-----------------------------------------------------------------reg [STATE_W-1:0] next_state_r;always @ *begin    next_state_r = state_q;    case (state_q)    //-----------------------------------------    // IDLE    //-----------------------------------------    STATE_RX_IDLE :    begin       if (data_ready_w)       begin           // Decode PID           case (data_w)              `PID_OUT, `PID_IN, `PID_SETUP, `PID_PING:                    next_state_r  = STATE_RX_TOKEN2;              `PID_SOF:                    next_state_r  = STATE_RX_SOF2;              `PID_DATA0, `PID_DATA1, `PID_DATA2, `PID_MDATA:              begin                    next_state_r  = STATE_RX_DATA;              end              `PID_ACK, `PID_NAK, `PID_STALL, `PID_NYET:                    next_state_r  = STATE_RX_IDLE;              default : // SPLIT / ERR                    next_state_r  = STATE_RX_IGNORED;           endcase       end    end    //-----------------------------------------    // RX_IGNORED: Unknown / unsupported    //-----------------------------------------    STATE_RX_IGNORED :    begin        // Wait until the end of the packet        if (!rx_active_w)           next_state_r = STATE_RX_IDLE;    end    //-----------------------------------------    // SOF (BYTE 2)    //-----------------------------------------    STATE_RX_SOF2 :    begin       if (data_ready_w)           next_state_r = STATE_RX_SOF3;       else if (!rx_active_w)           next_state_r = STATE_RX_IDLE;    end    //-----------------------------------------    // SOF (BYTE 3)    //-----------------------------------------    STATE_RX_SOF3 :    begin       if (data_ready_w || !rx_active_w)           next_state_r = STATE_RX_IDLE;    end    //-----------------------------------------    // TOKEN (IN/OUT/SETUP) (Address/Endpoint)    //-----------------------------------------    STATE_RX_TOKEN2 :    begin       if (data_ready_w)           next_state_r = STATE_RX_TOKEN3;       else if (!rx_active_w)           next_state_r = STATE_RX_IDLE;    end    //-----------------------------------------    // TOKEN (IN/OUT/SETUP) (Endpoint/CRC)    //-----------------------------------------    STATE_RX_TOKEN3 :    begin       if (data_ready_w)           next_state_r = STATE_RX_TOKEN_COMPLETE;       else if (!rx_active_w)           next_state_r = STATE_RX_IDLE;    end    //-----------------------------------------    // RX_TOKEN_COMPLETE    //-----------------------------------------    STATE_RX_TOKEN_COMPLETE :    begin        next_state_r  = STATE_RX_IDLE;    end    //-----------------------------------------    // RX_DATA    //-----------------------------------------    STATE_RX_DATA :    begin       // Receive complete       if (crc_byte_w)            next_state_r = STATE_RX_DATA_COMPLETE;    end    //-----------------------------------------    // RX_DATA_COMPLETE    //-----------------------------------------    STATE_RX_DATA_COMPLETE :    begin        if (!rx_active_w)            next_state_r = STATE_RX_IDLE;    end    default :       ;    endcaseend// Update statealways @ (posedge clk_i or posedge rst_i)if (rst_i)    state_q   <= STATE_RX_IDLE;else if (!enable_i)    state_q   <= STATE_RX_IDLE;else    state_q   <= next_state_r;//-----------------------------------------------------------------// Handshake://-----------------------------------------------------------------reg handshake_valid_q;always @ (posedge clk_i or posedge rst_i)if (rst_i)    handshake_valid_q <= 1'b0;else if (state_q == STATE_RX_IDLE && data_ready_w)begin    case (data_w)    `PID_ACK, `PID_NAK, `PID_STALL, `PID_NYET:        handshake_valid_q <= address_match_w;    default :        handshake_valid_q <= 1'b0;    endcaseendelse    handshake_valid_q <= 1'b0;assign handshake_valid_o = handshake_valid_q;//-----------------------------------------------------------------// SOF: Frame number//-----------------------------------------------------------------always @ (posedge clk_i or posedge rst_i)if (rst_i)    frame_num_q         <= `USB_FRAME_W'b0;else if (state_q == STATE_RX_SOF2 && data_ready_w)    frame_num_q         <= {3'b0, data_w};else if (state_q == STATE_RX_SOF3 && data_ready_w)    frame_num_q         <= {data_w[2:0], frame_num_q[7:0]};else if (!enable_i)    frame_num_q         <= `USB_FRAME_W'b0;assign frame_number_o = frame_num_q;reg frame_valid_q;always @ (posedge clk_i or posedge rst_i)if (rst_i)    frame_valid_q <= 1'b0;else    frame_valid_q <= (state_q == STATE_RX_SOF3 && data_ready_w);assign frame_valid_o = frame_valid_q;//-----------------------------------------------------------------// Token: PID//-----------------------------------------------------------------always @ (posedge clk_i or posedge rst_i)if (rst_i)    token_pid_q <= `USB_PID_W'b0;else if (state_q == STATE_RX_IDLE && data_ready_w)    token_pid_q <= data_w;else if (!enable_i)    token_pid_q <= `USB_PID_W'b0;assign pid_o = token_pid_q;reg token_valid_q;always @ (posedge clk_i or posedge rst_i)if (rst_i)    token_valid_q <= 1'b0;else    token_valid_q <= (state_q == STATE_RX_TOKEN_COMPLETE) && address_match_w;assign token_valid_o = token_valid_q;//-----------------------------------------------------------------// Token: Device Address//-----------------------------------------------------------------always @ (posedge clk_i or posedge rst_i)if (rst_i)    token_dev_q <= `USB_DEV_W'b0;else if (state_q == STATE_RX_TOKEN2 && data_ready_w)    token_dev_q <= data_w[6:0];else if (!enable_i)    token_dev_q <= `USB_DEV_W'b0;assign token_addr_o = token_dev_q;//-----------------------------------------------------------------// Token: Endpoint//-----------------------------------------------------------------always @ (posedge clk_i or posedge rst_i)if (rst_i)    token_ep_q      <= `USB_EP_W'b0;else if (state_q == STATE_RX_TOKEN2 && data_ready_w)    token_ep_q[0]   <= data_w[7];else if (state_q == STATE_RX_TOKEN3 && data_ready_w)    token_ep_q[3:1] <= data_w[2:0];else if (!enable_i)    token_ep_q      <= `USB_EP_W'b0;assign token_ep_o = token_ep_q;assign token_crc_err_o = 1'b0;wire [7:0] input_data_w  = data_w;wire       input_ready_w = state_q == STATE_RX_DATA && data_ready_w && !crc_byte_w;//-----------------------------------------------------------------// CRC16: Generate CRC16 on incoming data bytes//-----------------------------------------------------------------reg [15:0]  crc_sum_q;wire [15:0] crc_out_w;reg         crc_err_q;usbf_crc16u_crc16(    .crc_in_i(crc_sum_q),    .din_i(data_w),    .crc_out_o(crc_out_w));always @ (posedge clk_i or posedge rst_i)if (rst_i)    crc_sum_q   <= 16'hFFFF;else if (state_q == STATE_RX_IDLE)    crc_sum_q   <= 16'hFFFF;else if (data_ready_w)    crc_sum_q   <= crc_out_w;always @ (posedge clk_i or posedge rst_i)if (rst_i)    crc_err_q   <= 1'b0;else if (state_q == STATE_RX_IDLE)    crc_err_q   <= 1'b0;else if (state_q == STATE_RX_DATA_COMPLETE && next_state_r == STATE_RX_IDLE)    crc_err_q   <= (crc_sum_q != 16'hB001);assign data_crc_err_o = crc_err_q;reg data_complete_q;always @ (posedge clk_i or posedge rst_i)if (rst_i)    data_complete_q   <= 1'b0;else if (state_q == STATE_RX_DATA_COMPLETE && next_state_r == STATE_RX_IDLE)    data_complete_q   <= 1'b1;else    data_complete_q   <= 1'b0;assign data_complete_o = data_complete_q;reg data_zlp_q;always @ (posedge clk_i or posedge rst_i)if (rst_i)    data_zlp_q   <= 1'b0;else if (state_q == STATE_RX_IDLE && next_state_r == STATE_RX_DATA)    data_zlp_q   <= 1'b1;else if (input_ready_w)    data_zlp_q   <= 1'b0;//-----------------------------------------------------------------// Data Output//-----------------------------------------------------------------reg        valid_q;reg        last_q;reg [7:0]  data_q;reg        mask_q;always @ (posedge clk_i or posedge rst_i)if (rst_i)begin    valid_q  <= 1'b0;    data_q   <= 8'b0;    mask_q   <= 1'b0;    last_q   <= 1'b0;endelsebegin    valid_q  <= input_ready_w || ((state_q == STATE_RX_DATA) && crc_byte_w && data_zlp_q);    data_q   <= input_data_w;    mask_q   <= input_ready_w;    last_q   <= (state_q == STATE_RX_DATA) && crc_byte_w;end// Dataassign data_valid_o = valid_q;assign data_strb_o  = mask_q;assign data_o       = data_q;assign data_last_o  = last_q | crc_byte_w;endmodule
 |