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

Subversion Repositories usb1_funct

[/] [usb1_funct/] [trunk/] [rtl/] [verilog/] [usb1_pd.v] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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