data/full_repos/permissive/504248338/verilog/rtl/usb1_host/src/phy/usb_fs_phy.v
data/verilator_xmls/db9295cc-87a8-42b6-95ee-cb57fccf99ca.xml
module usb_fs_phy



#(
     parameter USB_CLK_FREQ     = 60000000
)

(

     input           clk_i
    ,input           rstn_i
    ,input  [  7:0]  utmi_data_out_i
    ,input           utmi_txvalid_i
    ,input  [  1:0]  utmi_op_mode_i
    ,input  [  1:0]  utmi_xcvrselect_i
    ,input           utmi_termselect_i
    ,input           utmi_dppulldown_i
    ,input           utmi_dmpulldown_i
    ,input           usb_rx_rcv_i
    ,input           usb_rx_dp_i
    ,input           usb_rx_dn_i
    ,input           usb_reset_assert_i


    ,output [  7:0]  utmi_data_in_o
    ,output          utmi_txready_o
    ,output          utmi_rxvalid_o
    ,output          utmi_rxactive_o
    ,output          utmi_rxerror_o
    ,output [  1:0]  utmi_linestate_o
    ,output          usb_tx_dp_o
    ,output          usb_tx_dn_o
    ,output          usb_tx_oen_o
    ,output          usb_reset_detect_o
    ,output          usb_en_o
);








localparam SAMPLE_RATE       = (USB_CLK_FREQ == 60000000) ? 3'd4 : 3'd3;




reg         rx_en_q;




reg         out_dp_q;
reg         out_dn_q;

wire        in_dp_w;
wire        in_dn_w;
wire        in_rx_w;

wire        in_j_w;
wire        in_k_w;
wire        in_se0_w;
wire        in_invalid_w;

wire        sample_w;

wire        bit_edge_w;
wire        bit_transition_w;

reg [2:0]   bit_count_q;
reg [2:0]   ones_count_q;
reg [7:0]   data_q;
reg         send_eop_q;

reg         sync_j_detected_q;

wire        bit_stuff_bit_w;
wire        next_is_bit_stuff_w;

wire        usb_reset_assert_w = usb_reset_assert_i | 
                                (utmi_xcvrselect_i == 2'b00 && 
                                 utmi_termselect_i == 1'b0  && 
                                 utmi_op_mode_i    == 2'b10 && 
                                 utmi_dppulldown_i && 
                                 utmi_dmpulldown_i);




reg         rx_dp_ms;
reg         rx_dn_ms;
reg         rxd_ms;


always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
begin
    rx_dp_ms <= 1'b0;
    rx_dn_ms <= 1'b0;
    rxd_ms   <= 1'b0;
end
else
begin
    rx_dp_ms <= in_dp_w;
    rx_dn_ms <= in_dn_w;
    rxd_ms   <= in_rx_w;
end




reg         rx_dp0_q;
reg         rx_dn0_q;
reg         rx_dp1_q;
reg         rx_dn1_q;
reg         rx_dp_q;
reg         rx_dn_q;
reg         rxd0_q;
reg         rxd1_q;
reg         rxd_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
begin
    rx_dp0_q    <= 1'b0;
    rx_dn0_q    <= 1'b0;
    rx_dp1_q    <= 1'b0;
    rx_dn1_q    <= 1'b0;
    rx_dp_q     <= 1'b0;
    rx_dn_q     <= 1'b0;
    rxd0_q      <= 1'b0;
    rxd1_q      <= 1'b0;
    rxd_q       <= 1'b0;
end
else
begin

    if (rx_dp0_q & rx_dp1_q)
        rx_dp_q     <= 1'b1;
    else if (!rx_dp0_q & !rx_dp1_q)
        rx_dp_q     <= 1'b0;

    if (rx_dn0_q & rx_dn1_q)
        rx_dn_q     <= 1'b1;
    else if (!rx_dn0_q & !rx_dn1_q)
        rx_dn_q     <= 1'b0;

    if (rxd0_q & rxd1_q)
        rxd_q     <= 1'b1;
    else if (!rxd0_q & !rxd1_q)
        rxd_q     <= 1'b0;


    rx_dp1_q    <= rx_dp0_q;
    rx_dp0_q    <= rx_dp_ms;

    rx_dn1_q    <= rx_dn0_q;
    rx_dn0_q    <= rx_dn_ms;

    rxd1_q      <= rxd0_q;
    rxd0_q      <= rxd_ms;
end






assign in_j_w       = in_se0_w ? 1'b0 :  rxd_q;
assign in_k_w       = in_se0_w ? 1'b0 : ~rxd_q;
assign in_se0_w     = (!rx_dp_q & !rx_dn_q);
assign in_invalid_w = (rx_dp_q & rx_dn_q);


assign utmi_linestate_o = usb_tx_oen_o ? {rx_dn_q, rx_dp_q} : {usb_tx_dn_o, usb_tx_dp_o};




localparam STATE_W              = 4;
localparam STATE_IDLE           = 4'd0;
localparam STATE_RX_DETECT      = 4'd1;
localparam STATE_RX_SYNC_J      = 4'd2;
localparam STATE_RX_SYNC_K      = 4'd3;
localparam STATE_RX_ACTIVE      = 4'd4;
localparam STATE_RX_EOP0        = 4'd5;
localparam STATE_RX_EOP1        = 4'd6;
localparam STATE_TX_SYNC        = 4'd7;
localparam STATE_TX_ACTIVE      = 4'd8;
localparam STATE_TX_EOP_STUFF   = 4'd9;
localparam STATE_TX_EOP0        = 4'd10;
localparam STATE_TX_EOP1        = 4'd11;
localparam STATE_TX_EOP2        = 4'd12;
localparam STATE_TX_RST         = 4'd13;


reg [STATE_W-1:0] state_q;

reg [STATE_W-1:0] next_state_r;
always @ *
begin
    next_state_r = state_q;

    case (state_q)



    STATE_IDLE :
    begin
        if (in_k_w)
            next_state_r    = STATE_RX_DETECT;
        else if (utmi_txvalid_i)
            next_state_r    = STATE_TX_SYNC;
        else if (usb_reset_assert_w)
            next_state_r    = STATE_TX_RST;
    end



    STATE_RX_DETECT :
    begin
        if (in_k_w && sample_w)
            next_state_r    = STATE_RX_SYNC_K;
        else if (sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_RX_SYNC_J :
    begin
        if (in_k_w && sample_w)
            next_state_r    = STATE_RX_SYNC_K;

        else if ((bit_count_q == 3'd1) && sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_RX_SYNC_K :
    begin


        if (sync_j_detected_q && in_k_w && sample_w)
            next_state_r    = STATE_RX_ACTIVE;

        else if (!sync_j_detected_q && in_k_w && sample_w)
            next_state_r    = STATE_IDLE;
        else if (in_j_w && sample_w)
            next_state_r    = STATE_RX_SYNC_J;
    end



    STATE_RX_ACTIVE :
    begin
        if (in_se0_w && sample_w)
            next_state_r    = STATE_RX_EOP0;

        else if (in_invalid_w && sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_RX_EOP0 :
    begin
        if (in_se0_w && sample_w)
            next_state_r    = STATE_RX_EOP1;

        else if (sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_RX_EOP1 :
    begin

        if (in_j_w && sample_w)
            next_state_r    = STATE_IDLE;

        else if (sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_TX_SYNC :
    begin
        if (bit_count_q == 3'd7 && sample_w)
            next_state_r    = STATE_TX_ACTIVE;
    end



    STATE_TX_ACTIVE :
    begin
        if (bit_count_q == 3'd7 && sample_w && (!utmi_txvalid_i || send_eop_q) && !bit_stuff_bit_w)
        begin

            if (next_is_bit_stuff_w)
                next_state_r    = STATE_TX_EOP_STUFF;
            else
                next_state_r    = STATE_TX_EOP0;
        end
    end



    STATE_TX_EOP_STUFF :
    begin
        if (sample_w)
            next_state_r    = STATE_TX_EOP0;
    end



    STATE_TX_EOP0 :
    begin
        if (sample_w)
            next_state_r    = STATE_TX_EOP1;
    end



    STATE_TX_EOP1 :
    begin
        if (sample_w)
            next_state_r    = STATE_TX_EOP2;
    end



    STATE_TX_EOP2 :
    begin
        if (sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_TX_RST :
    begin
        if (!usb_reset_assert_w)
            next_state_r    = STATE_IDLE;
    end
    default:
        ;
   endcase
end


always @ (negedge rstn_i or posedge clk_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)
    sync_j_detected_q  <= 1'b0;

else if (state_q == STATE_IDLE)
    sync_j_detected_q  <= 1'b0;

else if (state_q == STATE_RX_SYNC_J)
    sync_j_detected_q  <= 1'b1;




reg rx_error_q;

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

else if (ones_count_q == 3'd7)
    rx_error_q  <= 1'b1;

else if (in_invalid_w && sample_w)
    rx_error_q  <= 1'b1;

else if ((state_q == STATE_RX_SYNC_K) && !sync_j_detected_q && in_k_w && sample_w)
    rx_error_q  <= 1'b1;
else
    rx_error_q  <= 1'b0;

assign utmi_rxerror_o = rx_error_q;




reg rxd_last_q;

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

assign bit_edge_w = rxd_last_q ^ in_j_w;




reg [2:0] sample_cnt_q;
reg       adjust_delayed_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i) begin
    sample_cnt_q        <= 3'd0;
    adjust_delayed_q    <= 1'b0;
end else begin

   if (adjust_delayed_q)
       adjust_delayed_q    <= 1'b0;
   else if (bit_edge_w && (sample_cnt_q != 3'd0) && (state_q < STATE_TX_SYNC))
       sample_cnt_q        <= 3'd0;

   else if (bit_edge_w && (sample_cnt_q == 3'd0) && (state_q < STATE_TX_SYNC)) begin

       adjust_delayed_q    <= 1'b1;
       if(sample_cnt_q == SAMPLE_RATE) 
           sample_cnt_q <= 'b0;
        else
          sample_cnt_q  <= sample_cnt_q + 'd1;
   end else begin
     if(sample_cnt_q == SAMPLE_RATE)
         sample_cnt_q   <= 'b0;
     else
         sample_cnt_q   <= sample_cnt_q + 'd1;
   end
end

assign sample_w = (sample_cnt_q == 'd0);




reg rxd_last_j_q;






always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    rxd_last_j_q  <= 1'b0;
else if ((state_q == STATE_IDLE) || sample_w)
    rxd_last_j_q  <= in_j_w;

assign bit_transition_w = sample_w ? rxd_last_j_q ^ in_j_w : 1'b0;




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    ones_count_q <= 3'd1;

else if (state_q == STATE_IDLE)
    ones_count_q <= 3'd1;

else if ((state_q == STATE_RX_ACTIVE) && sample_w)
begin
    if (bit_transition_w)
        ones_count_q <= 3'b0;
    else
        ones_count_q <= ones_count_q + 3'd1;
end

else if ((state_q == STATE_TX_ACTIVE) && sample_w)
begin

    if (!data_q[0] || bit_stuff_bit_w)
        ones_count_q <= 3'b0;
    else
        ones_count_q <= ones_count_q + 3'd1;
end

assign bit_stuff_bit_w     = (ones_count_q == 3'd6);
assign next_is_bit_stuff_w = (ones_count_q == 3'd5) && !bit_transition_w;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    bit_count_q <= 3'b0;
else if ((state_q == STATE_IDLE) || (state_q == STATE_RX_SYNC_K))
    bit_count_q <= 3'b0;
else if ((state_q == STATE_RX_ACTIVE || state_q == STATE_TX_ACTIVE) && sample_w && !bit_stuff_bit_w)
    bit_count_q <= bit_count_q + 3'd1;
else if (((state_q == STATE_TX_SYNC) || (state_q == STATE_RX_SYNC_J)) && sample_w)
    bit_count_q <= bit_count_q + 3'd1;




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

else if (state_q == STATE_IDLE)
    data_q  <= 8'b00101010;
else if ((state_q == STATE_RX_ACTIVE) && sample_w && !bit_stuff_bit_w)
    data_q  <= {~bit_transition_w, data_q[7:1]};
else if ((state_q == STATE_TX_SYNC) && sample_w)
begin
    if (bit_count_q == 3'd7)
        data_q  <= utmi_data_out_i;
    else
        data_q  <= {~bit_transition_w, data_q[7:1]};
end    
else if ((state_q == STATE_TX_ACTIVE) && sample_w && !bit_stuff_bit_w)
begin
    if (bit_count_q == 3'd7)
        data_q  <= utmi_data_out_i;
    else
        data_q  <= {~bit_transition_w, data_q[7:1]};
end


assign utmi_rxactive_o = (state_q == STATE_RX_ACTIVE);

assign utmi_data_in_o  = data_q;




reg rx_ready_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    rx_ready_q <= 1'b0;
else if ((state_q == STATE_RX_ACTIVE) && sample_w && (bit_count_q == 3'd7) && !bit_stuff_bit_w)
    rx_ready_q <= 1'b1;
else
    rx_ready_q <= 1'b0;

assign utmi_rxvalid_o  = rx_ready_q;




reg tx_ready_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    tx_ready_q <= 1'b0;
else if ((state_q == STATE_TX_SYNC) && sample_w && (bit_count_q == 3'd7))
    tx_ready_q <= 1'b1;
else if ((state_q == STATE_TX_ACTIVE) && sample_w && !bit_stuff_bit_w && (bit_count_q == 3'd7) && !send_eop_q)
    tx_ready_q <= 1'b1;
else
    tx_ready_q <= 1'b0;

assign utmi_txready_o  = tx_ready_q;




always @ (negedge rstn_i or negedge clk_i)
if (!rstn_i)
    send_eop_q  <= 1'b0;
else if ((state_q == STATE_TX_ACTIVE) && !utmi_txvalid_i)
    send_eop_q  <= 1'b1;
else if (state_q == STATE_TX_EOP0)
    send_eop_q  <= 1'b0;




wire out_bit_w = sample_w ? data_q[0] : 1'bz;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
begin
    out_dp_q <= 1'b0;
    out_dn_q <= 1'b0;
    rx_en_q  <= 1'b1;
end
else if (state_q == STATE_IDLE)
begin

    out_dp_q <= 1'b1;
    out_dn_q <= 1'b0;

    if (utmi_txvalid_i || usb_reset_assert_w)
        rx_en_q <= 1'b0;
    else
        rx_en_q <= 1'b1;
end
else if ((state_q == STATE_TX_SYNC) && sample_w)
begin
    out_dp_q <= data_q[0];
    out_dn_q <= ~data_q[0];
end
else if ((state_q == STATE_TX_ACTIVE || state_q == STATE_TX_EOP_STUFF) && sample_w)
begin

    if (!data_q[0] || bit_stuff_bit_w)
    begin
        out_dp_q <= ~out_dp_q;
        out_dn_q <= ~out_dn_q;
    end
end
else if ((state_q == STATE_TX_EOP0 || state_q == STATE_TX_EOP1) && sample_w)
begin

    out_dp_q <= 1'b0;
    out_dn_q <= 1'b0;
end
else if ((state_q == STATE_TX_EOP2) && sample_w)
begin

    out_dp_q <= 1'b1;
    out_dn_q <= 1'b0;


    rx_en_q <= 1'b1;
end
else if (state_q == STATE_TX_RST)
begin

    out_dp_q <= 1'b0;
    out_dn_q <= 1'b0;
end




reg [6:0] se0_cnt_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    se0_cnt_q <= 7'b0;
else if (in_se0_w)
begin
    if (se0_cnt_q != 7'd127)
        se0_cnt_q <= se0_cnt_q + 7'd1;
end    
else
    se0_cnt_q <= 7'b0;

assign usb_reset_detect_o = (se0_cnt_q == 7'd127);





assign usb_tx_oen_o = rx_en_q;


assign usb_tx_dp_o  = out_dp_q;
assign usb_tx_dn_o  = out_dn_q;


assign in_dp_w = usb_rx_dp_i;
assign in_dn_w = usb_rx_dn_i;


assign in_rx_w = usb_rx_rcv_i;


assign usb_en_o = utmi_termselect_i;


endmodule
module usb_fs_phy



#(
     parameter USB_CLK_FREQ     = 60000000
)

(

     input           clk_i
    ,input           rstn_i
    ,input  [  7:0]  utmi_data_out_i
    ,input           utmi_txvalid_i
    ,input  [  1:0]  utmi_op_mode_i
    ,input  [  1:0]  utmi_xcvrselect_i
    ,input           utmi_termselect_i
    ,input           utmi_dppulldown_i
    ,input           utmi_dmpulldown_i
    ,input           usb_rx_rcv_i
    ,input           usb_rx_dp_i
    ,input           usb_rx_dn_i
    ,input           usb_reset_assert_i


    ,output [  7:0]  utmi_data_in_o
    ,output          utmi_txready_o
    ,output          utmi_rxvalid_o
    ,output          utmi_rxactive_o
    ,output          utmi_rxerror_o
    ,output [  1:0]  utmi_linestate_o
    ,output          usb_tx_dp_o
    ,output          usb_tx_dn_o
    ,output          usb_tx_oen_o
    ,output          usb_reset_detect_o
    ,output          usb_en_o
);









localparam SAMPLE_RATE       = (USB_CLK_FREQ == 60000000) ? 3'd4 : 3'd3;




reg         rx_en_q;




reg         out_dp_q;
reg         out_dn_q;

wire        in_dp_w;
wire        in_dn_w;
wire        in_rx_w;

wire        in_j_w;
wire        in_k_w;
wire        in_se0_w;
wire        in_invalid_w;

wire        sample_w;

wire        bit_edge_w;
wire        bit_transition_w;

reg [2:0]   bit_count_q;
reg [2:0]   ones_count_q;
reg [7:0]   data_q;
reg         send_eop_q;

reg         sync_j_detected_q;

wire        bit_stuff_bit_w;
wire        next_is_bit_stuff_w;

wire        usb_reset_assert_w = usb_reset_assert_i | 
                                (utmi_xcvrselect_i == 2'b00 && 
                                 utmi_termselect_i == 1'b0  && 
                                 utmi_op_mode_i    == 2'b10 && 
                                 utmi_dppulldown_i && 
                                 utmi_dmpulldown_i);




reg         rx_dp_ms;
reg         rx_dn_ms;
reg         rxd_ms;


always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
begin
    rx_dp_ms <= 1'b0;
    rx_dn_ms <= 1'b0;
    rxd_ms   <= 1'b0;
end
else
begin
    rx_dp_ms <= in_dp_w;
    rx_dn_ms <= in_dn_w;
    rxd_ms   <= in_rx_w;
end




reg         rx_dp0_q;
reg         rx_dn0_q;
reg         rx_dp1_q;
reg         rx_dn1_q;
reg         rx_dp_q;
reg         rx_dn_q;
reg         rxd0_q;
reg         rxd1_q;
reg         rxd_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
begin
    rx_dp0_q    <= 1'b0;
    rx_dn0_q    <= 1'b0;
    rx_dp1_q    <= 1'b0;
    rx_dn1_q    <= 1'b0;
    rx_dp_q     <= 1'b0;
    rx_dn_q     <= 1'b0;
    rxd0_q      <= 1'b0;
    rxd1_q      <= 1'b0;
    rxd_q       <= 1'b0;
end
else
begin

    if (rx_dp0_q & rx_dp1_q)
        rx_dp_q     <= 1'b1;
    else if (!rx_dp0_q & !rx_dp1_q)
        rx_dp_q     <= 1'b0;

    if (rx_dn0_q & rx_dn1_q)
        rx_dn_q     <= 1'b1;
    else if (!rx_dn0_q & !rx_dn1_q)
        rx_dn_q     <= 1'b0;

    if (rxd0_q & rxd1_q)
        rxd_q     <= 1'b1;
    else if (!rxd0_q & !rxd1_q)
        rxd_q     <= 1'b0;


    rx_dp1_q    <= rx_dp0_q;
    rx_dp0_q    <= rx_dp_ms;

    rx_dn1_q    <= rx_dn0_q;
    rx_dn0_q    <= rx_dn_ms;

    rxd1_q      <= rxd0_q;
    rxd0_q      <= rxd_ms;
end






assign in_j_w       = in_se0_w ? 1'b0 :  rxd_q;
assign in_k_w       = in_se0_w ? 1'b0 : ~rxd_q;
assign in_se0_w     = (!rx_dp_q & !rx_dn_q);
assign in_invalid_w = (rx_dp_q & rx_dn_q);


assign utmi_linestate_o = usb_tx_oen_o ? {rx_dn_q, rx_dp_q} : {usb_tx_dn_o, usb_tx_dp_o};




localparam STATE_W              = 4;
localparam STATE_IDLE           = 4'd0;
localparam STATE_RX_DETECT      = 4'd1;
localparam STATE_RX_SYNC_J      = 4'd2;
localparam STATE_RX_SYNC_K      = 4'd3;
localparam STATE_RX_ACTIVE      = 4'd4;
localparam STATE_RX_EOP0        = 4'd5;
localparam STATE_RX_EOP1        = 4'd6;
localparam STATE_TX_SYNC        = 4'd7;
localparam STATE_TX_ACTIVE      = 4'd8;
localparam STATE_TX_EOP_STUFF   = 4'd9;
localparam STATE_TX_EOP0        = 4'd10;
localparam STATE_TX_EOP1        = 4'd11;
localparam STATE_TX_EOP2        = 4'd12;
localparam STATE_TX_RST         = 4'd13;


reg [STATE_W-1:0] state_q;

reg [STATE_W-1:0] next_state_r;
always @ *
begin
    next_state_r = state_q;

    case (state_q)



    STATE_IDLE :
    begin
        if (in_k_w)
            next_state_r    = STATE_RX_DETECT;
        else if (utmi_txvalid_i)
            next_state_r    = STATE_TX_SYNC;
        else if (usb_reset_assert_w)
            next_state_r    = STATE_TX_RST;
    end



    STATE_RX_DETECT :
    begin
        if (in_k_w && sample_w)
            next_state_r    = STATE_RX_SYNC_K;
        else if (sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_RX_SYNC_J :
    begin
        if (in_k_w && sample_w)
            next_state_r    = STATE_RX_SYNC_K;

        else if ((bit_count_q == 3'd1) && sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_RX_SYNC_K :
    begin


        if (sync_j_detected_q && in_k_w && sample_w)
            next_state_r    = STATE_RX_ACTIVE;

        else if (!sync_j_detected_q && in_k_w && sample_w)
            next_state_r    = STATE_IDLE;
        else if (in_j_w && sample_w)
            next_state_r    = STATE_RX_SYNC_J;
    end



    STATE_RX_ACTIVE :
    begin
        if (in_se0_w && sample_w)
            next_state_r    = STATE_RX_EOP0;

        else if (in_invalid_w && sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_RX_EOP0 :
    begin
        if (in_se0_w && sample_w)
            next_state_r    = STATE_RX_EOP1;

        else if (sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_RX_EOP1 :
    begin

        if (in_j_w && sample_w)
            next_state_r    = STATE_IDLE;

        else if (sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_TX_SYNC :
    begin
        if (bit_count_q == 3'd7 && sample_w)
            next_state_r    = STATE_TX_ACTIVE;
    end



    STATE_TX_ACTIVE :
    begin
        if (bit_count_q == 3'd7 && sample_w && (!utmi_txvalid_i || send_eop_q) && !bit_stuff_bit_w)
        begin

            if (next_is_bit_stuff_w)
                next_state_r    = STATE_TX_EOP_STUFF;
            else
                next_state_r    = STATE_TX_EOP0;
        end
    end



    STATE_TX_EOP_STUFF :
    begin
        if (sample_w)
            next_state_r    = STATE_TX_EOP0;
    end



    STATE_TX_EOP0 :
    begin
        if (sample_w)
            next_state_r    = STATE_TX_EOP1;
    end



    STATE_TX_EOP1 :
    begin
        if (sample_w)
            next_state_r    = STATE_TX_EOP2;
    end



    STATE_TX_EOP2 :
    begin
        if (sample_w)
            next_state_r    = STATE_IDLE;
    end



    STATE_TX_RST :
    begin
        if (!usb_reset_assert_w)
            next_state_r    = STATE_IDLE;
    end
    default:
        ;
   endcase
end


always @ (negedge rstn_i or posedge clk_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)
    sync_j_detected_q  <= 1'b0;

else if (state_q == STATE_IDLE)
    sync_j_detected_q  <= 1'b0;

else if (state_q == STATE_RX_SYNC_J)
    sync_j_detected_q  <= 1'b1;




reg rx_error_q;

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

else if (ones_count_q == 3'd7)
    rx_error_q  <= 1'b1;

else if (in_invalid_w && sample_w)
    rx_error_q  <= 1'b1;

else if ((state_q == STATE_RX_SYNC_K) && !sync_j_detected_q && in_k_w && sample_w)
    rx_error_q  <= 1'b1;
else
    rx_error_q  <= 1'b0;

assign utmi_rxerror_o = rx_error_q;




reg rxd_last_q;

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

assign bit_edge_w = rxd_last_q ^ in_j_w;




reg [2:0] sample_cnt_q;
reg       adjust_delayed_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i) begin
    sample_cnt_q        <= 3'd0;
    adjust_delayed_q    <= 1'b0;
end else begin

   if (adjust_delayed_q)
       adjust_delayed_q    <= 1'b0;
   else if (bit_edge_w && (sample_cnt_q != 3'd0) && (state_q < STATE_TX_SYNC))
       sample_cnt_q        <= 3'd0;

   else if (bit_edge_w && (sample_cnt_q == 3'd0) && (state_q < STATE_TX_SYNC)) begin

       adjust_delayed_q    <= 1'b1;
       if(sample_cnt_q == SAMPLE_RATE) 
           sample_cnt_q <= 'b0;
        else
          sample_cnt_q  <= sample_cnt_q + 'd1;
   end else begin
     if(sample_cnt_q == SAMPLE_RATE)
         sample_cnt_q   <= 'b0;
     else
         sample_cnt_q   <= sample_cnt_q + 'd1;
   end
end

assign sample_w = (sample_cnt_q == 'd0);




reg rxd_last_j_q;






always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    rxd_last_j_q  <= 1'b0;
else if ((state_q == STATE_IDLE) || sample_w)
    rxd_last_j_q  <= in_j_w;

assign bit_transition_w = sample_w ? rxd_last_j_q ^ in_j_w : 1'b0;




always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    ones_count_q <= 3'd1;

else if (state_q == STATE_IDLE)
    ones_count_q <= 3'd1;

else if ((state_q == STATE_RX_ACTIVE) && sample_w)
begin
    if (bit_transition_w)
        ones_count_q <= 3'b0;
    else
        ones_count_q <= ones_count_q + 3'd1;
end

else if ((state_q == STATE_TX_ACTIVE) && sample_w)
begin

    if (!data_q[0] || bit_stuff_bit_w)
        ones_count_q <= 3'b0;
    else
        ones_count_q <= ones_count_q + 3'd1;
end

assign bit_stuff_bit_w     = (ones_count_q == 3'd6);
assign next_is_bit_stuff_w = (ones_count_q == 3'd5) && !bit_transition_w;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    bit_count_q <= 3'b0;
else if ((state_q == STATE_IDLE) || (state_q == STATE_RX_SYNC_K))
    bit_count_q <= 3'b0;
else if ((state_q == STATE_RX_ACTIVE || state_q == STATE_TX_ACTIVE) && sample_w && !bit_stuff_bit_w)
    bit_count_q <= bit_count_q + 3'd1;
else if (((state_q == STATE_TX_SYNC) || (state_q == STATE_RX_SYNC_J)) && sample_w)
    bit_count_q <= bit_count_q + 3'd1;




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

else if (state_q == STATE_IDLE)
    data_q  <= 8'b00101010;
else if ((state_q == STATE_RX_ACTIVE) && sample_w && !bit_stuff_bit_w)
    data_q  <= {~bit_transition_w, data_q[7:1]};
else if ((state_q == STATE_TX_SYNC) && sample_w)
begin
    if (bit_count_q == 3'd7)
        data_q  <= utmi_data_out_i;
    else
        data_q  <= {~bit_transition_w, data_q[7:1]};
end    
else if ((state_q == STATE_TX_ACTIVE) && sample_w && !bit_stuff_bit_w)
begin
    if (bit_count_q == 3'd7)
        data_q  <= utmi_data_out_i;
    else
        data_q  <= {~bit_transition_w, data_q[7:1]};
end


assign utmi_rxactive_o = (state_q == STATE_RX_ACTIVE);

assign utmi_data_in_o  = data_q;




reg rx_ready_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    rx_ready_q <= 1'b0;
else if ((state_q == STATE_RX_ACTIVE) && sample_w && (bit_count_q == 3'd7) && !bit_stuff_bit_w)
    rx_ready_q <= 1'b1;
else
    rx_ready_q <= 1'b0;

assign utmi_rxvalid_o  = rx_ready_q;




reg tx_ready_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    tx_ready_q <= 1'b0;
else if ((state_q == STATE_TX_SYNC) && sample_w && (bit_count_q == 3'd7))
    tx_ready_q <= 1'b1;
else if ((state_q == STATE_TX_ACTIVE) && sample_w && !bit_stuff_bit_w && (bit_count_q == 3'd7) && !send_eop_q)
    tx_ready_q <= 1'b1;
else
    tx_ready_q <= 1'b0;

assign utmi_txready_o  = tx_ready_q;




always @ (negedge rstn_i or negedge clk_i)
if (!rstn_i)
    send_eop_q  <= 1'b0;
else if ((state_q == STATE_TX_ACTIVE) && !utmi_txvalid_i)
    send_eop_q  <= 1'b1;
else if (state_q == STATE_TX_EOP0)
    send_eop_q  <= 1'b0;




wire out_bit_w = sample_w ? data_q[0] : 1'bz;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
begin
    out_dp_q <= 1'b0;
    out_dn_q <= 1'b0;
    rx_en_q  <= 1'b1;
end
else if (state_q == STATE_IDLE)
begin

    out_dp_q <= 1'b1;
    out_dn_q <= 1'b0;

    if (utmi_txvalid_i || usb_reset_assert_w)
        rx_en_q <= 1'b0;
    else
        rx_en_q <= 1'b1;
end
else if ((state_q == STATE_TX_SYNC) && sample_w)
begin
    out_dp_q <= data_q[0];
    out_dn_q <= ~data_q[0];
end
else if ((state_q == STATE_TX_ACTIVE || state_q == STATE_TX_EOP_STUFF) && sample_w)
begin

    if (!data_q[0] || bit_stuff_bit_w)
    begin
        out_dp_q <= ~out_dp_q;
        out_dn_q <= ~out_dn_q;
    end
end
else if ((state_q == STATE_TX_EOP0 || state_q == STATE_TX_EOP1) && sample_w)
begin

    out_dp_q <= 1'b0;
    out_dn_q <= 1'b0;
end
else if ((state_q == STATE_TX_EOP2) && sample_w)
begin

    out_dp_q <= 1'b1;
    out_dn_q <= 1'b0;


    rx_en_q <= 1'b1;
end
else if (state_q == STATE_TX_RST)
begin

    out_dp_q <= 1'b0;
    out_dn_q <= 1'b0;
end




reg [6:0] se0_cnt_q;

always @ (posedge clk_i or negedge rstn_i)
if (!rstn_i)
    se0_cnt_q <= 7'b0;
else if (in_se0_w)
begin
    if (se0_cnt_q != 7'd127)
        se0_cnt_q <= se0_cnt_q + 7'd1;
end    
else
    se0_cnt_q <= 7'b0;

assign usb_reset_detect_o = (se0_cnt_q == 7'd127);





assign usb_tx_oen_o = rx_en_q;


assign usb_tx_dp_o  = out_dp_q;
assign usb_tx_dn_o  = out_dn_q;


assign in_dp_w = usb_rx_dp_i;
assign in_dn_w = usb_rx_dn_i;


assign in_rx_w = usb_rx_rcv_i;


assign usb_en_o = utmi_termselect_i;


endmodule