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

Subversion Repositories usb2uart

[/] [usb2uart/] [trunk/] [rtl/] [usb1_core/] [usb1_pd.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dinesha
/////////////////////////////////////////////////////////////////////
2
////                                                             ////
3
////  Packet Disassembler                                        ////
4
////  Disassembles Token and Data USB packets                    ////
5
////                                                             ////
6
////  Author: Rudolf Usselmann                                   ////
7
////          rudi@asics.ws                                      ////
8
////                                                             ////
9
////                                                             ////
10
////  Downloaded from: http://www.opencores.org/cores/usb1_funct/////
11
////                                                             ////
12
/////////////////////////////////////////////////////////////////////
13
////                                                             ////
14
//// Copyright (C) 2000-2002 Rudolf Usselmann                    ////
15
////                         www.asics.ws                        ////
16
////                         rudi@asics.ws                       ////
17
////                                                             ////
18
//// This source file may be used and distributed without        ////
19
//// restriction provided that this copyright statement is not   ////
20
//// removed from the file and that any derivative work contains ////
21
//// the original copyright notice and the associated disclaimer.////
22
////                                                             ////
23
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
24
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
25
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
26
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
27
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
28
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
29
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
30
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
31
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
32
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
33
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
34
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
35
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
36
////                                                             ////
37
/////////////////////////////////////////////////////////////////////
38
 
39
//  CVS Log
40
//
41
//  $Id: usb1_pd.v,v 1.2 2002-09-25 06:06:49 rudi Exp $
42
//
43
//  $Date: 2002-09-25 06:06:49 $
44
//  $Revision: 1.2 $
45
//  $Author: rudi $
46
//  $Locker:  $
47
//  $State: Exp $
48
//
49
// Change History:
50
//               $Log: not supported by cvs2svn $
51
//               Revision 1.1.1.1  2002/09/19 12:07:17  rudi
52
//               Initial Checkin
53
//
54
//
55
//
56
//
57
//
58
//
59
//
60
//
61
 
62
`include "usb1_defines.v"
63
 
64
module usb1_pd( clk, rst,
65
 
66
                // UTMI RX I/F
67
                rx_data, rx_valid, rx_active, rx_err,
68
 
69
                // PID Information
70
                pid_OUT, pid_IN, pid_SOF, pid_SETUP,
71
                pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA,
72
                pid_ACK, pid_NACK, pid_STALL, pid_NYET,
73
                pid_PRE, pid_ERR, pid_SPLIT, pid_PING,
74
                pid_cks_err,
75
 
76
                // Token Information
77
                token_fadr, token_endp, token_valid, crc5_err,
78
                frame_no,
79
 
80
                // Receive Data Output
81
                rx_data_st, rx_data_valid, rx_data_done, crc16_err,
82
 
83
                // Misc.
84
                seq_err, rx_busy
85
                );
86
 
87
input           clk, rst;
88
 
89
                //UTMI RX Interface
90
input   [7:0]    rx_data;
91
input           rx_valid, rx_active, rx_err;
92
 
93
                // Decoded PIDs (used when token_valid is asserted)
94
output          pid_OUT, pid_IN, pid_SOF, pid_SETUP;
95
output          pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA;
96
output          pid_ACK, pid_NACK, pid_STALL, pid_NYET;
97
output          pid_PRE, pid_ERR, pid_SPLIT, pid_PING;
98
output          pid_cks_err;            // Indicates a PID checksum error
99
 
100
 
101
output  [6:0]    token_fadr;             // Function address from token
102
output  [3:0]    token_endp;             // Endpoint number from token
103
output          token_valid;            // Token is valid
104
output          crc5_err;               // Token crc5 error
105
output  [10:0]   frame_no;               // Frame number for SOF tokens
106
 
107
output  [7:0]    rx_data_st;             // Data to memory store unit
108
output          rx_data_valid;          // Data on rx_data_st is valid
109
output          rx_data_done;           // Indicates end of a transfer
110
output          crc16_err;              // Data packet CRC 16 error
111
 
112
output          seq_err;                // State Machine Sequence Error
113
output          rx_busy;                // Receivig Data Packet
114
 
115
///////////////////////////////////////////////////////////////////
116
//
117
// Local Wires and Registers
118
//
119
 
120
parameter       [3:0]    // synopsys enum state
121
                IDLE   = 4'b0001,
122
                ACTIVE = 4'b0010,
123
                TOKEN  = 4'b0100,
124
                DATA   = 4'b1000;
125
 
126
reg     [3:0]    /* synopsys enum state */ state, next_state;
127
// synopsys state_vector state
128
 
129
reg     [7:0]    pid;                    // Packet PDI
130
reg             pid_le_sm;              // PID Load enable from State Machine
131
wire            pid_ld_en;              // Enable loading of PID (all conditions)
132
wire            pid_cks_err;            // Indicates a pid checksum err
133
 
134
                // Decoded PID values
135
wire            pid_OUT, pid_IN, pid_SOF, pid_SETUP;
136
wire            pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA;
137
wire            pid_ACK, pid_NACK, pid_STALL, pid_NYET;
138
wire            pid_PRE, pid_ERR, pid_SPLIT, pid_PING, pid_RES;
139
wire            pid_TOKEN;              // All TOKEN packet that we recognize
140
wire            pid_DATA;               // All DATA packets that we recognize
141
 
142
reg     [7:0]    token0, token1;         // Token Registers
143
reg             token_le_1, token_le_2; // Latch enables for token storage registers
144
wire    [4:0]    token_crc5;
145
 
146
reg     [7:0]    d0, d1, d2;             // Data path delay line (used to filter out crcs)
147
reg             data_valid_d;           // Data Valid output from State Machine
148
reg             data_done;              // Data cycle complete output from State Machine
149
reg             data_valid0;            // Data valid delay line
150
reg             rxv1;
151
reg             rxv2;
152
 
153
reg             seq_err;                // State machine sequence error
154
 
155
reg             pid_ack;
156
 
157
reg             token_valid_r1;
158
reg             token_valid_str1, token_valid_str2;
159
 
160
reg             rx_active_r;
161
 
162
wire    [4:0]    crc5_out;
163
wire    [4:0]    crc5_out2;
164
wire            crc16_clr;
165
reg     [15:0]   crc16_sum;
166
wire    [15:0]   crc16_out;
167
 
168
///////////////////////////////////////////////////////////////////
169
//
170
// Misc Logic
171
//
172
 
173
reg     rx_busy, rx_busy_d;
174
 
175
always @(posedge clk or negedge rst)
176
        if(!rst)                        rx_busy_d <= #1 1'b0;
177
        else
178
        if(rx_valid & (state == DATA))  rx_busy_d <= #1 1'b1;
179
        else
180
        if(state != DATA)               rx_busy_d <= #1 1'b0;
181
 
182
always @(posedge clk)
183
        rx_busy <= #1 rx_busy_d;
184
 
185
// PID Decoding Logic
186
assign pid_ld_en = pid_le_sm & rx_active & rx_valid;
187
 
188
always @(posedge clk or negedge rst)
189
        if(!rst)                pid <= #1 8'hf0;
190
        else
191
        if(pid_ld_en)           pid <= #1 rx_data;
192
 
193
assign  pid_cks_err = (pid[3:0] != ~pid[7:4]);
194
 
195
assign  pid_OUT   = pid[3:0] == `USBF_T_PID_OUT;
196
assign  pid_IN    = pid[3:0] == `USBF_T_PID_IN;
197
assign  pid_SOF   = pid[3:0] == `USBF_T_PID_SOF;
198
assign  pid_SETUP = pid[3:0] == `USBF_T_PID_SETUP;
199
assign  pid_DATA0 = pid[3:0] == `USBF_T_PID_DATA0;
200
assign  pid_DATA1 = pid[3:0] == `USBF_T_PID_DATA1;
201
assign  pid_DATA2 = pid[3:0] == `USBF_T_PID_DATA2;
202
assign  pid_MDATA = pid[3:0] == `USBF_T_PID_MDATA;
203
assign  pid_ACK   = pid[3:0] == `USBF_T_PID_ACK;
204
assign  pid_NACK  = pid[3:0] == `USBF_T_PID_NACK;
205
assign  pid_STALL = pid[3:0] == `USBF_T_PID_STALL;
206
assign  pid_NYET  = pid[3:0] == `USBF_T_PID_NYET;
207
assign  pid_PRE   = pid[3:0] == `USBF_T_PID_PRE;
208
assign  pid_ERR   = pid[3:0] == `USBF_T_PID_ERR;
209
assign  pid_SPLIT = pid[3:0] == `USBF_T_PID_SPLIT;
210
assign  pid_PING  = pid[3:0] == `USBF_T_PID_PING;
211
assign  pid_RES   = pid[3:0] == `USBF_T_PID_RES;
212
 
213
assign  pid_TOKEN = pid_OUT | pid_IN | pid_SOF | pid_SETUP | pid_PING;
214
assign  pid_DATA = pid_DATA0 | pid_DATA1 | pid_DATA2 | pid_MDATA;
215
 
216
// Token Decoding LOGIC
217
always @(posedge clk)
218
        if(token_le_1)  token0 <= #1 rx_data;
219
 
220
always @(posedge clk)
221
        if(token_le_2)  token1 <= #1 rx_data;
222
 
223
always @(posedge clk)
224
        token_valid_r1 <= #1 token_le_2;
225
 
226
always @(posedge clk)
227
        token_valid_str1 <= #1 token_valid_r1 | pid_ack;
228
 
229
always @(posedge clk)
230
        token_valid_str2 <= #1 token_valid_str1;
231
 
232
assign token_valid = token_valid_str1;
233
 
234
// CRC 5 should perform the check in one cycle (flow through logic)
235
// 11 bits and crc5 input, 1 bit output
236
assign crc5_err = token_valid & (crc5_out2 != token_crc5);
237
 
238
usb1_crc5 u0(
239
        .crc_in(        5'h1f                   ),
240
        .din(   {       token_fadr[0],
241
                        token_fadr[1],
242
                        token_fadr[2],
243
                        token_fadr[3],
244
                        token_fadr[4],
245
                        token_fadr[5],
246
                        token_fadr[6],
247
                        token_endp[0],
248
                        token_endp[1],
249
                        token_endp[2],
250
                        token_endp[3]   }       ),
251
        .crc_out(       crc5_out                ) );
252
 
253
// Invert and reverse result bits
254
assign  crc5_out2 = ~{crc5_out[0], crc5_out[1], crc5_out[2], crc5_out[3],
255
                        crc5_out[4]};
256
 
257
assign frame_no = { token1[2:0], token0};
258
assign token_fadr = token0[6:0];
259
assign token_endp = {token1[2:0], token0[7]};
260
assign token_crc5 = token1[7:3];
261
 
262
// Data receiving logic
263
// build a delay line and stop when we are about to get crc
264
always @(posedge clk or negedge rst)
265
        if(!rst)                rxv1 <= #1 1'b0;
266
        else
267
        if(data_valid_d)        rxv1 <= #1 1'b1;
268
        else
269
        if(data_done)           rxv1 <= #1 1'b0;
270
 
271
always @(posedge clk or negedge rst)
272
        if(!rst)                rxv2 <= #1 1'b0;
273
        else
274
        if(rxv1 & data_valid_d) rxv2 <= #1 1'b1;
275
        else
276
        if(data_done)           rxv2 <= #1 1'b0;
277
 
278
always @(posedge clk)
279
        data_valid0 <= #1 rxv2 & data_valid_d;
280
 
281
always @(posedge clk)
282
   begin
283
        if(data_valid_d)        d0 <= #1 rx_data;
284
        if(data_valid_d)        d1 <= #1 d0;
285
        if(data_valid_d)        d2 <= #1 d1;
286
   end
287
 
288
assign rx_data_st = d2;
289
assign rx_data_valid = data_valid0;
290
assign rx_data_done = data_done;
291
 
292
// crc16 accumulates rx_data as long as data_valid_d is asserted.
293
// when data_done is asserted, crc16 reports status, and resets itself
294
// next cycle.
295
always @(posedge clk)
296
        rx_active_r <= #1 rx_active;
297
 
298
assign crc16_clr = rx_active & !rx_active_r;
299
 
300
always @(posedge clk)
301
        if(crc16_clr)           crc16_sum <= #1 16'hffff;
302
        else
303
        if(data_valid_d)        crc16_sum <= #1 crc16_out;
304
 
305
usb1_crc16 u1(
306
        .crc_in(        crc16_sum               ),
307
        .din(   {rx_data[0], rx_data[1], rx_data[2], rx_data[3],
308
                rx_data[4], rx_data[5], rx_data[6], rx_data[7]} ),
309
        .crc_out(       crc16_out               ) );
310
 
311
// Verify against polynomial 
312
assign crc16_err = data_done & (crc16_sum != 16'h800d);
313
 
314
///////////////////////////////////////////////////////////////////
315
//
316
// Receive/Decode State machine
317
//
318
 
319
always @(posedge clk or negedge rst)
320
        if(!rst)        state <= #1 IDLE;
321
        else            state <= #1 next_state;
322
 
323
always @(state or rx_valid or rx_active or rx_err or pid_ACK or pid_TOKEN
324
        or pid_DATA)
325
   begin
326
        next_state = state;     // Default don't change current state
327
        pid_le_sm = 1'b0;
328
        token_le_1 = 1'b0;
329
        token_le_2 = 1'b0;
330
        data_valid_d = 1'b0;
331
        data_done = 1'b0;
332
        seq_err = 1'b0;
333
        pid_ack = 1'b0;
334
        case(state)             // synopsys full_case parallel_case
335
           IDLE:
336
                   begin
337
                        pid_le_sm = 1'b1;
338
                        if(rx_valid & rx_active)        next_state = ACTIVE;
339
                   end
340
           ACTIVE:
341
                   begin
342
                        // Received a ACK from Host
343
                        if(pid_ACK & !rx_err)
344
                           begin
345
                                pid_ack = 1'b1;
346
                                if(!rx_active)  next_state = IDLE;
347
                           end
348
                        else
349
                        // Receiving a TOKEN
350
                        if(pid_TOKEN & rx_valid & rx_active & !rx_err)
351
                           begin
352
                                token_le_1 = 1'b1;
353
                                next_state = TOKEN;
354
                           end
355
                        else
356
                        // Receiving DATA
357
                        if(pid_DATA & rx_valid & rx_active & !rx_err)
358
                           begin
359
                                data_valid_d = 1'b1;
360
                                next_state = DATA;
361
                           end
362
                        else
363
                        if(     !rx_active | rx_err |
364
                                (rx_valid & !(pid_TOKEN | pid_DATA)) )  // ERROR
365
                           begin
366
                                seq_err = !rx_err;
367
                                if(!rx_active)  next_state = IDLE;
368
                           end
369
                   end
370
           TOKEN:
371
                   begin
372
                        if(rx_valid & rx_active & !rx_err)
373
                           begin
374
                                token_le_2 = 1'b1;
375
                                next_state = IDLE;
376
                           end
377
                        else
378
                        if(!rx_active | rx_err) // ERROR
379
                           begin
380
                                seq_err = !rx_err;
381
                                if(!rx_active)  next_state = IDLE;
382
                           end
383
                   end
384
           DATA:
385
                   begin
386
                        if(rx_valid & rx_active & !rx_err)      data_valid_d = 1'b1;
387
                        if(!rx_active | rx_err)
388
                           begin
389
                                data_done = 1'b1;
390
                                if(!rx_active)  next_state = IDLE;
391
                           end
392
                   end
393
 
394
        endcase
395
   end
396
 
397
endmodule
398
 

powered by: WebSVN 2.1.0

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