bcp_usb_tests.v
14.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
//
// BCP extend USB tests
// :set tabstop=4
`define BB_USB_DEBUG
task disp_dbg_msg;
input [0:639] msg;
begin
`ifdef BB_USB_DEBUG
$display("%t: %M: %s", $time, msg);
`endif
end
endtask
task disp_dbg_int;
input [0:320] msg;
input [31:0] data;
begin
`ifdef BB_USB_DEBUG
$display("%t: %M: %s 0x%x(%d)", $time, msg, data, data);
`endif
end
endtask
task disp_dbg_pid;
input [0:320] msg;
input [31:0] token;
begin
`ifdef BB_USB_DEBUG
case (token)
OUT_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "OUT_PID", token);
IN_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "IN_PID", token);
SOF_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "SOF_PID", token);
SETUP_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "SETUP_PID", token);
DATAX_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "DATAX_PID", token);
DATA0_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "DATA0_PID", token);
DATA1_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "DATA1_PID", token);
ACK_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "ACK_PID", token);
NAK_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "NAK_PID", token);
STALL_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "STALL_PID", token);
PRE_PID: $display("%t: %M: %s %s(%d)",
$time, msg, "PRE_PID", token);
default: $display("%t: %M: %s %s(%d)",
$time, msg, "* * UNKNOWN PID * *", token);
endcase
`endif
end
endtask
// Those are volatile data
// please check them before any other transcations
reg [7:0] bcp_pkt_data[0:1024]; // buffer to hold tx/rx pkt
integer bcp_pkt_length; // pkt lenght
integer bcp_token_pid; // token PID
integer bcp_pkt_pid; // pkt pid
integer bcp_endpt; // which endpnt
integer bcp_ack; // ack back?
integer bcp_device; // device addr(0-127)
reg [7:0] bcp_test_err; // BCP test error
reg [7:0] bcp_test_on; // BCP test on
reg bcp_test_start;
reg bcp_ext_lsdev_setup;
integer bcp_prev_err;
integer bcp_i; // bcp loop count
integer bcp_retry_cnt; // bcp retry times
integer bcp_device_ack; // Ack back signal from CORE
//
// USB CORE is set as Host
//
// First 4 bits of bcp_test_on is used to
// define which test is running
// Bit 7 -- setup test
// Bit 6 -- SOF rcving test
// Bit 5 -- OUT Transaction
// Bit 4 -- IN Transaction
wire [3:0] bcp_host_test_on = bcp_test_on[7:4];
wire bcp_host_setup_on = bcp_test_on[7];
wire bcp_host_rcv_SOF_on = bcp_test_on[6];
wire bcp_host_OUT_on = bcp_test_on[5];
wire bcp_host_IN_on = bcp_test_on[4];
// First 4 bits of bcp_test_err is used to
// define which test cause error
wire [3:0] bcp_host_test_err = bcp_test_err[7:4];
wire bcp_host_setup_err = bcp_test_err[7];
wire bcp_host_recv_SOF_err = bcp_test_err[6];
wire bcp_host_OUT_err = bcp_test_err[5];
wire bcp_host_IN_err = bcp_test_err[4];
initial
begin
bcp_test_on = 8'b0;
bcp_test_err = 8'b0;
bcp_err_num = 0;
bcp_prev_err = 0;
bcp_device_ack = 0;
bcp_test_start = 0;
bcp_ext_lsdev_setup = 0;
for (bcp_i=0; bcp_i<1025; bcp_i=bcp_i+1)
bcp_pkt_data[bcp_i] = bcp_i[7:0];
end
// Host setup test
// set test bench to be device and waiting for reset
// When USB core setup as host_en
// Test bench should recv reset
always @(posedge usb_clk)
begin
if (bcp_test_start) begin
if (bcp_err_num != bcp_prev_err)
bcp_test_err = bcp_test_err | bcp_test_on;
end
end
always @(posedge bcp_ext_lsdev_setup)
begin
if (lsdev) begin
clock_low_speed <= 1;
main_proc_retry_repeat_interval = 19'b 1100001101010000000;
main_proc_eop_time = 11'b 10100110110;
VHDL2V_dplus <= #(1) 1'b0;
VHDL2V_dminus <= #(1) 1'b1;
$display("Set to low speed");
end else begin
clock_low_speed <= 0;
main_proc_retry_repeat_interval = 18'b 110000110101000000;
main_proc_eop_time = 8'b 10100110;
VHDL2V_dplus <= #(1) 1'b1;
VHDL2V_dminus <= #(1) 1'b0;
$display("Set to full speed");
end
bcp_ext_lsdev_setup = 0;
end
always @(posedge bcp_host_setup_on)
begin
bcp_prev_err = bcp_err_num;
bcp_test_start = 1;
//tb_is_device <= 0;
disp_dbg_msg("Test setup as ARC is Host");
//tb_is_device <= 1'b 1;
bcp_usb_sof_on <= 1'b0;
// Start USB clk
clk_start <= 0;
#1;
clk_start <= 1'b1;
//disp_dbg_msg("Wait for reset from Host(USB Core)");
//wait_for_reset(4000000);
//disp_dbg_msg("Wait for reset from Host(USB Core) done");
if (bcp_err_num > bcp_prev_err)
bcp_test_err[7] = 1;
bcp_test_on[7] = 0;
bcp_test_start = 0;
end
// Host SOF token setup
// SOF should be generate every 1 ms
// Host will get SOF interrupt first
always @(posedge bcp_host_rcv_SOF_on)
begin
bcp_prev_err = bcp_err_num;
bcp_test_start = 1;
disp_dbg_msg("Wait for SOF PID");
token_in_packet(SOF_PID, 1'b 1, 1'b 0, 1000000);
disp_dbg_msg("SOF PID is got");
if (bcp_err_num > bcp_prev_err)
bcp_test_err[6] = 1;
bcp_test_on[6] = 0;
bcp_test_start = 0;
end
// Host OUT Transaction
// Host sending out Token, data
// Then, this test try to get the data from USB
// Before test is start,
// bcp_token_pid, bcp_pkt_pid,
// bcp_ack, bcp_endpt, bcp_device
// must be setup properly via backdoor
// After transaction, data will be stored in
// bcp_pkt_data for backdoor checking.
always @(posedge bcp_host_OUT_on)
begin
bcp_prev_err = bcp_err_num;
bcp_test_start = 1;
disp_dbg_pid("Try to receive token: ", bcp_token_pid);
disp_dbg_int("At endpoint: ", bcp_endpt);
disp_dbg_int("This device id(addr) is: ", bcp_device);
// timout is 400ns
token_in_packet(bcp_token_pid, bcp_device,
bcp_endpt, 9'b 110010000);
disp_dbg_pid("Try to recv data packet token: ", bcp_pkt_pid);
// Note: Offset 0
// timeout meaningless for arc case(fix 50000ps)
wait_for_host_data(bcp_pkt_pid, bcp_pkt_length, 0, 0);
// copy data to our buf for bdoor use
for (bcp_i=0; bcp_i<bcp_pkt_length; bcp_i=bcp_i+1)
bcp_pkt_data[bcp_i] = main_proc_hc_rxpkt_data[bcp_i];
disp_dbg_int("Device recv # of bytes = ", bcp_pkt_length);
if (bcp_ack) begin //Ack required
disp_dbg_msg("Sendout ACK ");
handshake_out_packet(ACK_PID, GOOD_ACK);
disp_dbg_msg("Sendout ACK Done");
end
if (bcp_err_num > bcp_prev_err)
bcp_test_err[5] = 1;
bcp_test_on[5] = 0;
bcp_test_start = 0;
end
// Host IN Transaction
// Host sending out Token(Should be IN)
// Then, this test try to send out data
// Before test is start,
// bcp_token_pid, bcp_pkt_pid,
// bcp_ack, bcp_endpt, bcp_device
// bcp_pkt_length, bcp_pkt_data
//should be set via backdoor
//
always @(posedge bcp_host_IN_on)
begin
bcp_test_start = 1;
bcp_prev_err = bcp_err_num;
disp_dbg_pid("Try to receive token(should be IN): ", bcp_token_pid);
disp_dbg_int("At endpoint: ", bcp_endpt);
disp_dbg_int("This device id(addr) is: ", bcp_device);
for (bcp_i=0; bcp_i<bcp_pkt_length; bcp_i=bcp_i+1) begin
main_proc_hc_pckt_data[bcp_i] = bcp_pkt_data[bcp_i];
end
// timout is 400ns
token_in_packet(bcp_token_pid, bcp_device,
bcp_endpt, 9'b 110010000);
disp_dbg_msg("Get Token IN Done");
disp_dbg_msg("Send data out");
// offset will be always 0
data_out_packet(bcp_pkt_pid, bcp_pkt_length, 1'b 0);
disp_dbg_msg("Send data out done");
if (bcp_ack) begin
// Wait for handshake
disp_dbg_msg("Wait for handshake");
bcp_retry_cnt = 1'b 0;
while (( main_proc_hand_shake != hand_shake_type_ack_hs) ||
( bcp_retry_cnt >= 21)) begin
disp_dbg_msg("Wait for handshake * *");
handshake_in_packet(main_proc_hand_shake);
if (bcp_retry_cnt === 20) begin
sim_error(0, "Host did not acknowledge echo packet");
end
bcp_retry_cnt = bcp_retry_cnt + 1'b 1;
end
disp_dbg_msg("Wait for handshake Done");
end
if (bcp_err_num > bcp_prev_err)
bcp_test_err[4] = 1;
bcp_test_on[4] = 0;
bcp_test_start = 0;
end
//
// USB Core is set as Device
//
// bcp_usb_sof_on have to be turned on to
// make SOF generated properly.
// Last 4 bits of bcp_test_on is used to
// define which test is running
// Bit 3 -- setup test
// Bit 2 -- reset test
// Bit 1 -- OUT Transaction
// Bit 0 -- IN Transaction
wire [3:0] bcp_device_on = bcp_test_on[3:0];
wire bcp_device_setup_on = bcp_test_on[3];
wire bcp_device_reset_on = bcp_test_on[2];
wire bcp_device_OUT_on = bcp_test_on[1];
wire bcp_device_IN_on = bcp_test_on[0];
// Last 4 bits of bcp_test_on is used to
// define error occured on whichtest
wire [3:0] bcp_device_test_err = bcp_test_err[3:0];
wire bcp_device_setup_err = bcp_test_err[3];
wire bcp_device_reset_err = bcp_test_err[2];
wire bcp_device_OUT_err = bcp_test_err[1];
wire bcp_device_IN_err = bcp_test_err[0];
// Setup as host (USB Core will be a device)
always @(posedge bcp_device_setup_on)
begin
bcp_prev_err = bcp_err_num;
bcp_test_start = 1;
// For our test
// we do not need to test SOF
//bcp_usb_sof_on <= 1'b1; // Turn on SOF Timer
//tb_is_device <= 1'b0;
// Deal with low/full speed
if (lsdev === 1) begin // Low speed device
clock_low_speed <= 1;
main_proc_retry_repeat_interval = 19'b 1100001101010000000;
main_proc_eop_time = 11'b 10100110110;
end else begin // full speed device
clock_low_speed <= 0;
main_proc_retry_repeat_interval = 18'b 110000110101000000;
main_proc_eop_time = 8'b 10100110;
end
//Emulate host controller by pulling down on data lines
VHDL2V_dplus <= 1'b Z; // Release data+
VHDL2V_dminus <= 1'b Z; // Release data-
// wait for system reset to deassert
#(2000);
if (lsdev === 1) wait (dminus == 1'b 1);
else wait (dplus == 1'b 1);
// start usb_clk
clk_start <= 1'b0;
#(1);
clk_start <= 1'b1;
bcp_test_on[3] = 0;
if (bcp_err_num > bcp_prev_err)
bcp_test_err[3] = 1;
bcp_test_start = 0;
end
// Reset
// Send reset to device
always @(posedge bcp_device_reset_on)
begin
bcp_prev_err = bcp_err_num;
bcp_test_start = 1;
disp_dbg_msg("Sending reset to USB core");
if (lsdev === 1)
usb_reset(22'b 1011011100011011000000);
else
usb_reset(12'b 101000101000);
disp_dbg_msg("USB Reset is done");
bcp_test_on[2] = 0;
if (bcp_err_num > bcp_prev_err)
bcp_test_err[2] = 1;
bcp_test_start = 0;
end
// Device(core) OUT Transaction
// Test will sending out Token
// (Can be SETUP or OUT token)
// Then send out data packet and
// wait for ack if bcp_ack is set
// (Please be aware that SETUP packet must be acknoledged)
// bcp_token_pid, bcp_pkt_pid
// bcp_ack, bcp_endpt, bcp_device must be set up
// properly via backdoor before test is turned on
always @(posedge bcp_device_OUT_on)
begin
bcp_prev_err = bcp_err_num;
bcp_test_start = 1;
disp_dbg_pid("Try to send out token: ", bcp_token_pid);
disp_dbg_int("At endpoint :", bcp_endpt);
disp_dbg_int("Core device id is: ", bcp_device);
token_packet(bcp_token_pid, bcp_device, bcp_endpt);
if (bcp_token_pid == SETUP_PID)
repeat (2) @(posedge usb_clk);
// copy date to main buffer for tx
for (bcp_i=0; bcp_i<bcp_pkt_length; bcp_i = bcp_i+1)
main_proc_hc_pckt_data[bcp_i] = bcp_pkt_data[bcp_i];
disp_dbg_int("Send data to USB core byte count = ", bcp_pkt_length);
disp_dbg_pid("Try to send out data token: ", bcp_pkt_pid);
// Send out data, offset always 0 in our case
data_out_packet(bcp_pkt_pid, bcp_pkt_length, 0);
if (bcp_ack) begin
disp_dbg_msg("Waiting for handshake");
handshake_in_packet(bcp_device_ack);
if (bcp_device_ack != hand_shake_type_ack_hs) begin
bcp_test_err[1] = 1;
disp_dbg_msg("Rcving wrong handshake packet");
case (bcp_device_ack)
// Client software might need to reset
// if the following cases occur.
hand_shake_type_nak_hs :
disp_dbg_msg("NACK");
hand_shake_type_stall_hs:
disp_dbg_msg("STALL");
hand_shake_type_data_hs:
disp_dbg_msg("DATA");
hand_shake_type_bto_hs:
disp_dbg_msg("BUS timeout");
hand_shake_type_corrupted_packet:
disp_dbg_msg("CORRUPTED");
endcase
end
disp_dbg_msg("Handshaking is done");
end
disp_dbg_msg("USB device(core) out transaction is done");
bcp_test_on[1] = 0;
if (bcp_err_num > bcp_prev_err)
bcp_test_err[1] = 1;
bcp_test_start = 0;
end
// Device(core) IN Transaction
// Test will Send out Token
// (This must be IN token)
// Then wait for data
// ack if bcp_ack is set
// bcp_token_pid, bcp_pkt_pid
// bcp_ack, bcp_endpt, bcp_device must be set up
// properly via backdoor before test is turned on
always @(posedge bcp_device_IN_on)
begin
bcp_prev_err = bcp_err_num;
bcp_test_start = 1;
disp_dbg_pid("Try to send out token: ", bcp_token_pid);
disp_dbg_pid("Data pkt id", bcp_pkt_pid);
disp_dbg_int("At endpoint(In transaction) :", bcp_endpt);
disp_dbg_int("Core device id is(In transaction): ", bcp_device);
token_packet(bcp_token_pid, bcp_device, bcp_endpt);
// wait for two usb_clk, is it necessary?
// repeat (2) @posedge (usb_clk);
// copy data for comparison
for (bcp_i=0; bcp_i<bcp_pkt_length; bcp_i=bcp_i+1)
main_proc_hc_pckt_data[bcp_i] = bcp_pkt_data[bcp_i];
// offset is always 0
data_in_packet(bcp_pkt_pid, bcp_pkt_length, 0,
bcp_device_ack, checking_type_check);
// Recv other packets
if (bcp_device_ack != hand_shake_type_data_hs) begin
bcp_test_err[0] = 1;
case (bcp_device_ack)
// Client software might need to reset
// if the following cases occur.
hand_shake_type_ack_hs :
disp_dbg_msg("ACK");
hand_shake_type_nak_hs :
disp_dbg_msg("NACK");
hand_shake_type_stall_hs:
disp_dbg_msg("STALL");
hand_shake_type_data_hs:
disp_dbg_msg("DATA");
hand_shake_type_bto_hs:
disp_dbg_msg("BUS timeout");
hand_shake_type_corrupted_packet:
disp_dbg_msg("CORRUPTED");
endcase
end
// copy rcv data back
for (bcp_i=0; bcp_i<bcp_pkt_length; bcp_i=bcp_i+1)
bcp_pkt_data[bcp_i] = main_proc_hc_rxpkt_data[bcp_i];
if (bcp_ack) begin
disp_dbg_msg("USB device(core) IN transaction ACK back");
// 1 -- Good Ack
// 2 -- Incomplete Ack
// 3 -- Bad Ack
handshake_out_packet(ACK_PID, bcp_ack);
end
disp_dbg_msg("USB device(core) IN transaction is done");
bcp_test_on[0] = 0;
if (bcp_err_num > bcp_prev_err)
bcp_test_err[0] = 1;
bcp_test_start = 0;
end