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

Subversion Repositories ulpi_wrapper

[/] [ulpi_wrapper/] [trunk/] [rtl/] [ulpi_wrapper.v] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ultra_embe
//-----------------------------------------------------------------
2
//                        ULPI (Link) Wrapper
3 5 ultra_embe
//                              V1.1
4 2 ultra_embe
//                        Ultra-Embedded.com
5 4 ultra_embe
//                        Copyright 2015-2018
6 2 ultra_embe
//
7
//                 Email: admin@ultra-embedded.com
8
//
9
//                         License: GPL
10
// If you would like a version with a more permissive license for
11
// use in closed source commercial applications please contact me
12
// for details.
13
//-----------------------------------------------------------------
14
//
15
// This file is open source HDL; you can redistribute it and/or 
16
// modify it under the terms of the GNU General Public License as 
17
// published by the Free Software Foundation; either version 2 of 
18
// the License, or (at your option) any later version.
19
//
20
// This file is distributed in the hope that it will be useful,
21
// but WITHOUT ANY WARRANTY; without even the implied warranty of
22
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
// GNU General Public License for more details.
24
//
25
// You should have received a copy of the GNU General Public 
26
// License along with this file; if not, write to the Free Software
27
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
28
// USA
29
//-----------------------------------------------------------------
30
 
31
//-----------------------------------------------------------------
32
// Module: UTMI+ to ULPI Wrapper
33
//
34
// Description:
35
//   - Converts from UTMI interface to reduced pin count ULPI.
36
//   - No support for low power mode.
37
//   - I/O synchronous to 60MHz ULPI clock input (from PHY)
38
//   - Tested against SMSC/Microchip USB3300 in device mode.
39
//-----------------------------------------------------------------
40
module ulpi_wrapper
41
(
42
    // ULPI Interface (PHY)
43
    input             ulpi_clk60_i,
44
    input             ulpi_rst_i,
45 4 ultra_embe
    input  [7:0]      ulpi_data_out_i,
46
    output [7:0]      ulpi_data_in_o,
47 2 ultra_embe
    input             ulpi_dir_i,
48
    input             ulpi_nxt_i,
49
    output            ulpi_stp_o,
50
 
51
    // UTMI Interface (SIE)
52
    input             utmi_txvalid_i,
53
    output            utmi_txready_o,
54
    output            utmi_rxvalid_o,
55
    output            utmi_rxactive_o,
56
    output            utmi_rxerror_o,
57 4 ultra_embe
    output [7:0]      utmi_data_in_o,
58
    input  [7:0]      utmi_data_out_i,
59 2 ultra_embe
    input  [1:0]      utmi_xcvrselect_i,
60
    input             utmi_termselect_i,
61 4 ultra_embe
    input  [1:0]      utmi_op_mode_i,
62 2 ultra_embe
    input             utmi_dppulldown_i,
63
    input             utmi_dmpulldown_i,
64
    output [1:0]      utmi_linestate_o
65
);
66
 
67
//-----------------------------------------------------------------
68
// States
69
//-----------------------------------------------------------------
70
localparam STATE_W          = 2;
71
localparam STATE_IDLE       = 2'd0;
72
localparam STATE_CMD        = 2'd1;
73
localparam STATE_DATA       = 2'd2;
74 3 ultra_embe
localparam STATE_REG        = 2'd3;
75 2 ultra_embe
 
76
reg [STATE_W-1:0]   state_q;
77
 
78
//-----------------------------------------------------------------
79 3 ultra_embe
// Local Params
80
//-----------------------------------------------------------------
81
localparam REG_FUNC_CTRL = 8'h84;
82
localparam REG_OTG_CTRL  = 8'h8a;
83
localparam REG_TRANSMIT  = 8'h40;
84
localparam REG_WRITE     = 8'h80;
85
localparam REG_READ      = 8'hC0;
86
 
87
//-----------------------------------------------------------------
88 2 ultra_embe
// UTMI Mode Select
89
//-----------------------------------------------------------------
90
reg         mode_update_q;
91
reg [1:0]   xcvrselect_q;
92
reg         termselect_q;
93
reg [1:0]   opmode_q;
94
reg         phy_reset_q;
95 5 ultra_embe
reg         mode_write_q;
96 2 ultra_embe
 
97 5 ultra_embe
// Detect register write completion
98
wire mode_complete_w = (state_q == STATE_REG &&
99
                        mode_write_q         &&
100
                        ulpi_nxt_i           &&
101
                        !ulpi_dir_i);           // Not interrupted by a Rx
102
 
103 2 ultra_embe
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
104
if (ulpi_rst_i)
105
begin
106
    mode_update_q   <= 1'b0;
107
    xcvrselect_q    <= 2'b0;
108
    termselect_q    <= 1'b0;
109
    opmode_q        <= 2'b11;
110
    phy_reset_q     <= 1'b1;
111
end
112
else
113
begin
114
    xcvrselect_q    <= utmi_xcvrselect_i;
115
    termselect_q    <= utmi_termselect_i;
116 4 ultra_embe
    opmode_q        <= utmi_op_mode_i;
117 2 ultra_embe
 
118 5 ultra_embe
    if (mode_update_q && mode_complete_w)
119 2 ultra_embe
    begin
120
        mode_update_q <= 1'b0;
121
        phy_reset_q   <= 1'b0;
122
    end
123 4 ultra_embe
    else if (opmode_q     != utmi_op_mode_i     ||
124 2 ultra_embe
             termselect_q != utmi_termselect_i ||
125
             xcvrselect_q != utmi_xcvrselect_i)
126
        mode_update_q <= 1'b1;
127
end
128
 
129
//-----------------------------------------------------------------
130
// UTMI OTG Control
131
//-----------------------------------------------------------------
132
reg otg_update_q;
133
reg dppulldown_q;
134
reg dmpulldown_q;
135 5 ultra_embe
reg otg_write_q;
136 2 ultra_embe
 
137 5 ultra_embe
// Detect register write completion
138
wire otg_complete_w  = (state_q == STATE_REG &&
139
                        otg_write_q         &&
140
                        ulpi_nxt_i           &&
141
                        !ulpi_dir_i);           // Not interrupted by a Rx
142
 
143 2 ultra_embe
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
144
if (ulpi_rst_i)
145
begin
146
    otg_update_q    <= 1'b0;
147
    dppulldown_q    <= 1'b1;
148
    dmpulldown_q    <= 1'b1;
149
end
150
else
151
begin
152
    dppulldown_q    <= utmi_dppulldown_i;
153
    dmpulldown_q    <= utmi_dmpulldown_i;
154
 
155 5 ultra_embe
    if (otg_update_q && otg_complete_w)
156 2 ultra_embe
        otg_update_q <= 1'b0;
157
    else if (dppulldown_q != utmi_dppulldown_i ||
158
             dmpulldown_q != utmi_dmpulldown_i)
159
        otg_update_q <= 1'b1;
160
end
161
 
162
//-----------------------------------------------------------------
163
// Bus turnaround detect
164
//-----------------------------------------------------------------
165
reg ulpi_dir_q;
166
 
167
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
168
if (ulpi_rst_i)
169
    ulpi_dir_q <= 1'b0;
170
else
171
    ulpi_dir_q <= ulpi_dir_i;
172
 
173
wire turnaround_w = ulpi_dir_q ^ ulpi_dir_i;
174
 
175
//-----------------------------------------------------------------
176
// Rx - Tx delay
177
//-----------------------------------------------------------------
178
localparam TX_DELAY_W       = 3;
179
localparam TX_START_DELAY   = 3'd7;
180
 
181
reg [TX_DELAY_W-1:0] tx_delay_q;
182
 
183
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
184
if (ulpi_rst_i)
185
    tx_delay_q <= {TX_DELAY_W{1'b0}};
186
else if (utmi_rxactive_o)
187
    tx_delay_q <= TX_START_DELAY;
188
else if (tx_delay_q != {TX_DELAY_W{1'b0}})
189
    tx_delay_q <= tx_delay_q - 1;
190
 
191
wire tx_delay_complete_w = (tx_delay_q == {TX_DELAY_W{1'b0}});
192
 
193
//-----------------------------------------------------------------
194
// Tx Buffer - decouple UTMI Tx from PHY I/O
195
//-----------------------------------------------------------------
196
reg [7:0] tx_buffer_q[0:1];
197
reg       tx_valid_q[0:1];
198
reg       tx_wr_idx_q;
199
reg       tx_rd_idx_q;
200
 
201
wire      utmi_tx_ready_w;
202
wire      utmi_tx_accept_w;
203
 
204
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
205
if (ulpi_rst_i)
206
begin
207
    tx_buffer_q[0] <= 8'b0;
208
    tx_buffer_q[1] <= 8'b0;
209
    tx_valid_q[0]  <= 1'b0;
210
    tx_valid_q[1]  <= 1'b0;
211
    tx_wr_idx_q    <= 1'b0;
212
    tx_rd_idx_q    <= 1'b0;
213
end
214
else
215
begin
216
    // Push
217
    if (utmi_txvalid_i && utmi_txready_o)
218
    begin
219 4 ultra_embe
        tx_buffer_q[tx_wr_idx_q] <= utmi_data_out_i;
220 2 ultra_embe
        tx_valid_q[tx_wr_idx_q]  <= 1'b1;
221
 
222
        tx_wr_idx_q <= tx_wr_idx_q + 1'b1;
223
    end
224
 
225
    // Pop
226
    if (utmi_tx_ready_w && utmi_tx_accept_w)
227
    begin
228
        tx_valid_q[tx_rd_idx_q]  <= 1'b0;
229
        tx_rd_idx_q <= tx_rd_idx_q + 1'b1;
230
    end
231
end
232
 
233
// Tx buffer space (only accept after Rx->Tx turnaround delay)
234
assign utmi_txready_o  = ~tx_valid_q[tx_wr_idx_q] & tx_delay_complete_w;
235
 
236
assign utmi_tx_ready_w = tx_valid_q[tx_rd_idx_q];
237
 
238
wire [7:0] utmi_tx_data_w = tx_buffer_q[tx_rd_idx_q];
239
 
240
//-----------------------------------------------------------------
241
// Implementation
242
//-----------------------------------------------------------------
243
 
244
// Xilinx placement pragmas:
245
//synthesis attribute IOB of ulpi_data_q is "TRUE"
246
//synthesis attribute IOB of ulpi_stp_q is "TRUE"
247
 
248
reg [7:0]           ulpi_data_q;
249
reg                 ulpi_stp_q;
250
reg [7:0]           data_q;
251
 
252
reg                 utmi_rxvalid_q;
253
reg                 utmi_rxerror_q;
254
reg                 utmi_rxactive_q;
255
reg [1:0]           utmi_linestate_q;
256
reg [7:0]           utmi_data_q;
257
 
258
always @ (posedge ulpi_clk60_i or posedge ulpi_rst_i)
259 4 ultra_embe
if (ulpi_rst_i)
260 2 ultra_embe
begin
261 4 ultra_embe
    state_q             <= STATE_IDLE;
262
    ulpi_data_q         <= 8'b0;
263
    data_q              <= 8'b0;
264
    ulpi_stp_q          <= 1'b1;
265
 
266
    utmi_rxvalid_q      <= 1'b0;
267
    utmi_rxerror_q      <= 1'b0;
268
    utmi_rxactive_q     <= 1'b0;
269
    utmi_linestate_q    <= 2'b0;
270
    utmi_data_q         <= 8'b0;
271 5 ultra_embe
 
272
    mode_write_q        <= 1'b0;
273
    otg_write_q         <= 1'b0;
274 4 ultra_embe
end
275
else
276
begin
277
    ulpi_stp_q          <= 1'b0;
278
    utmi_rxvalid_q      <= 1'b0;
279
 
280
    // Turnaround: Input + NXT - set RX_ACTIVE
281
    if (turnaround_w && ulpi_dir_i && ulpi_nxt_i)
282 2 ultra_embe
    begin
283 4 ultra_embe
        utmi_rxactive_q <= 1'b1;
284 5 ultra_embe
 
285
        // Register write - abort
286
        if (state_q == STATE_REG)
287
        begin
288
            state_q       <= STATE_IDLE;
289
            ulpi_data_q   <= 8'b0;  // IDLE
290
        end
291 2 ultra_embe
    end
292 4 ultra_embe
    // Turnaround: Input -> Output - reset RX_ACTIVE
293
    else if (turnaround_w && !ulpi_dir_i)
294 2 ultra_embe
    begin
295 4 ultra_embe
        utmi_rxactive_q <= 1'b0;
296 5 ultra_embe
 
297
        // Register write - abort
298
        if (state_q == STATE_REG)
299
        begin
300
            state_q       <= STATE_IDLE;
301
            ulpi_data_q   <= 8'b0;  // IDLE
302
        end
303 4 ultra_embe
    end
304
    // Non-turnaround cycle
305
    else if (!turnaround_w)
306
    begin
307
        //-----------------------------------------------------------------
308
        // Input: RX_CMD (status)
309
        //-----------------------------------------------------------------
310
        if (ulpi_dir_i && !ulpi_nxt_i)
311
        begin
312
            // Phy status
313
            utmi_linestate_q <= ulpi_data_out_i[1:0];
314 2 ultra_embe
 
315 4 ultra_embe
            case (ulpi_data_out_i[5:4])
316
            2'b00:
317
            begin
318
                utmi_rxactive_q <= 1'b0;
319
                utmi_rxerror_q  <= 1'b0;
320
            end
321
            2'b01:
322
            begin
323
                utmi_rxactive_q <= 1'b1;
324
                utmi_rxerror_q  <= 1'b0;
325
            end
326
            2'b11:
327
            begin
328
                utmi_rxactive_q <= 1'b1;
329
                utmi_rxerror_q  <= 1'b1;
330
            end
331
            default:
332
                ; // HOST_DISCONNECTED
333
            endcase
334
        end
335
        //-----------------------------------------------------------------
336
        // Input: RX_DATA
337
        //-----------------------------------------------------------------
338
        else if (ulpi_dir_i && ulpi_nxt_i)
339 2 ultra_embe
        begin
340 4 ultra_embe
            utmi_rxvalid_q  <= 1'b1;
341
            utmi_data_q     <= ulpi_data_out_i;
342
        end
343
        //-----------------------------------------------------------------
344
        // Output
345
        //-----------------------------------------------------------------
346
        else if (!ulpi_dir_i)
347
        begin
348
            // IDLE: Pending mode update
349
            if ((state_q == STATE_IDLE) && mode_update_q)
350 2 ultra_embe
            begin
351 5 ultra_embe
                data_q        <= {1'b0, 1'b1, phy_reset_q, opmode_q, termselect_q, xcvrselect_q};
352
                ulpi_data_q   <= REG_FUNC_CTRL;
353 2 ultra_embe
 
354 5 ultra_embe
                otg_write_q   <= 1'b0;
355
                mode_write_q  <= 1'b1;
356
 
357
                state_q       <= STATE_CMD;
358 4 ultra_embe
            end
359
            // IDLE: Pending OTG control update
360
            else if ((state_q == STATE_IDLE) && otg_update_q)
361
            begin
362 5 ultra_embe
                data_q        <= {5'b0, dmpulldown_q, dppulldown_q, 1'b0};
363
                ulpi_data_q   <= REG_OTG_CTRL;
364 2 ultra_embe
 
365 5 ultra_embe
                otg_write_q   <= 1'b1;
366
                mode_write_q  <= 1'b0;
367
 
368
                state_q       <= STATE_CMD;
369 2 ultra_embe
            end
370 4 ultra_embe
            // IDLE: Pending transmit
371
            else if ((state_q == STATE_IDLE) && utmi_tx_ready_w)
372 3 ultra_embe
            begin
373 4 ultra_embe
                ulpi_data_q <= REG_TRANSMIT | {4'b0, utmi_tx_data_w[3:0]};
374
                state_q     <= STATE_DATA;
375 3 ultra_embe
            end
376 4 ultra_embe
            // Command
377
            else if ((state_q == STATE_CMD) && ulpi_nxt_i)
378
            begin
379
                // Write Register
380
                state_q     <= STATE_REG;
381
                ulpi_data_q <= data_q;
382
            end
383
            // Data (register write)
384
            else if (state_q == STATE_REG && ulpi_nxt_i)
385
            begin
386
                state_q       <= STATE_IDLE;
387
                ulpi_data_q   <= 8'b0;  // IDLE
388
                ulpi_stp_q    <= 1'b1;
389 5 ultra_embe
 
390
                otg_write_q   <= 1'b0;
391
                mode_write_q  <= 1'b0;
392 4 ultra_embe
            end
393
            // Data
394
            else if (state_q == STATE_DATA && ulpi_nxt_i)
395
            begin
396
                // End of packet
397
                if (!utmi_tx_ready_w)
398 2 ultra_embe
                begin
399 3 ultra_embe
                    state_q       <= STATE_IDLE;
400
                    ulpi_data_q   <= 8'b0;  // IDLE
401
                    ulpi_stp_q    <= 1'b1;
402
                end
403 4 ultra_embe
                else
404 2 ultra_embe
                begin
405 4 ultra_embe
                    state_q        <= STATE_DATA;
406
                    ulpi_data_q    <= utmi_tx_data_w;
407 2 ultra_embe
                end
408
            end
409
        end
410 4 ultra_embe
    end
411 2 ultra_embe
end
412
 
413
// Accept from buffer
414 4 ultra_embe
assign utmi_tx_accept_w = ((state_q == STATE_IDLE) && !(mode_update_q || otg_update_q || turnaround_w) && !ulpi_dir_i) ||
415 3 ultra_embe
                          (state_q == STATE_DATA && ulpi_nxt_i && !ulpi_dir_i);
416 2 ultra_embe
 
417
//-----------------------------------------------------------------
418
// Assignments
419
//-----------------------------------------------------------------
420
// ULPI Interface
421 4 ultra_embe
assign ulpi_data_in_o       = ulpi_data_q;
422 2 ultra_embe
assign ulpi_stp_o           = ulpi_stp_q;
423
 
424
// UTMI Interface
425
assign utmi_linestate_o     = utmi_linestate_q;
426 4 ultra_embe
assign utmi_data_in_o       = utmi_data_q;
427 2 ultra_embe
assign utmi_rxerror_o       = utmi_rxerror_q;
428
assign utmi_rxactive_o      = utmi_rxactive_q;
429
assign utmi_rxvalid_o       = utmi_rxvalid_q;
430
 
431 4 ultra_embe
 
432
 
433 5 ultra_embe
endmodule

powered by: WebSVN 2.1.0

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