data/full_repos/permissive/504248338/verilog/rtl/usb1_host/src/core/usbh_sie.sv
1: b"%Error: data/full_repos/permissive/504248338/verilog/rtl/usb1_host/src/core/usbh_sie.sv:661: Cannot find file containing module: 'usbh_crc16'\nusbh_crc16\n^~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/504248338/verilog/rtl/usb1_host/src/core,data/full_repos/permissive/504248338/usbh_crc16\n             data/full_repos/permissive/504248338/verilog/rtl/usb1_host/src/core,data/full_repos/permissive/504248338/usbh_crc16.v\n             data/full_repos/permissive/504248338/verilog/rtl/usb1_host/src/core,data/full_repos/permissive/504248338/usbh_crc16.sv\n             usbh_crc16\n             usbh_crc16.v\n             usbh_crc16.sv\n             obj_dir/usbh_crc16\n             obj_dir/usbh_crc16.v\n             obj_dir/usbh_crc16.sv\n%Error: data/full_repos/permissive/504248338/verilog/rtl/usb1_host/src/core/usbh_sie.sv:670: Cannot find file containing module: 'usbh_crc5'\nusbh_crc5\n^~~~~~~~~\n%Error: Exiting due to 2 error(s)\n"
module usbh_sie



#(
     parameter USB_CLK_FREQ     = 60000000
)



(

    input           clk_i,
    input           rstn_i,
    input           start_i,
    input           in_transfer_i,
    input           sof_transfer_i,
    input           resp_expected_i,
    input  [  7:0]  token_pid_i,
    input  [  6:0]  token_dev_i,
    input  [  3:0]  token_ep_i,
    input  [ 15:0]  data_len_i,
    input           data_idx_i,
    input  [  7:0]  tx_data_i,
    input           utmi_txready_i,
    input  [  7:0]  utmi_data_i,
    input           utmi_rxvalid_i,
    input           utmi_rxactive_i,
    input  [  1:0]  utmi_linestate_i,


    output          ack_o,
    output          tx_pop_o,
    output [  7:0]  rx_data_o,
    output          rx_push_o,
    output          tx_done_o,
    output          rx_done_o,
    output          crc_err_o,
    output          timeout_o,
    output [  7:0]  response_o,
    output [ 15:0]  rx_count_o,
    output          idle_o,
    output [  7:0]  utmi_data_o,
    output          utmi_txvalid_o
);






logic                 start_ack_q;


logic                 status_tx_done_q;
logic                 status_rx_done_q;
logic                 status_crc_err_q;
logic                 status_timeout_q;
logic [7:0]           status_response_q;

logic [15:0]          byte_count_q;
logic                 in_transfer_q;

logic [8:0]           last_tx_time_q;

logic                 send_data1_q;
logic                 send_sof_q;
logic                 send_ack_q;


logic [15:0]          crc_sum_q;
logic  [15:0]         crc_out_w;
logic  [7:0]          crc_data_in_w;


logic [4:0]          crc5_out_w;
wire  [4:0]          crc5_next_w = crc5_out_w ^ 5'h1F;

logic [15:0]          token_q;

logic                 wait_resp_q;

logic [3:0]           state_q;




localparam RX_TIMEOUT       = (USB_CLK_FREQ == 60000000) ? 9'd511 : 9'd255;

localparam TX_IFS           = (USB_CLK_FREQ == 60000000) ? 4'd10  : 4'd7; 

localparam PID_OUT          = 8'hE1;
localparam PID_IN           = 8'h69;
localparam PID_SOF          = 8'hA5;
localparam PID_SETUP        = 8'h2D;

localparam PID_DATA0        = 8'hC3;
localparam PID_DATA1        = 8'h4B;

localparam PID_ACK          = 8'hD2;
localparam PID_NAK          = 8'h5A;
localparam PID_STALL        = 8'h1E;


localparam STATE_IDLE       = 4'd0;
localparam STATE_RX_DATA    = 4'd1;
localparam STATE_TX_PID     = 4'd2;
localparam STATE_TX_DATA    = 4'd3;
localparam STATE_TX_CRC1    = 4'd4;
localparam STATE_TX_CRC2    = 4'd5;
localparam STATE_TX_TOKEN1  = 4'd6;
localparam STATE_TX_TOKEN2  = 4'd7;
localparam STATE_TX_TOKEN3  = 4'd8;
localparam STATE_TX_ACKNAK  = 4'd9;
localparam STATE_TX_WAIT    = 4'd10;
localparam STATE_RX_WAIT    = 4'd11;
localparam STATE_TX_IFS     = 4'd12;





logic [7:0] rx_data_w;
logic       data_ready_w;
logic       crc_byte_w;
logic       rx_active_w;
logic       rx_active_rise_w;


logic ifs_busy_w;


wire rx_resp_timeout_w = (last_tx_time_q >= RX_TIMEOUT) & wait_resp_q;


wire crc_error_w = (state_q == STATE_RX_DATA) && !rx_active_w && in_transfer_q        &&
                   (status_response_q == PID_DATA0 || status_response_q == PID_DATA1) &&
                   (crc_sum_q != 16'hB001);




logic [3:0] next_state_r;

always @ *
begin
    next_state_r = state_q;
        



    case (state_q)




        STATE_TX_TOKEN1 :
        begin

            if (utmi_txready_i)
                next_state_r = STATE_TX_TOKEN2;
        end



        STATE_TX_TOKEN2 :
        begin

            if (utmi_txready_i)
                next_state_r = STATE_TX_TOKEN3;        
        end



        STATE_TX_TOKEN3 :
        begin

            if (utmi_txready_i)
            begin

                if (send_sof_q)
                    next_state_r = STATE_TX_IFS;

                else if (in_transfer_q)
                    next_state_r = STATE_RX_WAIT;

                else
                    next_state_r = STATE_TX_IFS;
            end
        end



        STATE_TX_IFS :
        begin

            if (~ifs_busy_w)
            begin

                if (send_sof_q)
                    next_state_r = STATE_IDLE;

                else
                    next_state_r = STATE_TX_PID;
            end
        end



        STATE_TX_PID :
        begin

            if (utmi_txready_i && (byte_count_q == 16'b0))
                next_state_r = STATE_TX_CRC1;
            else if (utmi_txready_i)
                next_state_r = STATE_TX_DATA;
        end



        STATE_TX_DATA :
        begin

            if (utmi_txready_i && (byte_count_q == 16'b0))
                next_state_r = STATE_TX_CRC1;
        end



        STATE_TX_CRC1 :
        begin

            if (utmi_txready_i)
                next_state_r = STATE_TX_CRC2;
        end



        STATE_TX_CRC2 :
        begin

            if (utmi_txready_i)
            begin

               if (wait_resp_q)
                  next_state_r = STATE_RX_WAIT;

               else
                  next_state_r = STATE_IDLE;                
            end
        end



        STATE_TX_WAIT :
        begin

            if (~ifs_busy_w)
                next_state_r = STATE_TX_ACKNAK;
        end        



        STATE_TX_ACKNAK :
        begin

            if (utmi_txready_i)
                next_state_r = STATE_IDLE;
        end



        STATE_RX_WAIT :
        begin

           if (data_ready_w)
              next_state_r = STATE_RX_DATA;

           else if (rx_resp_timeout_w)
              next_state_r = STATE_IDLE;
        end



        STATE_RX_DATA :
        begin

            if (~rx_active_w)
            begin

                if (send_ack_q && crc_error_w)
                    next_state_r = STATE_IDLE;

                else if (send_ack_q && (status_response_q == PID_DATA0 || status_response_q == PID_DATA1))
                    next_state_r = STATE_TX_WAIT;
                else
                    next_state_r = STATE_IDLE;
            end
        end



        STATE_IDLE :
        begin

           if (start_i)
              next_state_r  = STATE_TX_TOKEN1;
        end
        default :
           ;
    endcase
end


always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    state_q   <= STATE_IDLE;
else
    state_q   <= next_state_r;




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    token_q         <= 16'h0000;
else if (state_q == STATE_IDLE)
    token_q         <= {token_dev_i, token_ep_i, 5'b0};

else if (state_q == STATE_TX_TOKEN1 && utmi_txready_i)
    token_q[4:0]    <= crc5_next_w;




reg [1:0] utmi_linestate_q;
reg       se0_detect_q;
reg       wait_eop_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    utmi_linestate_q <= 2'b0;
else
    utmi_linestate_q <= utmi_linestate_i;


wire se0_detect_w = (utmi_linestate_q == 2'b00 && utmi_linestate_i == 2'b00);

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    se0_detect_q <= 1'b0;
else
    se0_detect_q <= se0_detect_w;


wire eop_detected_w = se0_detect_q & (utmi_linestate_i != 2'b00);


always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    wait_eop_q <= 1'b0;
else if (eop_detected_w)
    wait_eop_q <= 1'b0;
else if ((state_q == STATE_TX_CRC2   && next_state_r != STATE_TX_CRC2)   ||
         (state_q == STATE_TX_TOKEN3 && next_state_r != STATE_TX_TOKEN3) ||
         (state_q == STATE_TX_ACKNAK && next_state_r != STATE_TX_ACKNAK))
    wait_eop_q <= 1'b1;
else if (rx_active_rise_w)
    wait_eop_q <= 1'b1;

localparam TX_IFS_W = 4;
reg [TX_IFS_W-1:0] tx_ifs_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    tx_ifs_q <= {(TX_IFS_W){1'b0}};

else if (wait_eop_q || eop_detected_w)
    tx_ifs_q <= TX_IFS;

else if (tx_ifs_q !=  {(TX_IFS_W){1'b0}})
    tx_ifs_q <= tx_ifs_q - 1;

assign ifs_busy_w = wait_eop_q || (tx_ifs_q != {(TX_IFS_W){1'b0}});




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    last_tx_time_q <= 9'd0;

else if (state_q == STATE_IDLE || (utmi_txvalid_o && utmi_txready_i))
    last_tx_time_q <= 9'd0;

else if (last_tx_time_q != RX_TIMEOUT)
    last_tx_time_q <= last_tx_time_q + 9'd1;




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    byte_count_q <= 16'h0000;

else if (state_q == STATE_IDLE && start_i && !sof_transfer_i)
    byte_count_q <= data_len_i;
else if (state_q == STATE_RX_WAIT)
    byte_count_q <= 16'h0000;

else if ((state_q == STATE_TX_PID || state_q == STATE_TX_DATA) && utmi_txready_i)
begin

    if (byte_count_q != 16'd0)
        byte_count_q <= byte_count_q - 16'd1;
end

else if (state_q == STATE_RX_DATA && data_ready_w && !crc_byte_w)
    byte_count_q <= byte_count_q + 16'd1;




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    start_ack_q  <= 1'b0;

else if (state_q == STATE_TX_TOKEN1 && utmi_txready_i)
    start_ack_q  <= 1'b1;
else
    start_ack_q  <= 1'b0;




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
begin
    in_transfer_q   <= 1'b0;
    send_ack_q      <= 1'b0;
    send_data1_q    <= 1'b0;
    send_sof_q      <= 1'b0;
end

else if (state_q == STATE_IDLE && start_i)
begin





    in_transfer_q   <= in_transfer_i;


    send_ack_q      <= in_transfer_i && resp_expected_i;


    send_data1_q    <= data_idx_i;

    send_sof_q      <= sof_transfer_i;
end




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    wait_resp_q <= 1'b0;

else if (state_q == STATE_RX_WAIT && data_ready_w)
    wait_resp_q <= 1'b0;
else if (state_q == STATE_IDLE && start_i)
    wait_resp_q <= resp_expected_i;




always @ (posedge clk_i or negedge rstn_i)
begin
   if (!rstn_i)
   begin
       status_response_q    <= 8'h00;
       status_timeout_q     <= 1'b0;
       status_rx_done_q     <= 1'b0;
       status_tx_done_q     <= 1'b0;
   end
   else
   begin
        case (state_q)




        STATE_RX_WAIT :
        begin

           if (data_ready_w)
               status_response_q   <= rx_data_w;


           if (rx_resp_timeout_w)
               status_timeout_q    <= 1'b1;

            status_tx_done_q     <= 1'b0;
        end



        STATE_RX_DATA :
        begin

           if (!utmi_rxactive_i)
                status_rx_done_q   <= 1'b1;
           else
                status_rx_done_q   <= 1'b0;
        end



        STATE_TX_CRC2 :
        begin

            if (utmi_txready_i && !wait_resp_q)
            begin

                status_tx_done_q    <= 1'b1;
            end
        end



        STATE_IDLE :
        begin





            if (start_i && !sof_transfer_i)
            begin

                status_response_q       <= 8'h00;
                status_timeout_q        <= 1'b0;
            end

            status_rx_done_q     <= 1'b0;
            status_tx_done_q     <= 1'b0;
        end



        default :
        begin
            status_rx_done_q     <= 1'b0;
            status_tx_done_q     <= 1'b0;
        end
       endcase
   end
end





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 negedge rstn_i)
if (!rstn_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 negedge rstn_i)
if (!rstn_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 negedge rstn_i)
if (!rstn_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 negedge rstn_i)
if (!rstn_i)
    rx_active_q <= 4'b0;
else
    rx_active_q <= {utmi_rxactive_i, rx_active_q[3:1]};

assign rx_data_w    = data_buffer_q[7:0];
assign data_ready_w = data_valid_q[0];
assign crc_byte_w   = data_crc_q[0];
assign rx_active_w  = rx_active_q[0];

assign rx_active_rise_w = !rx_active_q[3] && utmi_rxactive_i;






usbh_crc16
u_crc16
(
    .crc_i(crc_sum_q),
    .data_i(crc_data_in_w),
    .crc_o(crc_out_w)
);


usbh_crc5
u_crc5
(
    .crc_i(5'h1F),
    .data_i(token_q[15:5]),
    .crc_o(crc5_out_w)
);


always @ (posedge clk_i or negedge rstn_i)
begin
   if (!rstn_i)
   begin
       crc_sum_q          <= 16'hFFFF;
       status_crc_err_q   <= 1'b0;
   end
   else
   begin
        case (state_q)



            STATE_TX_PID :
            begin

                crc_sum_q      <= 16'hFFFF;
            end        



            STATE_TX_DATA :
            begin

                if (utmi_txready_i)
                begin

                    crc_sum_q      <= crc_out_w;
                end
            end



            STATE_RX_WAIT :
            begin

                crc_sum_q   <= 16'hFFFF;
            end            



            STATE_RX_DATA :
            begin

               if (data_ready_w)
               begin

                   crc_sum_q          <= crc_out_w;
               end

               else if (!rx_active_w)
               begin

                    if (crc_error_w)
                        status_crc_err_q   <= 1'b1;
                    else
                        status_crc_err_q   <= 1'b0;
               end
            end




            STATE_IDLE :
            begin

               if (start_i && !sof_transfer_i)
               begin

                  status_crc_err_q  <= 1'b0;
               end
            end
           default :
               ;
        endcase
   end
end




wire [15:0] token_rev_w;

genvar i;
generate
for (i=0; i < 16; i=i+1) 
begin : LOOP
    assign token_rev_w[i] = token_q[15-i];
end
endgenerate

reg       utmi_txvalid_r;
reg [7:0] utmi_data_r;

always @ *
begin
    if (state_q == STATE_TX_CRC1)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = crc_sum_q[7:0] ^ 8'hFF;
    end
    else if (state_q == STATE_TX_CRC2)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = crc_sum_q[15:8] ^ 8'hFF;
    end
    else if (state_q == STATE_TX_TOKEN1)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = token_pid_i;
    end
    else if (state_q == STATE_TX_TOKEN2)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = token_rev_w[7:0];
    end
    else if (state_q == STATE_TX_TOKEN3)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = token_rev_w[15:8];
    end
    else if (state_q == STATE_TX_PID)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = send_data1_q ? PID_DATA1 : PID_DATA0;
    end
    else if (state_q == STATE_TX_ACKNAK)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = PID_ACK;
    end
    else if (state_q == STATE_TX_DATA)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = tx_data_i;
    end
    else
    begin
        utmi_txvalid_r = 1'b0;
        utmi_data_r    = 8'b0;
    end
end

assign utmi_txvalid_o = utmi_txvalid_r;
assign utmi_data_o    = utmi_data_r;


assign rx_data_o    = rx_data_w;
assign rx_push_o    = (state_q != STATE_IDLE && state_q != STATE_RX_WAIT) & data_ready_w & !crc_byte_w;

assign crc_data_in_w = (state_q == STATE_RX_DATA) ? rx_data_w : tx_data_i;

assign rx_count_o   = byte_count_q;
assign idle_o       = (state_q == STATE_IDLE);

assign ack_o        = start_ack_q;

assign tx_pop_o     = state_q == STATE_TX_DATA && utmi_txready_i;

assign tx_done_o    = status_tx_done_q;
assign rx_done_o    = status_rx_done_q;
assign crc_err_o    = status_crc_err_q;
assign timeout_o    = status_timeout_q;
assign response_o   = status_response_q;



endmodule
module usbh_sie



#(
     parameter USB_CLK_FREQ     = 60000000
)



(

    input           clk_i,
    input           rstn_i,
    input           start_i,
    input           in_transfer_i,
    input           sof_transfer_i,
    input           resp_expected_i,
    input  [  7:0]  token_pid_i,
    input  [  6:0]  token_dev_i,
    input  [  3:0]  token_ep_i,
    input  [ 15:0]  data_len_i,
    input           data_idx_i,
    input  [  7:0]  tx_data_i,
    input           utmi_txready_i,
    input  [  7:0]  utmi_data_i,
    input           utmi_rxvalid_i,
    input           utmi_rxactive_i,
    input  [  1:0]  utmi_linestate_i,


    output          ack_o,
    output          tx_pop_o,
    output [  7:0]  rx_data_o,
    output          rx_push_o,
    output          tx_done_o,
    output          rx_done_o,
    output          crc_err_o,
    output          timeout_o,
    output [  7:0]  response_o,
    output [ 15:0]  rx_count_o,
    output          idle_o,
    output [  7:0]  utmi_data_o,
    output          utmi_txvalid_o
);







logic                 start_ack_q;


logic                 status_tx_done_q;
logic                 status_rx_done_q;
logic                 status_crc_err_q;
logic                 status_timeout_q;
logic [7:0]           status_response_q;

logic [15:0]          byte_count_q;
logic                 in_transfer_q;

logic [8:0]           last_tx_time_q;

logic                 send_data1_q;
logic                 send_sof_q;
logic                 send_ack_q;


logic [15:0]          crc_sum_q;
logic  [15:0]         crc_out_w;
logic  [7:0]          crc_data_in_w;


logic [4:0]          crc5_out_w;
wire  [4:0]          crc5_next_w = crc5_out_w ^ 5'h1F;

logic [15:0]          token_q;

logic                 wait_resp_q;

logic [3:0]           state_q;




localparam RX_TIMEOUT       = (USB_CLK_FREQ == 60000000) ? 9'd511 : 9'd255;

localparam TX_IFS           = (USB_CLK_FREQ == 60000000) ? 4'd10  : 4'd7; 

localparam PID_OUT          = 8'hE1;
localparam PID_IN           = 8'h69;
localparam PID_SOF          = 8'hA5;
localparam PID_SETUP        = 8'h2D;

localparam PID_DATA0        = 8'hC3;
localparam PID_DATA1        = 8'h4B;

localparam PID_ACK          = 8'hD2;
localparam PID_NAK          = 8'h5A;
localparam PID_STALL        = 8'h1E;


localparam STATE_IDLE       = 4'd0;
localparam STATE_RX_DATA    = 4'd1;
localparam STATE_TX_PID     = 4'd2;
localparam STATE_TX_DATA    = 4'd3;
localparam STATE_TX_CRC1    = 4'd4;
localparam STATE_TX_CRC2    = 4'd5;
localparam STATE_TX_TOKEN1  = 4'd6;
localparam STATE_TX_TOKEN2  = 4'd7;
localparam STATE_TX_TOKEN3  = 4'd8;
localparam STATE_TX_ACKNAK  = 4'd9;
localparam STATE_TX_WAIT    = 4'd10;
localparam STATE_RX_WAIT    = 4'd11;
localparam STATE_TX_IFS     = 4'd12;





logic [7:0] rx_data_w;
logic       data_ready_w;
logic       crc_byte_w;
logic       rx_active_w;
logic       rx_active_rise_w;


logic ifs_busy_w;


wire rx_resp_timeout_w = (last_tx_time_q >= RX_TIMEOUT) & wait_resp_q;


wire crc_error_w = (state_q == STATE_RX_DATA) && !rx_active_w && in_transfer_q        &&
                   (status_response_q == PID_DATA0 || status_response_q == PID_DATA1) &&
                   (crc_sum_q != 16'hB001);




logic [3:0] next_state_r;

always @ *
begin
    next_state_r = state_q;
        



    case (state_q)




        STATE_TX_TOKEN1 :
        begin

            if (utmi_txready_i)
                next_state_r = STATE_TX_TOKEN2;
        end



        STATE_TX_TOKEN2 :
        begin

            if (utmi_txready_i)
                next_state_r = STATE_TX_TOKEN3;        
        end



        STATE_TX_TOKEN3 :
        begin

            if (utmi_txready_i)
            begin

                if (send_sof_q)
                    next_state_r = STATE_TX_IFS;

                else if (in_transfer_q)
                    next_state_r = STATE_RX_WAIT;

                else
                    next_state_r = STATE_TX_IFS;
            end
        end



        STATE_TX_IFS :
        begin

            if (~ifs_busy_w)
            begin

                if (send_sof_q)
                    next_state_r = STATE_IDLE;

                else
                    next_state_r = STATE_TX_PID;
            end
        end



        STATE_TX_PID :
        begin

            if (utmi_txready_i && (byte_count_q == 16'b0))
                next_state_r = STATE_TX_CRC1;
            else if (utmi_txready_i)
                next_state_r = STATE_TX_DATA;
        end



        STATE_TX_DATA :
        begin

            if (utmi_txready_i && (byte_count_q == 16'b0))
                next_state_r = STATE_TX_CRC1;
        end



        STATE_TX_CRC1 :
        begin

            if (utmi_txready_i)
                next_state_r = STATE_TX_CRC2;
        end



        STATE_TX_CRC2 :
        begin

            if (utmi_txready_i)
            begin

               if (wait_resp_q)
                  next_state_r = STATE_RX_WAIT;

               else
                  next_state_r = STATE_IDLE;                
            end
        end



        STATE_TX_WAIT :
        begin

            if (~ifs_busy_w)
                next_state_r = STATE_TX_ACKNAK;
        end        



        STATE_TX_ACKNAK :
        begin

            if (utmi_txready_i)
                next_state_r = STATE_IDLE;
        end



        STATE_RX_WAIT :
        begin

           if (data_ready_w)
              next_state_r = STATE_RX_DATA;

           else if (rx_resp_timeout_w)
              next_state_r = STATE_IDLE;
        end



        STATE_RX_DATA :
        begin

            if (~rx_active_w)
            begin

                if (send_ack_q && crc_error_w)
                    next_state_r = STATE_IDLE;

                else if (send_ack_q && (status_response_q == PID_DATA0 || status_response_q == PID_DATA1))
                    next_state_r = STATE_TX_WAIT;
                else
                    next_state_r = STATE_IDLE;
            end
        end



        STATE_IDLE :
        begin

           if (start_i)
              next_state_r  = STATE_TX_TOKEN1;
        end
        default :
           ;
    endcase
end


always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    state_q   <= STATE_IDLE;
else
    state_q   <= next_state_r;




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    token_q         <= 16'h0000;
else if (state_q == STATE_IDLE)
    token_q         <= {token_dev_i, token_ep_i, 5'b0};

else if (state_q == STATE_TX_TOKEN1 && utmi_txready_i)
    token_q[4:0]    <= crc5_next_w;




reg [1:0] utmi_linestate_q;
reg       se0_detect_q;
reg       wait_eop_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    utmi_linestate_q <= 2'b0;
else
    utmi_linestate_q <= utmi_linestate_i;


wire se0_detect_w = (utmi_linestate_q == 2'b00 && utmi_linestate_i == 2'b00);

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    se0_detect_q <= 1'b0;
else
    se0_detect_q <= se0_detect_w;


wire eop_detected_w = se0_detect_q & (utmi_linestate_i != 2'b00);


always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    wait_eop_q <= 1'b0;
else if (eop_detected_w)
    wait_eop_q <= 1'b0;
else if ((state_q == STATE_TX_CRC2   && next_state_r != STATE_TX_CRC2)   ||
         (state_q == STATE_TX_TOKEN3 && next_state_r != STATE_TX_TOKEN3) ||
         (state_q == STATE_TX_ACKNAK && next_state_r != STATE_TX_ACKNAK))
    wait_eop_q <= 1'b1;
else if (rx_active_rise_w)
    wait_eop_q <= 1'b1;

localparam TX_IFS_W = 4;
reg [TX_IFS_W-1:0] tx_ifs_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    tx_ifs_q <= {(TX_IFS_W){1'b0}};

else if (wait_eop_q || eop_detected_w)
    tx_ifs_q <= TX_IFS;

else if (tx_ifs_q !=  {(TX_IFS_W){1'b0}})
    tx_ifs_q <= tx_ifs_q - 1;

assign ifs_busy_w = wait_eop_q || (tx_ifs_q != {(TX_IFS_W){1'b0}});




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    last_tx_time_q <= 9'd0;

else if (state_q == STATE_IDLE || (utmi_txvalid_o && utmi_txready_i))
    last_tx_time_q <= 9'd0;

else if (last_tx_time_q != RX_TIMEOUT)
    last_tx_time_q <= last_tx_time_q + 9'd1;




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    byte_count_q <= 16'h0000;

else if (state_q == STATE_IDLE && start_i && !sof_transfer_i)
    byte_count_q <= data_len_i;
else if (state_q == STATE_RX_WAIT)
    byte_count_q <= 16'h0000;

else if ((state_q == STATE_TX_PID || state_q == STATE_TX_DATA) && utmi_txready_i)
begin

    if (byte_count_q != 16'd0)
        byte_count_q <= byte_count_q - 16'd1;
end

else if (state_q == STATE_RX_DATA && data_ready_w && !crc_byte_w)
    byte_count_q <= byte_count_q + 16'd1;




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    start_ack_q  <= 1'b0;

else if (state_q == STATE_TX_TOKEN1 && utmi_txready_i)
    start_ack_q  <= 1'b1;
else
    start_ack_q  <= 1'b0;




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
begin
    in_transfer_q   <= 1'b0;
    send_ack_q      <= 1'b0;
    send_data1_q    <= 1'b0;
    send_sof_q      <= 1'b0;
end

else if (state_q == STATE_IDLE && start_i)
begin





    in_transfer_q   <= in_transfer_i;


    send_ack_q      <= in_transfer_i && resp_expected_i;


    send_data1_q    <= data_idx_i;

    send_sof_q      <= sof_transfer_i;
end




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    wait_resp_q <= 1'b0;

else if (state_q == STATE_RX_WAIT && data_ready_w)
    wait_resp_q <= 1'b0;
else if (state_q == STATE_IDLE && start_i)
    wait_resp_q <= resp_expected_i;




always @ (posedge clk_i or negedge rstn_i)
begin
   if (!rstn_i)
   begin
       status_response_q    <= 8'h00;
       status_timeout_q     <= 1'b0;
       status_rx_done_q     <= 1'b0;
       status_tx_done_q     <= 1'b0;
   end
   else
   begin
        case (state_q)




        STATE_RX_WAIT :
        begin

           if (data_ready_w)
               status_response_q   <= rx_data_w;


           if (rx_resp_timeout_w)
               status_timeout_q    <= 1'b1;

            status_tx_done_q     <= 1'b0;
        end



        STATE_RX_DATA :
        begin

           if (!utmi_rxactive_i)
                status_rx_done_q   <= 1'b1;
           else
                status_rx_done_q   <= 1'b0;
        end



        STATE_TX_CRC2 :
        begin

            if (utmi_txready_i && !wait_resp_q)
            begin

                status_tx_done_q    <= 1'b1;
            end
        end



        STATE_IDLE :
        begin





            if (start_i && !sof_transfer_i)
            begin

                status_response_q       <= 8'h00;
                status_timeout_q        <= 1'b0;
            end

            status_rx_done_q     <= 1'b0;
            status_tx_done_q     <= 1'b0;
        end



        default :
        begin
            status_rx_done_q     <= 1'b0;
            status_tx_done_q     <= 1'b0;
        end
       endcase
   end
end





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 negedge rstn_i)
if (!rstn_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 negedge rstn_i)
if (!rstn_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 negedge rstn_i)
if (!rstn_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 negedge rstn_i)
if (!rstn_i)
    rx_active_q <= 4'b0;
else
    rx_active_q <= {utmi_rxactive_i, rx_active_q[3:1]};

assign rx_data_w    = data_buffer_q[7:0];
assign data_ready_w = data_valid_q[0];
assign crc_byte_w   = data_crc_q[0];
assign rx_active_w  = rx_active_q[0];

assign rx_active_rise_w = !rx_active_q[3] && utmi_rxactive_i;






usbh_crc16
u_crc16
(
    .crc_i(crc_sum_q),
    .data_i(crc_data_in_w),
    .crc_o(crc_out_w)
);


usbh_crc5
u_crc5
(
    .crc_i(5'h1F),
    .data_i(token_q[15:5]),
    .crc_o(crc5_out_w)
);


always @ (posedge clk_i or negedge rstn_i)
begin
   if (!rstn_i)
   begin
       crc_sum_q          <= 16'hFFFF;
       status_crc_err_q   <= 1'b0;
   end
   else
   begin
        case (state_q)



            STATE_TX_PID :
            begin

                crc_sum_q      <= 16'hFFFF;
            end        



            STATE_TX_DATA :
            begin

                if (utmi_txready_i)
                begin

                    crc_sum_q      <= crc_out_w;
                end
            end



            STATE_RX_WAIT :
            begin

                crc_sum_q   <= 16'hFFFF;
            end            



            STATE_RX_DATA :
            begin

               if (data_ready_w)
               begin

                   crc_sum_q          <= crc_out_w;
               end

               else if (!rx_active_w)
               begin

                    if (crc_error_w)
                        status_crc_err_q   <= 1'b1;
                    else
                        status_crc_err_q   <= 1'b0;
               end
            end




            STATE_IDLE :
            begin

               if (start_i && !sof_transfer_i)
               begin

                  status_crc_err_q  <= 1'b0;
               end
            end
           default :
               ;
        endcase
   end
end




wire [15:0] token_rev_w;

genvar i;
generate
for (i=0; i < 16; i=i+1) 
begin : LOOP
    assign token_rev_w[i] = token_q[15-i];
end
endgenerate

reg       utmi_txvalid_r;
reg [7:0] utmi_data_r;

always @ *
begin
    if (state_q == STATE_TX_CRC1)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = crc_sum_q[7:0] ^ 8'hFF;
    end
    else if (state_q == STATE_TX_CRC2)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = crc_sum_q[15:8] ^ 8'hFF;
    end
    else if (state_q == STATE_TX_TOKEN1)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = token_pid_i;
    end
    else if (state_q == STATE_TX_TOKEN2)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = token_rev_w[7:0];
    end
    else if (state_q == STATE_TX_TOKEN3)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = token_rev_w[15:8];
    end
    else if (state_q == STATE_TX_PID)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = send_data1_q ? PID_DATA1 : PID_DATA0;
    end
    else if (state_q == STATE_TX_ACKNAK)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = PID_ACK;
    end
    else if (state_q == STATE_TX_DATA)
    begin
        utmi_txvalid_r = 1'b1;
        utmi_data_r    = tx_data_i;
    end
    else
    begin
        utmi_txvalid_r = 1'b0;
        utmi_data_r    = 8'b0;
    end
end

assign utmi_txvalid_o = utmi_txvalid_r;
assign utmi_data_o    = utmi_data_r;


assign rx_data_o    = rx_data_w;
assign rx_push_o    = (state_q != STATE_IDLE && state_q != STATE_RX_WAIT) & data_ready_w & !crc_byte_w;

assign crc_data_in_w = (state_q == STATE_RX_DATA) ? rx_data_w : tx_data_i;

assign rx_count_o   = byte_count_q;
assign idle_o       = (state_q == STATE_IDLE);

assign ack_o        = start_ack_q;

assign tx_pop_o     = state_q == STATE_TX_DATA && utmi_txready_i;

assign tx_done_o    = status_tx_done_q;
assign rx_done_o    = status_rx_done_q;
assign crc_err_o    = status_crc_err_q;
assign timeout_o    = status_timeout_q;
assign response_o   = status_response_q;



endmodule