OpenCores
URL https://opencores.org/ocsvn/ulpi_wrapper/ulpi_wrapper/trunk

Subversion Repositories ulpi_wrapper

[/] [ulpi_wrapper/] [trunk/] [rtl/] [ulpi_wrapper.v] - Diff between revs 3 and 4

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 3 Rev 4
Line 1... Line 1...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//                        ULPI (Link) Wrapper
//                        ULPI (Link) Wrapper
//                              V0.1
//                              V1.0
//                        Ultra-Embedded.com
//                        Ultra-Embedded.com
//                          Copyright 2015
//                        Copyright 2015-2018
//
//
//                 Email: admin@ultra-embedded.com
//                 Email: admin@ultra-embedded.com
//
//
//                         License: GPL
//                         License: GPL
// If you would like a version with a more permissive license for
// If you would like a version with a more permissive license for
Line 40... Line 40...
module ulpi_wrapper
module ulpi_wrapper
(
(
    // ULPI Interface (PHY)
    // ULPI Interface (PHY)
    input             ulpi_clk60_i,
    input             ulpi_clk60_i,
    input             ulpi_rst_i,
    input             ulpi_rst_i,
    input  [7:0]      ulpi_data_i,
    input  [7:0]      ulpi_data_out_i,
    output [7:0]      ulpi_data_o,
    output [7:0]      ulpi_data_in_o,
    input             ulpi_dir_i,
    input             ulpi_dir_i,
    input             ulpi_nxt_i,
    input             ulpi_nxt_i,
    output            ulpi_stp_o,
    output            ulpi_stp_o,
 
 
    // Register access (Wishbone pipelined access type)
 
    // NOTE: Tie inputs to 0 if unused
 
    input [7:0]       reg_addr_i,
 
    input             reg_stb_i,
 
    input             reg_we_i,
 
    input [7:0]       reg_data_i,
 
    output [7:0]      reg_data_o,
 
    output            reg_ack_o,
 
 
 
    // UTMI Interface (SIE)
    // UTMI Interface (SIE)
    input             utmi_txvalid_i,
    input             utmi_txvalid_i,
    output            utmi_txready_o,
    output            utmi_txready_o,
    output            utmi_rxvalid_o,
    output            utmi_rxvalid_o,
    output            utmi_rxactive_o,
    output            utmi_rxactive_o,
    output            utmi_rxerror_o,
    output            utmi_rxerror_o,
    output [7:0]      utmi_data_o,
    output [7:0]      utmi_data_in_o,
    input  [7:0]      utmi_data_i,
    input  [7:0]      utmi_data_out_i,
    input  [1:0]      utmi_xcvrselect_i,
    input  [1:0]      utmi_xcvrselect_i,
    input             utmi_termselect_i,
    input             utmi_termselect_i,
    input  [1:0]      utmi_opmode_i,
    input  [1:0]      utmi_op_mode_i,
    input             utmi_dppulldown_i,
    input             utmi_dppulldown_i,
    input             utmi_dmpulldown_i,
    input             utmi_dmpulldown_i,
    output [1:0]      utmi_linestate_o
    output [1:0]      utmi_linestate_o
);
);
 
 
Line 99... Line 90...
reg         mode_update_q;
reg         mode_update_q;
reg [1:0]   xcvrselect_q;
reg [1:0]   xcvrselect_q;
reg         termselect_q;
reg         termselect_q;
reg [1:0]   opmode_q;
reg [1:0]   opmode_q;
reg         phy_reset_q;
reg         phy_reset_q;
reg         auto_wr_q;
 
reg         reg_wr_q;
 
 
 
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
if (ulpi_rst_i)
if (ulpi_rst_i)
begin
begin
    mode_update_q   <= 1'b0;
    mode_update_q   <= 1'b0;
Line 115... Line 104...
end
end
else
else
begin
begin
    xcvrselect_q    <= utmi_xcvrselect_i;
    xcvrselect_q    <= utmi_xcvrselect_i;
    termselect_q    <= utmi_termselect_i;
    termselect_q    <= utmi_termselect_i;
    opmode_q        <= utmi_opmode_i;
    opmode_q        <= utmi_op_mode_i;
 
 
    if (mode_update_q && (state_q == STATE_CMD) && (ulpi_data_o == REG_FUNC_CTRL))
    if (mode_update_q && (state_q == STATE_CMD) && (ulpi_data_in_o == REG_FUNC_CTRL))
    begin
    begin
        mode_update_q <= 1'b0;
        mode_update_q <= 1'b0;
        phy_reset_q   <= 1'b0;
        phy_reset_q   <= 1'b0;
    end
    end
    else if (opmode_q     != utmi_opmode_i     ||
    else if (opmode_q     != utmi_op_mode_i     ||
             termselect_q != utmi_termselect_i ||
             termselect_q != utmi_termselect_i ||
             xcvrselect_q != utmi_xcvrselect_i)
             xcvrselect_q != utmi_xcvrselect_i)
        mode_update_q <= 1'b1;
        mode_update_q <= 1'b1;
end
end
 
 
Line 147... Line 136...
else
else
begin
begin
    dppulldown_q    <= utmi_dppulldown_i;
    dppulldown_q    <= utmi_dppulldown_i;
    dmpulldown_q    <= utmi_dmpulldown_i;
    dmpulldown_q    <= utmi_dmpulldown_i;
 
 
    if (otg_update_q && (state_q == STATE_CMD) && (ulpi_data_o == REG_OTG_CTRL))
    if (otg_update_q && (state_q == STATE_CMD) && (ulpi_data_in_o == REG_OTG_CTRL))
        otg_update_q <= 1'b0;
        otg_update_q <= 1'b0;
    else if (dppulldown_q != utmi_dppulldown_i ||
    else if (dppulldown_q != utmi_dppulldown_i ||
             dmpulldown_q != utmi_dmpulldown_i)
             dmpulldown_q != utmi_dmpulldown_i)
        otg_update_q <= 1'b1;
        otg_update_q <= 1'b1;
end
end
Line 167... Line 156...
else
else
    ulpi_dir_q <= ulpi_dir_i;
    ulpi_dir_q <= ulpi_dir_i;
 
 
wire turnaround_w = ulpi_dir_q ^ ulpi_dir_i;
wire turnaround_w = ulpi_dir_q ^ ulpi_dir_i;
 
 
reg ulpi_rxcmd_q;
 
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
 
if (ulpi_rst_i)
 
    ulpi_rxcmd_q <= 1'b0;
 
// Switch to input with NXT asserted in turnaround cycle
 
else if (!ulpi_dir_q && ulpi_dir_i && ulpi_nxt_i)
 
    ulpi_rxcmd_q <= 1'b1;
 
// Switch to output (turnaround cycle)
 
else if (ulpi_dir_q && !ulpi_dir_i)
 
    ulpi_rxcmd_q <= 1'b0;
 
 
 
//-----------------------------------------------------------------
 
// Register Access
 
//-----------------------------------------------------------------
 
reg       reg_wr_pending_q;
 
reg       reg_rd_pending_q;
 
reg [7:0] reg_addr_q;
 
reg [7:0] reg_data_q;
 
reg       reg_ack_q;
 
 
 
wire reg_ready_w = (reg_wr_pending_q && state_q == STATE_REG && ulpi_nxt_i && reg_wr_q) ||
 
                   (reg_rd_pending_q && !turnaround_w && ulpi_dir_i && !ulpi_rxcmd_q);
 
 
 
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
 
if (ulpi_rst_i)
 
begin
 
    reg_wr_pending_q    <= 1'b0;
 
    reg_rd_pending_q    <= 1'b0;
 
    reg_addr_q          <= 8'b0;
 
end
 
else if (reg_stb_i)
 
begin
 
    reg_addr_q          <= reg_addr_i;
 
    reg_wr_pending_q    <= reg_we_i;
 
    reg_rd_pending_q    <= ~reg_we_i;
 
end
 
else if (reg_ready_w)
 
begin
 
    reg_wr_pending_q    <= 1'b0;
 
    reg_rd_pending_q    <= 1'b0;
 
end
 
 
 
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
 
if (ulpi_rst_i)
 
    reg_data_q  <= 8'b0;
 
else if (reg_stb_i && reg_we_i)
 
    reg_data_q  <= reg_data_i;
 
 
 
assign reg_data_o = utmi_data_o;
 
 
 
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
 
if (ulpi_rst_i)
 
    reg_ack_q  <= 1'b0;
 
else
 
    reg_ack_q  <= reg_ready_w;
 
 
 
assign reg_ack_o = reg_ack_q;
 
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Rx - Tx delay
// Rx - Tx delay
//-----------------------------------------------------------------
//-----------------------------------------------------------------
localparam TX_DELAY_W       = 3;
localparam TX_DELAY_W       = 3;
localparam TX_START_DELAY   = 3'd7;
localparam TX_START_DELAY   = 3'd7;
Line 269... Line 200...
else
else
begin
begin
    // Push
    // Push
    if (utmi_txvalid_i && utmi_txready_o)
    if (utmi_txvalid_i && utmi_txready_o)
    begin
    begin
        tx_buffer_q[tx_wr_idx_q] <= utmi_data_i;
        tx_buffer_q[tx_wr_idx_q] <= utmi_data_out_i;
        tx_valid_q[tx_wr_idx_q]  <= 1'b1;
        tx_valid_q[tx_wr_idx_q]  <= 1'b1;
 
 
        tx_wr_idx_q <= tx_wr_idx_q + 1'b1;
        tx_wr_idx_q <= tx_wr_idx_q + 1'b1;
    end
    end
 
 
Line 309... Line 240...
reg                 utmi_rxactive_q;
reg                 utmi_rxactive_q;
reg [1:0]           utmi_linestate_q;
reg [1:0]           utmi_linestate_q;
reg [7:0]           utmi_data_q;
reg [7:0]           utmi_data_q;
 
 
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
begin
 
    if (ulpi_rst_i)
    if (ulpi_rst_i)
    begin
    begin
        state_q             <= STATE_IDLE;
        state_q             <= STATE_IDLE;
        ulpi_data_q         <= 8'b0;
        ulpi_data_q         <= 8'b0;
        data_q              <= 8'b0;
        data_q              <= 8'b0;
        ulpi_stp_q          <= 1'b0;
    ulpi_stp_q          <= 1'b1;
 
 
        utmi_rxvalid_q      <= 1'b0;
        utmi_rxvalid_q      <= 1'b0;
        utmi_rxerror_q      <= 1'b0;
        utmi_rxerror_q      <= 1'b0;
        utmi_rxactive_q     <= 1'b0;
        utmi_rxactive_q     <= 1'b0;
        utmi_linestate_q    <= 2'b0;
        utmi_linestate_q    <= 2'b0;
        utmi_data_q         <= 8'b0;
        utmi_data_q         <= 8'b0;
        auto_wr_q           <= 1'b0;
 
        reg_wr_q            <= 1'b0;
 
    end
    end
    else
    else
    begin
    begin
        ulpi_stp_q          <= 1'b0;
        ulpi_stp_q          <= 1'b0;
        utmi_rxvalid_q      <= 1'b0;
        utmi_rxvalid_q      <= 1'b0;
 
 
        if (!turnaround_w)
    // Turnaround: Input + NXT - set RX_ACTIVE
 
    if (turnaround_w && ulpi_dir_i && ulpi_nxt_i)
 
    begin
 
        utmi_rxactive_q <= 1'b1;
 
    end
 
    // Turnaround: Input -> Output - reset RX_ACTIVE
 
    else if (turnaround_w && !ulpi_dir_i)
 
    begin
 
        utmi_rxactive_q <= 1'b0;
 
    end
 
    // Non-turnaround cycle
 
    else if (!turnaround_w)
        begin
        begin
            //-----------------------------------------------------------------
            //-----------------------------------------------------------------
            // Input: RX_DATA
        // Input: RX_CMD (status)
            //-----------------------------------------------------------------
            //-----------------------------------------------------------------
            if (ulpi_dir_i && ulpi_rxcmd_q)
        if (ulpi_dir_i && !ulpi_nxt_i)
            begin
            begin
                utmi_rxvalid_q  <= ulpi_nxt_i;
            // Phy status
                utmi_data_q     <= ulpi_data_i;
            utmi_linestate_q <= ulpi_data_out_i[1:0];
 
 
                // No valid data, extract phy status 
            case (ulpi_data_out_i[5:4])
                if (!ulpi_nxt_i)
 
                begin
 
                    utmi_linestate_q <= ulpi_data_i[1:0];
 
 
 
                    case (ulpi_data_i[5:4])
 
                    2'b00:
                    2'b00:
                    begin
                    begin
                        utmi_rxactive_q <= 1'b0;
                        utmi_rxactive_q <= 1'b0;
                        utmi_rxerror_q  <= 1'b0;
                        utmi_rxerror_q  <= 1'b0;
                    end
                    end
Line 365... Line 299...
                    end
                    end
                    default:
                    default:
                        ; // HOST_DISCONNECTED
                        ; // HOST_DISCONNECTED
                    endcase
                    endcase
                end
                end
                // RxValid (so force RxActive)
 
                else
 
                    utmi_rxactive_q <= 1'b1;
 
            end
 
            //-----------------------------------------------------------------
            //-----------------------------------------------------------------
            // Input: REG_DATA
        // Input: RX_DATA
            //-----------------------------------------------------------------
            //-----------------------------------------------------------------
            else if (ulpi_dir_i)
        else if (ulpi_dir_i && ulpi_nxt_i)
            begin
            begin
                utmi_rxvalid_q  <= 1'b0;
            utmi_rxvalid_q  <= 1'b1;
                utmi_data_q     <= ulpi_data_i;
            utmi_data_q     <= ulpi_data_out_i;
            end
            end
            //-----------------------------------------------------------------
            //-----------------------------------------------------------------
            // Output
            // Output
            //-----------------------------------------------------------------
            //-----------------------------------------------------------------
            else
        else if (!ulpi_dir_i)
            begin
            begin
                // IDLE: Pending mode update
                // IDLE: Pending mode update
                if ((state_q == STATE_IDLE) && mode_update_q)
                if ((state_q == STATE_IDLE) && mode_update_q)
                begin
                begin
                    data_q      <= {1'b0, 1'b1, phy_reset_q, opmode_q, termselect_q, xcvrselect_q};
                    data_q      <= {1'b0, 1'b1, phy_reset_q, opmode_q, termselect_q, xcvrselect_q};
                    ulpi_data_q <= REG_FUNC_CTRL;
                    ulpi_data_q <= REG_FUNC_CTRL;
 
 
                    state_q     <= STATE_CMD;
                    state_q     <= STATE_CMD;
                    auto_wr_q   <= 1'b1;
 
                    reg_wr_q    <= 1'b0;
 
                end
                end
                // IDLE: Pending OTG control update
                // IDLE: Pending OTG control update
                else if ((state_q == STATE_IDLE) && otg_update_q)
                else if ((state_q == STATE_IDLE) && otg_update_q)
                begin
                begin
                    data_q      <= {5'b0, dmpulldown_q, dppulldown_q, 1'b0};
                    data_q      <= {5'b0, dmpulldown_q, dppulldown_q, 1'b0};
                    ulpi_data_q <= REG_OTG_CTRL;
                    ulpi_data_q <= REG_OTG_CTRL;
 
 
                    state_q     <= STATE_CMD;
                    state_q     <= STATE_CMD;
                    auto_wr_q   <= 1'b1;
 
                    reg_wr_q    <= 1'b0;
 
                end
 
                // IDLE: Pending register access
 
                else if ((state_q == STATE_IDLE) && (reg_wr_pending_q || reg_rd_pending_q))
 
                begin
 
                    data_q      <= reg_data_q;
 
 
 
                    if (reg_wr_pending_q)
 
                        ulpi_data_q <= REG_WRITE | {2'b0, reg_addr_q[5:0]};
 
                    else
 
                        ulpi_data_q <= REG_READ  | {2'b0, reg_addr_q[5:0]};
 
 
 
                    state_q     <= STATE_CMD;
 
                    auto_wr_q   <= 1'b0;
 
                    reg_wr_q    <= reg_wr_pending_q;
 
                end
                end
                // IDLE: Pending transmit
                // IDLE: Pending transmit
                else if ((state_q == STATE_IDLE) && utmi_tx_ready_w)
                else if ((state_q == STATE_IDLE) && utmi_tx_ready_w)
                begin
                begin
                    ulpi_data_q <= REG_TRANSMIT | {4'b0, utmi_tx_data_w[3:0]};
                    ulpi_data_q <= REG_TRANSMIT | {4'b0, utmi_tx_data_w[3:0]};
                    state_q     <= STATE_DATA;
                    state_q     <= STATE_DATA;
                    auto_wr_q   <= 1'b0;
 
                    reg_wr_q    <= 1'b0;
 
                end
                end
                // Command
                // Command
                else if ((state_q == STATE_CMD) && ulpi_nxt_i)
                else if ((state_q == STATE_CMD) && ulpi_nxt_i)
                begin
                begin
                    // Read Register
 
                    if (!reg_wr_q && !auto_wr_q)
 
                    begin
 
                        state_q     <= STATE_IDLE;
 
                        ulpi_data_q <= 8'b0;
 
                    end
 
                    // Write Register
                    // Write Register
                    else
 
                    begin
 
                        state_q     <= STATE_REG;
                        state_q     <= STATE_REG;
                        ulpi_data_q <= data_q;
                        ulpi_data_q <= data_q;
                    end
                    end
                end
 
                // Data (register write)
                // Data (register write)
                else if (state_q == STATE_REG && ulpi_nxt_i)
                else if (state_q == STATE_REG && ulpi_nxt_i)
                begin
                begin
                    state_q       <= STATE_IDLE;
                    state_q       <= STATE_IDLE;
                    ulpi_data_q   <= 8'b0;  // IDLE
                    ulpi_data_q   <= 8'b0;  // IDLE
                    ulpi_stp_q    <= 1'b1;
                    ulpi_stp_q    <= 1'b1;
                    auto_wr_q     <= 1'b0;
 
                    reg_wr_q      <= 1'b0;
 
                end
                end
                // Data
                // Data
                else if (state_q == STATE_DATA && ulpi_nxt_i)
                else if (state_q == STATE_DATA && ulpi_nxt_i)
                begin
                begin
                    // End of packet
                    // End of packet
Line 468... Line 367...
                    end
                    end
                end
                end
            end
            end
        end
        end
    end
    end
end
 
 
 
// Accept from buffer
// Accept from buffer
assign utmi_tx_accept_w = ((state_q == STATE_IDLE) && !(mode_update_q || otg_update_q || turnaround_w || reg_wr_pending_q || reg_rd_pending_q) && !ulpi_dir_i) ||
assign utmi_tx_accept_w = ((state_q == STATE_IDLE) && !(mode_update_q || otg_update_q || turnaround_w) && !ulpi_dir_i) ||
                          (state_q == STATE_DATA && ulpi_nxt_i && !ulpi_dir_i);
                          (state_q == STATE_DATA && ulpi_nxt_i && !ulpi_dir_i);
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Assignments
// Assignments
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// ULPI Interface
// ULPI Interface
assign ulpi_data_o          = ulpi_data_q;
assign ulpi_data_in_o       = ulpi_data_q;
assign ulpi_stp_o           = ulpi_stp_q;
assign ulpi_stp_o           = ulpi_stp_q;
 
 
// UTMI Interface
// UTMI Interface
assign utmi_linestate_o     = utmi_linestate_q;
assign utmi_linestate_o     = utmi_linestate_q;
assign utmi_data_o          = utmi_data_q;
assign utmi_data_in_o       = utmi_data_q;
assign utmi_rxerror_o       = utmi_rxerror_q;
assign utmi_rxerror_o       = utmi_rxerror_q;
assign utmi_rxactive_o      = utmi_rxactive_q;
assign utmi_rxactive_o      = utmi_rxactive_q;
assign utmi_rxvalid_o       = utmi_rxvalid_q;
assign utmi_rxvalid_o       = utmi_rxvalid_q;
 
 
 
 
 
 
endmodule
endmodule
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.