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

Subversion Repositories usb_phy

[/] [usb_phy/] [trunk/] [rtl/] [verilog/] [usb_rx_phy.v] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 rudi
/////////////////////////////////////////////////////////////////////
2
////                                                             ////
3
////  USB 1.1 PHY                                                ////
4
////  RX & DPLL                                                  ////
5
////                                                             ////
6
////                                                             ////
7
////  Author: Rudolf Usselmann                                   ////
8
////          rudi@asics.ws                                      ////
9
////                                                             ////
10
////                                                             ////
11
////  Downloaded from: http://www.opencores.org/cores/usb_phy/   ////
12
////                                                             ////
13
/////////////////////////////////////////////////////////////////////
14
////                                                             ////
15
//// Copyright (C) 2000-2002 Rudolf Usselmann                    ////
16
////                         www.asics.ws                        ////
17
////                         rudi@asics.ws                       ////
18
////                                                             ////
19
//// This source file may be used and distributed without        ////
20
//// restriction provided that this copyright statement is not   ////
21
//// removed from the file and that any derivative work contains ////
22
//// the original copyright notice and the associated disclaimer.////
23
////                                                             ////
24
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
25
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
26
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
27
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
28
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
29
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
30
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
31
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
32
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
33
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
34
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
35
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
36
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
37
////                                                             ////
38
/////////////////////////////////////////////////////////////////////
39
 
40
//  CVS Log
41
//
42 11 rudi
//  $Id: usb_rx_phy.v,v 1.5 2004-10-19 09:29:07 rudi Exp $
43 2 rudi
//
44 11 rudi
//  $Date: 2004-10-19 09:29:07 $
45
//  $Revision: 1.5 $
46 2 rudi
//  $Author: rudi $
47
//  $Locker:  $
48
//  $State: Exp $
49
//
50
// Change History:
51
//               $Log: not supported by cvs2svn $
52 11 rudi
//               Revision 1.4  2003/12/02 04:56:00  rudi
53
//               Fixed a bug reported by Karl C. Posch from Graz University of Technology. Thanks Karl !
54
//
55 10 rudi
//               Revision 1.3  2003/10/19 18:07:45  rudi
56
//               - Fixed Sync Error to be only checked/generated during the sync phase
57
//
58 8 rudi
//               Revision 1.2  2003/10/19 17:40:13  rudi
59
//               - Made core more robust against line noise
60
//               - Added Error Checking and Reporting
61
//               (See README.txt for more info)
62
//
63 7 rudi
//               Revision 1.1.1.1  2002/09/16 14:27:01  rudi
64
//               Created Directory Structure
65 2 rudi
//
66
//
67
//
68
//
69
//
70
//
71
//
72 7 rudi
//
73 2 rudi
 
74
`include "timescale.v"
75
 
76
module usb_rx_phy(      clk, rst, fs_ce,
77
 
78
                        // Transciever Interface
79
                        rxd, rxdp, rxdn,
80
 
81
                        // UTMI Interface
82
                        RxValid_o, RxActive_o, RxError_o, DataIn_o,
83
                        RxEn_i, LineState);
84
 
85
input           clk;
86
input           rst;
87
output          fs_ce;
88
input           rxd, rxdp, rxdn;
89
output  [7:0]    DataIn_o;
90
output          RxValid_o;
91
output          RxActive_o;
92
output          RxError_o;
93
input           RxEn_i;
94
output  [1:0]    LineState;
95
 
96
///////////////////////////////////////////////////////////////////
97
//
98
// Local Wires and Registers
99
//
100
 
101 10 rudi
reg             rxd_s0, rxd_s1,  rxd_s;
102
reg             rxdp_s0, rxdp_s1, rxdp_s, rxdp_s_r;
103
reg             rxdn_s0, rxdn_s1, rxdn_s, rxdn_s_r;
104 2 rudi
reg             synced_d;
105
wire            k, j, se0;
106 10 rudi
reg             rxd_r;
107 2 rudi
reg             rx_en;
108
reg             rx_active;
109
reg     [2:0]    bit_cnt;
110
reg             rx_valid1, rx_valid;
111
reg             shift_en;
112
reg             sd_r;
113
reg             sd_nrzi;
114
reg     [7:0]    hold_reg;
115
wire            drop_bit;       // Indicates a stuffed bit
116
reg     [2:0]    one_cnt;
117
 
118
reg     [1:0]    dpll_state, dpll_next_state;
119 10 rudi
reg             fs_ce_d;
120
reg             fs_ce;
121 2 rudi
wire            change;
122
wire            lock_en;
123
reg     [2:0]    fs_state, fs_next_state;
124
reg             rx_valid_r;
125 7 rudi
reg             sync_err_d, sync_err;
126
reg             bit_stuff_err;
127
reg             se0_r, byte_err;
128 11 rudi
reg             se0_s;
129 2 rudi
 
130
///////////////////////////////////////////////////////////////////
131
//
132
// Misc Logic
133
//
134
 
135
assign RxActive_o = rx_active;
136
assign RxValid_o = rx_valid;
137 7 rudi
assign RxError_o = sync_err | bit_stuff_err | byte_err;
138 2 rudi
assign DataIn_o = hold_reg;
139 11 rudi
assign LineState = {rxdn_s1, rxdp_s1};
140 2 rudi
 
141 7 rudi
always @(posedge clk)   rx_en <= RxEn_i;
142 8 rudi
always @(posedge clk)   sync_err <= !rx_active & sync_err_d;
143 2 rudi
 
144
///////////////////////////////////////////////////////////////////
145
//
146
// Synchronize Inputs
147
//
148
 
149
// First synchronize to the local system clock to
150 7 rudi
// avoid metastability outside the sync block (*_s0).
151
// Then make sure we see the signal for at least two
152
// clock cycles stable to avoid glitches and noise
153 2 rudi
 
154 10 rudi
always @(posedge clk)   rxd_s0  <= rxd;
155 7 rudi
always @(posedge clk)   rxd_s1  <= rxd_s0;
156 10 rudi
always @(posedge clk)                                                   // Avoid detecting Line Glitches and noise
157 7 rudi
        if(rxd_s0 && rxd_s1)    rxd_s <= 1'b1;
158
        else
159
        if(!rxd_s0 && !rxd_s1)  rxd_s <= 1'b0;
160 2 rudi
 
161 10 rudi
always @(posedge clk)   rxdp_s0  <= rxdp;
162 7 rudi
always @(posedge clk)   rxdp_s1  <= rxdp_s0;
163
always @(posedge clk)   rxdp_s_r <= rxdp_s0 & rxdp_s1;
164
always @(posedge clk)   rxdp_s   <= (rxdp_s0 & rxdp_s1) | rxdp_s_r;     // Avoid detecting Line Glitches and noise
165 2 rudi
 
166 10 rudi
always @(posedge clk)   rxdn_s0  <= rxdn;
167 7 rudi
always @(posedge clk)   rxdn_s1  <= rxdn_s0;
168
always @(posedge clk)   rxdn_s_r <= rxdn_s0 & rxdn_s1;
169
always @(posedge clk)   rxdn_s   <= (rxdn_s0 & rxdn_s1) | rxdn_s_r;     // Avoid detecting Line Glitches and noise
170 2 rudi
 
171
assign k = !rxdp_s &  rxdn_s;
172
assign j =  rxdp_s & !rxdn_s;
173
assign se0 = !rxdp_s & !rxdn_s;
174
 
175 11 rudi
always @(posedge clk)   if(fs_ce)       se0_s <= se0;
176
 
177 2 rudi
///////////////////////////////////////////////////////////////////
178
//
179
// DPLL
180
//
181
 
182
// This design uses a clock enable to do 12Mhz timing and not a
183
// real 12Mhz clock. Everything always runs at 48Mhz. We want to
184
// make sure however, that the clock enable is always exactly in
185
// the middle between two virtual 12Mhz rising edges.
186
// We monitor rxdp and rxdn for any changes and do the appropiate
187
// adjustments.
188
// In addition to the locking done in the dpll FSM, we adjust the
189
// final latch enable to compensate for various sync registers ...
190
 
191
// Allow lockinf only when we are receiving
192
assign  lock_en = rx_en;
193
 
194 10 rudi
always @(posedge clk)   rxd_r <= rxd_s;
195
 
196 2 rudi
// Edge detector
197 10 rudi
assign change = rxd_r != rxd_s;
198 2 rudi
 
199
// DPLL FSM
200
`ifdef USB_ASYNC_REST
201
always @(posedge clk or negedge rst)
202
`else
203
always @(posedge clk)
204
`endif
205 7 rudi
        if(!rst)        dpll_state <= 2'h1;
206
        else            dpll_state <= dpll_next_state;
207 2 rudi
 
208
always @(dpll_state or lock_en or change)
209
   begin
210
        fs_ce_d = 1'b0;
211
        case(dpll_state)        // synopsys full_case parallel_case
212
           2'h0:
213 7 rudi
                if(lock_en && change)   dpll_next_state = 2'h0;
214
                else                    dpll_next_state = 2'h1;
215 2 rudi
           2'h1:begin
216
                fs_ce_d = 1'b1;
217 7 rudi
                if(lock_en && change)   dpll_next_state = 2'h3;
218
                else                    dpll_next_state = 2'h2;
219 2 rudi
                end
220
           2'h2:
221 7 rudi
                if(lock_en && change)   dpll_next_state = 2'h0;
222
                else                    dpll_next_state = 2'h3;
223 2 rudi
           2'h3:
224 7 rudi
                if(lock_en && change)   dpll_next_state = 2'h0;
225
                else                    dpll_next_state = 2'h0;
226 2 rudi
        endcase
227
   end
228
 
229
// Compensate for sync registers at the input - allign full speed
230
// clock enable to be in the middle between two bit changes ...
231 10 rudi
reg     fs_ce_r1, fs_ce_r2;
232 2 rudi
 
233 10 rudi
always @(posedge clk)   fs_ce_r1 <= fs_ce_d;
234
always @(posedge clk)   fs_ce_r2 <= fs_ce_r1;
235
always @(posedge clk)   fs_ce <= fs_ce_r2;
236
 
237
 
238 2 rudi
///////////////////////////////////////////////////////////////////
239
//
240
// Find Sync Pattern FSM
241
//
242
 
243
parameter       FS_IDLE = 3'h0,
244
                K1      = 3'h1,
245
                J1      = 3'h2,
246
                K2      = 3'h3,
247
                J2      = 3'h4,
248
                K3      = 3'h5,
249
                J3      = 3'h6,
250
                K4      = 3'h7;
251
 
252
`ifdef USB_ASYNC_REST
253
always @(posedge clk or negedge rst)
254
`else
255
always @(posedge clk)
256
`endif
257 7 rudi
        if(!rst)        fs_state <= FS_IDLE;
258
        else            fs_state <= fs_next_state;
259 2 rudi
 
260 11 rudi
always @(fs_state or fs_ce or k or j or rx_en or rx_active or se0 or se0_s)
261 2 rudi
   begin
262
        synced_d = 1'b0;
263 7 rudi
        sync_err_d = 1'b0;
264 2 rudi
        fs_next_state = fs_state;
265 11 rudi
        if(fs_ce && !rx_active && !se0 && !se0_s)
266 2 rudi
           case(fs_state)       // synopsys full_case parallel_case
267
                FS_IDLE:
268
                     begin
269 7 rudi
                        if(k && rx_en)  fs_next_state = K1;
270 2 rudi
                     end
271
                K1:
272
                     begin
273 7 rudi
                        if(j && rx_en)  fs_next_state = J1;
274
                        else
275
                           begin
276
                                        sync_err_d = 1'b1;
277
                                        fs_next_state = FS_IDLE;
278
                           end
279 2 rudi
                     end
280
                J1:
281
                     begin
282 7 rudi
                        if(k && rx_en)  fs_next_state = K2;
283
                        else
284
                           begin
285
                                        sync_err_d = 1'b1;
286
                                        fs_next_state = FS_IDLE;
287
                           end
288 2 rudi
                     end
289
                K2:
290
                     begin
291 7 rudi
                        if(j && rx_en)  fs_next_state = J2;
292
                        else
293
                           begin
294
                                        sync_err_d = 1'b1;
295
                                        fs_next_state = FS_IDLE;
296
                           end
297 2 rudi
                     end
298
                J2:
299
                     begin
300 7 rudi
                        if(k && rx_en)  fs_next_state = K3;
301
                        else
302
                           begin
303
                                        sync_err_d = 1'b1;
304
                                        fs_next_state = FS_IDLE;
305
                           end
306 2 rudi
                     end
307
                K3:
308
                     begin
309 7 rudi
                        if(j && rx_en)  fs_next_state = J3;
310 2 rudi
                        else
311 11 rudi
                        if(k && rx_en)
312
                           begin
313
                                        fs_next_state = FS_IDLE;        // Allow missing first K-J
314
                                        synced_d = 1'b1;
315
                           end
316 7 rudi
                        else
317
                           begin
318
                                        sync_err_d = 1'b1;
319
                                        fs_next_state = FS_IDLE;
320
                           end
321 2 rudi
                     end
322
                J3:
323
                     begin
324 7 rudi
                        if(k && rx_en)  fs_next_state = K4;
325
                        else
326
                           begin
327
                                        sync_err_d = 1'b1;
328
                                        fs_next_state = FS_IDLE;
329
                           end
330 2 rudi
                     end
331
                K4:
332
                     begin
333
                        if(k)   synced_d = 1'b1;
334
                        fs_next_state = FS_IDLE;
335
                     end
336
           endcase
337
   end
338
 
339
///////////////////////////////////////////////////////////////////
340
//
341
// Generate RxActive
342
//
343
 
344
`ifdef USB_ASYNC_REST
345
always @(posedge clk or negedge rst)
346
`else
347
always @(posedge clk)
348
`endif
349 7 rudi
        if(!rst)                rx_active <= 1'b0;
350 2 rudi
        else
351 7 rudi
        if(synced_d && rx_en)   rx_active <= 1'b1;
352 2 rudi
        else
353 7 rudi
        if(se0 && rx_valid_r)   rx_active <= 1'b0;
354 2 rudi
 
355
always @(posedge clk)
356 7 rudi
        if(rx_valid)    rx_valid_r <= 1'b1;
357 2 rudi
        else
358 7 rudi
        if(fs_ce)       rx_valid_r <= 1'b0;
359 2 rudi
 
360
///////////////////////////////////////////////////////////////////
361
//
362
// NRZI Decoder
363
//
364
 
365
always @(posedge clk)
366 7 rudi
        if(fs_ce)       sd_r <= rxd_s;
367 2 rudi
 
368
`ifdef USB_ASYNC_REST
369
always @(posedge clk or negedge rst)
370
`else
371
always @(posedge clk)
372
`endif
373 7 rudi
        if(!rst)                sd_nrzi <= 1'b0;
374 2 rudi
        else
375 10 rudi
        if(!rx_active)          sd_nrzi <= 1'b1;
376
        else
377 7 rudi
        if(rx_active && fs_ce)  sd_nrzi <= !(rxd_s ^ sd_r);
378 2 rudi
 
379
///////////////////////////////////////////////////////////////////
380
//
381
// Bit Stuff Detect
382
//
383
 
384
`ifdef USB_ASYNC_REST
385
always @(posedge clk or negedge rst)
386
`else
387
always @(posedge clk)
388
`endif
389 7 rudi
        if(!rst)        one_cnt <= 3'h0;
390 2 rudi
        else
391 7 rudi
        if(!shift_en)   one_cnt <= 3'h0;
392 2 rudi
        else
393
        if(fs_ce)
394
           begin
395 7 rudi
                if(!sd_nrzi || drop_bit)        one_cnt <= 3'h0;
396
                else                            one_cnt <= one_cnt + 3'h1;
397 2 rudi
           end
398
 
399
assign drop_bit = (one_cnt==3'h6);
400
 
401 11 rudi
always @(posedge clk)   bit_stuff_err <= drop_bit & sd_nrzi & fs_ce & !se0 & rx_active; // Bit Stuff Error
402 7 rudi
 
403 2 rudi
///////////////////////////////////////////////////////////////////
404
//
405
// Serial => Parallel converter
406
//
407
 
408
always @(posedge clk)
409 7 rudi
        if(fs_ce)       shift_en <= synced_d | rx_active;
410 2 rudi
 
411
always @(posedge clk)
412 7 rudi
        if(fs_ce && shift_en && !drop_bit)
413
                hold_reg <= {sd_nrzi, hold_reg[7:1]};
414 2 rudi
 
415
///////////////////////////////////////////////////////////////////
416
//
417
// Generate RxValid
418
//
419
 
420
`ifdef USB_ASYNC_REST
421
always @(posedge clk or negedge rst)
422
`else
423
always @(posedge clk)
424
`endif
425 7 rudi
        if(!rst)                bit_cnt <= 3'b0;
426 2 rudi
        else
427 7 rudi
        if(!shift_en)           bit_cnt <= 3'h0;
428 2 rudi
        else
429 7 rudi
        if(fs_ce && !drop_bit)  bit_cnt <= bit_cnt + 3'h1;
430 2 rudi
 
431
`ifdef USB_ASYNC_REST
432
always @(posedge clk or negedge rst)
433
`else
434
always @(posedge clk)
435
`endif
436 7 rudi
        if(!rst)                                        rx_valid1 <= 1'b0;
437 2 rudi
        else
438 7 rudi
        if(fs_ce && !drop_bit && (bit_cnt==3'h7))       rx_valid1 <= 1'b1;
439 2 rudi
        else
440 7 rudi
        if(rx_valid1 && fs_ce && !drop_bit)             rx_valid1 <= 1'b0;
441 2 rudi
 
442 11 rudi
always @(posedge clk)   rx_valid <= !drop_bit & rx_valid1 & fs_ce;
443 2 rudi
 
444 7 rudi
always @(posedge clk)   se0_r <= se0;
445
 
446 11 rudi
always @(posedge clk)   byte_err <= se0 & !se0_r & (|bit_cnt[2:1]) & rx_active;
447 7 rudi
 
448 2 rudi
endmodule
449
 

powered by: WebSVN 2.1.0

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