Subversion Repositories zxusbnet

Rev

Rev 185 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
15 lvd 1
// ZXiznet project
121 lvd 2
// (c) NedoPC 2018
15 lvd 3
//
4
// testbench
5
 
6
 
76 lvd 7
`timescale 1ns/100ps
15 lvd 8
 
184 lvd 9
//// CPU at 14 or 28MHz
10
`ifdef CPU28MHZ
11
 `define HALF_CPU_PERIOD (17.8)
12
`else
13
 `define HALF_CPU_PERIOD (35.7)
14
`endif
15 lvd 15
 
184 lvd 16
 
72 lvd 17
// CPU at 7MHz
75 lvd 18
//`define HALF_CPU_PERIOD (70)
15 lvd 19
 
72 lvd 20
// filter clock
84 lvd 21
`define HALF_FCLK_PERIOD (10.4)
72 lvd 22
 
15 lvd 23
module tb;
24
 
25
        reg rst_n;
26
        reg clk;
27
 
72 lvd 28
        reg fclk;
15 lvd 29
 
72 lvd 30
 
15 lvd 31
        tri1 iorq_n,
32
             mreq_n,
33
             rd_n,
34
             wr_n;
35
 
30 lvd 36
        tri1 int_n;
16 lvd 37
 
38
        wire csrom_n;
39
 
40
        wire iorqge,
41
             blkrom;
42
 
43
 
15 lvd 44
        wire [15:0] a;
45
        wire [ 7:0] d;
46
 
84 lvd 47
        tri  [ 7:0] #1 bd;
15 lvd 48
 
28 lvd 49
        wire brd_n, bwr_n;
50
 
51
 
15 lvd 52
        reg [7:0] tmp;
53
 
54
 
55
 
56
 
16 lvd 57
        wire [9:0] w5300_addr;
58
        wire       w5300_rst_n;
59
        wire       w5300_cs_n;
60
        wire       w5300_int_n;
61
 
62
        wire       sl811_rst_n;
63
        wire       sl811_a0;
64
        wire       sl811_cs_n;
29 lvd 65
        wire       sl811_ms_n;
16 lvd 66
        wire       sl811_intrq;
67
 
29 lvd 68
 
69
 
23 lvd 70
        reg usb_power;
16 lvd 71
 
23 lvd 72
 
16 lvd 73
        reg [1:0] where_rom;
74
 
75
 
76
 
77
 
72 lvd 78
        // filter clock
79
        initial
80
        begin
81
                fclk = 1'b1;
16 lvd 82
 
72 lvd 83
                forever #`HALF_FCLK_PERIOD fclk = ~fclk;
84
        end
85
 
86
 
15 lvd 87
        initial
88
        begin
89
                clk = 1'b1;
90
 
91
                forever #`HALF_CPU_PERIOD clk = ~clk;
92
        end
93
 
94
 
95
        initial
96
        begin
97
                rst_n = 1'b0;
98
 
99
                repeat(3) @(posedge clk);
100
 
101
                rst_n <= 1'b1;
102
        end
103
 
104
 
105
 
16 lvd 106
        initial
107
        begin
108
                where_rom = 2'b00;
33 lvd 109
 
110
                usb_power = 1'b0;
16 lvd 111
        end
15 lvd 112
 
16 lvd 113
 
114
 
115
 
15 lvd 116
 
117
 
118
 
119
 
120
        top DUT
121
        (
72 lvd 122
                .fclk(fclk),
84 lvd 123
 
15 lvd 124
                .za(a),
125
                .zd(d),
126
 
127
                .ziorq_n(iorq_n),
128
                .zmreq_n(mreq_n),
129
                .zrd_n(rd_n),
130
                .zwr_n(wr_n),
131
 
16 lvd 132
                .zcsrom_n(csrom_n),
133
 
134
                .ziorqge(iorqge),
135
                .zblkrom(blkrom),
15 lvd 136
 
16 lvd 137
                .zrst_n(rst_n),
138
                .zint_n(int_n),
15 lvd 139
 
28 lvd 140
                .bd(bd),
16 lvd 141
 
28 lvd 142
                .bwr_n(bwr_n),
143
                .brd_n(brd_n),
144
 
145
 
16 lvd 146
                .w5300_rst_n(w5300_rst_n),
147
                .w5300_addr (w5300_addr ),
148
                .w5300_cs_n (w5300_cs_n ),
149
                .w5300_int_n(w5300_int_n),
150
 
151
                .sl811_rst_n(sl811_rst_n),
152
                .sl811_intrq(sl811_intrq),
28 lvd 153
                .sl811_ms_n (sl811_ms_n ),
16 lvd 154
                .sl811_cs_n (sl811_cs_n ),
23 lvd 155
                .sl811_a0   (sl811_a0   ),
16 lvd 156
 
23 lvd 157
                .usb_power(usb_power)
158
 
15 lvd 159
        );
160
 
161
 
162
 
163
 
164
 
165
 
166
 
167
 
168
 
169
 
170
 
171
 
29 lvd 172
        ssz80 z
15 lvd 173
        (
174
                .clk  (clk  ),
175
                .rst_n(rst_n),
176
 
177
                .iorq_n(iorq_n),
178
                .mreq_n(mreq_n),
179
                .rd_n  (rd_n  ),
180
                .wr_n  (wr_n  ),
181
 
182
                .a(a),
183
                .d(d)
184
        );
185
 
186
 
187
 
188
 
189
 
29 lvd 190
        w5300 w
16 lvd 191
        (
192
                .rst_n(w5300_rst_n),
193
                .addr (w5300_addr ),
194
                .cs_n (w5300_cs_n ),
28 lvd 195
                .rd_n (brd_n      ),
196
                .wr_n (bwr_n      ),
23 lvd 197
                .int_n(w5300_int_n),
28 lvd 198
                .d(bd)
16 lvd 199
        );
200
 
201
 
29 lvd 202
        sl811 s
16 lvd 203
        (
204
                .rst_n(sl811_rst_n),
205
                .a0   (sl811_a0   ),
206
                .cs_n (sl811_cs_n ),
28 lvd 207
                .wr_n (bwr_n      ),
208
                .rd_n (brd_n      ),
209
                .ms   (~sl811_ms_n),
210
                .intrq(sl811_intrq),
211
                .d(bd)
16 lvd 212
        );
213
 
214
 
29 lvd 215
        // csrom gen
30 lvd 216
        assign csrom_n = !(a[15:14]==where_rom[1:0]);
16 lvd 217
 
29 lvd 218
 
219
 
220
 
221
 
222
 
223
////////////////////////////////////////////////////////////////////////////////        
224
////////////////////////////////////////////////////////////////////////////////        
225
////////////////////////////////////////////////////////////////////////////////        
226
/// here start tests
16 lvd 227
 
30 lvd 228
        reg [15:0] rstint_port = 16'h83_AB;
157 lvd 229
//      reg [15:0] w5300_port  = 16'h82_AB;
230
//      reg [15:0] sl811_port  = 16'h81_AB;
231
        reg [15:0] cfg_port    = 16'h82_AB;
232
        reg [15:0] wiomap_port = 16'h81_AB;
30 lvd 233
        reg [15:0] sl_addr     = 16'h80_AB;
234
        reg [15:0] sl_data     = 16'h7F_AB;
235
 
29 lvd 236
        initial
237
        begin : tests
238
 
239
 
240
                reg [7:0] tmp;
241
                reg [7:0] tmp2;
16 lvd 242
 
29 lvd 243
 
244
                wait(rst_n===1'b1);
16 lvd 245
 
29 lvd 246
                repeat(10) @(posedge clk);
247
 
248
 
16 lvd 249
 
31 lvd 250
                test_pwon_resets();
251
                test_pwon_ints();
30 lvd 252
 
253
 
254
 
31 lvd 255
                forever // repeat(10000)
30 lvd 256
                begin
32 lvd 257
                        case( $random%6 )
31 lvd 258
                        0: check_sl811_access();
185 lvd 259
//`ifndef CPU28MHZ
260
//                      1: check_w5300_mem_access();
261
//`endif
32 lvd 262
                        2: check_w5300_port_access();
263
                        3: test_resets();
264
                        4: check_sl811_port();
265
                        5: test_ints();
31 lvd 266
                        endcase
30 lvd 267
                end
268
 
269
 
270
 
271
 
272
 
273
 
274
 
275
 
276
 
277
 
278
 
279
 
280
 
281
 
282
 
283
 
284
 
285
                $display("all tests passed!");
286
                $stop;
287
        end
288
 
289
 
290
 
291
 
292
 
293
 
84 lvd 294
        task wait_end_access();
295
 
296
                reg a;
297
 
298
                a = 1'b0;
299
                wait( brd_n==1'b1 && bwr_n==1'b1 );
300
 
301
                a <= 1'b1;
302
                wait(a==1'b1);
303
 
304
        endtask
30 lvd 305
 
306
 
307
 
308
 
309
 
310
 
311
 
312
 
313
        // translates memory address to w5300 address in accordance with specs
314
        function [9:0] mk_w5300_addr( input [13:0] mem_addr );
315
 
316
                if( mem_addr<14'h2000 )
317
                begin
318
                        mk_w5300_addr = mem_addr[9:0];
319
                end
320
                else if( mem_addr<14'h3000 )
321
                begin
322
                        mk_w5300_addr[9] = 1'b1;
323
                        mk_w5300_addr[8:6] = mem_addr[11:9];
324
                        mk_w5300_addr[5:1] = 5'b10111;
325
                        mk_w5300_addr[0] = mem_addr[0];
326
                end
327
                else // if( mem_addr<14'h4000 )
328
                begin
329
                        mk_w5300_addr[9] = 1'b1;
330
                        mk_w5300_addr[8:6] = mem_addr[11:9];
331
                        mk_w5300_addr[5:1] = 5'b11000;
332
                        mk_w5300_addr[0] = mem_addr[0];
333
                end
334
 
335
        endfunction
336
 
337
 
338
 
339
 
340
 
341
 
32 lvd 342
        task check_w5300_port_access();
30 lvd 343
 
344
                reg [7:0] tmp,rddata,wrdata;
32 lvd 345
                reg [9:0] waddr;
346
                reg       a0_inv;
347
 
348
                reg [15:0] port;
349
 
350
 
351
                a0_inv = $random>>31;
352
 
353
                waddr = $random>>22;
354
 
355
 
356
 
157 lvd 357
                z.iowr(cfg_port,{3'd0,1'b1,a0_inv,3'd0});
32 lvd 358
 
157 lvd 359
                z.iord(cfg_port,tmp);
360
                if( tmp[4:0]!=={1'b1,a0_inv,3'd0} )
32 lvd 361
                begin
362
                        $display("can't set w5300 port!");
363
                        $stop;
364
                end
365
 
157 lvd 366
 
367
                z.iowr(wiomap_port,waddr[9:6]);
368
                z.iord(wiomap_port,tmp);
369
                if( tmp[3:0]!==waddr[9:6] )
370
                begin
371
                        $display("can't set wiomap port!");
372
                        $stop;
373
                end
374
 
375
 
376
 
32 lvd 377
                // make access port address
378
                port = sl_data;
157 lvd 379
                port[13:8] = waddr[5:0];
32 lvd 380
 
381
 
382
                w.init_access(); // clear access_* to X
383
 
384
 
385
                if( $random>>31 )
386
                begin
387
                        wrdata = $random>>24;
388
                        z.iowr(port,wrdata);
84 lvd 389
                        wait_end_access();
32 lvd 390
                        if( w.get_addr()!==(waddr^a0_inv) ||
391
                            w.get_rnw()!==1'b0            ||
392
                            w.get_wr_data()!==wrdata      )
393
                        begin
394
                                $display("w5300 port write failed!");
395
                                $stop;
396
                        end
397
                end
398
                else
399
                begin
400
                        rddata = $random>>24;
401
                        w.set_rd_data(rddata);
402
                        z.iord(port,tmp);
184 lvd 403
`ifdef CPU28MHZ
404
                        wait_end_access();
405
`else
406
                        @(negedge clk);
407
`endif
32 lvd 408
                        if( w.get_addr()!==(waddr^a0_inv) ||
409
                            w.get_rnw()!==1'b1            ||
410
                            tmp!==rddata                  )
411
                        begin
412
                                $display("w5300 port read failed!");
413
                                $stop;
414
                        end
415
                end
416
 
417
        endtask
418
 
419
 
420
 
421
 
422
        task check_w5300_mem_access;
423
 
424
                reg [7:0] tmp,rddata,wrdata;
30 lvd 425
                reg [15:0] memaddr;
426
                reg [ 9:0] waddr;
427
 
428
                reg [1:0] rom;
429
                reg       a0_inv;
430
                reg       sub_ena;
431
 
432
 
433
                rom    = $random>>30;
434
                a0_inv = $random>>31;
435
                sub_ena= $random>>31;
436
 
157 lvd 437
                z.iowr(cfg_port,{4'd0,a0_inv,sub_ena,rom});
30 lvd 438
 
157 lvd 439
                z.iord(cfg_port,tmp);
440
                if( tmp[4:0]!=={1'd0,a0_inv,sub_ena,rom} )
30 lvd 441
                begin
442
                        $display("can't set w5300 port!");
443
                        $stop;
444
                end
445
 
446
 
447
                if( $random>>31 )
448
                        where_rom = rom;
449
                else
450
                begin
451
                        where_rom = $random>>30;
452
                        while( where_rom==rom )
453
                                where_rom = $random>>30;
454
                end
455
 
456
 
457
 
458
                w.init_access(); // clear access_* to X
459
 
460
 
461
                memaddr = $random>>18;
462
                memaddr[15:14] = where_rom;
463
 
464
 
465
 
466
                if( $random>>31 )
467
                begin
84 lvd 468
                        repeat(10)
30 lvd 469
                        begin
84 lvd 470
                                wrdata = $random>>24;
471
                                z.memwr(memaddr,wrdata);
472
                                wait_end_access();
473
                                if( where_rom==rom && sub_ena )
30 lvd 474
                                begin
84 lvd 475
                                        if( w.get_addr()!==(mk_w5300_addr(memaddr[13:0])^a0_inv) ||
476
                                            w.get_rnw()!==1'b0                                   ||
477
                                            w.get_wr_data()!==wrdata                             )
478
                                        begin
479
                                                $display("w5300 write failed!");
480
                                                $stop;
481
                                        end
30 lvd 482
                                end
84 lvd 483
                                else
30 lvd 484
                                begin
84 lvd 485
                                        if( w.get_addr()!=={10{1'bX}} || w.get_rnw()!==1'bX || w.get_wr_data()!=={8{1'bX}} )
486
                                        begin
487
                                                $display("write succeeded with wrong ROM mapping!");
488
                                                $stop;
489
                                        end
30 lvd 490
                                end
491
                        end
492
                end
493
                else
494
                begin
495
                        rddata = $random>>24;
496
                        w.set_rd_data(rddata);
497
                        z.memrd(memaddr,tmp);
72 lvd 498
                        @(negedge clk);
30 lvd 499
                        if( where_rom==rom && sub_ena )
500
                        begin
501
                                if( w.get_addr()!==(mk_w5300_addr(memaddr[13:0])^a0_inv) ||
502
                                    w.get_rnw()!==1'b1                                   ||
503
                                    tmp!==rddata                                         )
504
                                begin
505
                                        $display("w5300 read failed!");
506
                                        $stop;
507
                                end
508
                        end
509
                        else
510
                        begin
511
                                if( w.get_addr()!=={10{1'bX}} || w.get_rnw()!==1'bX )
512
                                begin
513
                                        $display("read succeeded with wrong ROM mapping!");
514
                                        $stop;
515
                                end
516
                        end
517
                end
518
 
519
 
520
 
521
 
522
 
523
 
524
 
525
 
526
 
527
 
528
 
529
 
530
 
531
        endtask
532
 
533
 
534
 
535
 
536
 
537
 
538
 
539
        task check_sl811_access;
540
 
541
                reg [7:0] tmp, rddata, wrdata;
542
 
543
                reg [15:0] rdport;
544
 
545
 
32 lvd 546
                // turn off w5300 port access
157 lvd 547
                z.iord(cfg_port,tmp);
32 lvd 548
                if( tmp[4]!==1'b0 )
549
                begin
550
                        tmp[4]=1'b0;
157 lvd 551
                        z.iowr(cfg_port,tmp);
32 lvd 552
                end
553
 
554
 
30 lvd 555
                // check address reg
556
                wrdata=$random>>24;
557
                z.iowr(sl_addr,wrdata);
84 lvd 558
                wait_end_access();
30 lvd 559
                if( s.get_rnw()!==1'b0 || s.get_addr()!==1'b0 || s.get_wr_data()!==wrdata )
560
                begin
561
                        $display("sl811 address write failed!");
562
                        $stop;
563
                end
564
                //
565
                rddata=$random>>24;
566
                s.set_rd_data(rddata);
567
                z.iord(sl_addr,tmp);
184 lvd 568
`ifdef CPU28MHZ
569
                wait_end_access();
570
`else
571
                @(negedge clk);
572
`endif
30 lvd 573
                if( s.get_rnw()!==1'b1 || s.get_addr()!==1'b0 || tmp!==rddata )
574
                begin
184 lvd 575
                        $display("sl811 address read failed! rddata=%h, tmp=%h, get_rnw=%d, reg_addr=%h",rddata,tmp,s.get_rnw(),s.get_addr());
30 lvd 576
                        $stop;
577
                end
578
 
32 lvd 579
 
580
 
30 lvd 581
                // check data reg
582
                rdport=sl_data;
583
                rdport[14:8]=$random>>25;
584
                wrdata=$random>>24;
585
                z.iowr(rdport,wrdata);
84 lvd 586
                wait_end_access();
30 lvd 587
                if( s.get_rnw()!==1'b0 || s.get_addr()!==1'b1 || s.get_wr_data()!==wrdata )
588
                begin
589
                        $display("sl811 data write failed!");
590
                        $stop;
591
                end
592
                //
593
                rddata=$random>>24;
594
                s.set_rd_data(rddata);
595
                z.iord(rdport,tmp);
184 lvd 596
`ifdef CPU28MHZ
597
                wait_end_access();
598
`else
599
                @(negedge clk);
600
`endif
30 lvd 601
                if( s.get_rnw()!==1'b1 || s.get_addr()!==1'b1 || tmp!==rddata )
602
                begin
603
                        $display("sl811 data read failed!");
604
                        $stop;
605
                end
606
 
607
        endtask
608
 
609
 
610
 
611
 
612
        task check_sl811_port;
613
 
614
                reg [7:0] tmp;
615
 
31 lvd 616
                reg ms;
617
 
618
                ms=$random>>31;
619
 
157 lvd 620
                z.iowr(cfg_port,{1'b0,ms,6'd0});
84 lvd 621
                wait_end_access();
31 lvd 622
 
30 lvd 623
                @(posedge clk);
71 lvd 624
                if( (rst_n===1'b1 && s.get_ms()!==ms   ) ||
625
                    (rst_n===1'b0 && s.get_ms()!==1'b1 ) )
30 lvd 626
                begin
31 lvd 627
                        $display("sl811_ms_n behaves wrong!");
30 lvd 628
                        $stop;
629
                end
630
 
31 lvd 631
 
632
                usb_power <= $random>>31;
30 lvd 633
                @(posedge clk);
157 lvd 634
                z.iord(cfg_port,tmp);
635
                if( tmp[7]!==usb_power )
30 lvd 636
                begin
31 lvd 637
                        $display("can't sense usb_power!");
30 lvd 638
                        $stop;
639
                end
640
 
641
        endtask
642
 
643
 
644
 
645
 
646
 
31 lvd 647
        task test_pwon_ints;
30 lvd 648
 
649
                reg [7:0] tmp;
650
 
651
                // check ints
652
                z.iord(rstint_port,tmp);
653
                if( tmp[1:0]!==2'b00 )
654
                begin
655
                        $display("int requests after reset!");
656
                        $stop;
657
                end
658
                if( tmp[3:2]!==2'b00 )
659
                begin
660
                        $display("ints enabled after reset!");
661
                        $stop;
662
                end
663
                if( tmp[7]!==1'b0 )
664
                begin
665
                        $display("internal int is on after reset!");
666
                        $stop;
667
                end
668
                if( tmp[6]!==1'b0 )
669
                begin
670
                        $display("ext.int assertion enabled after reset!");
671
                        $stop;
672
                end
31 lvd 673
                if( int_n!==1'b1 )
30 lvd 674
                begin
31 lvd 675
                        $display("ext.int asserted after reset!");
30 lvd 676
                        $stop;
677
                end
31 lvd 678
        endtask
679
 
680
 
681
 
682
 
683
 
684
        task test_ints;
685
 
686
                reg [7:0] tmp;
687
 
688
                reg [1:0] ints,intena;
689
 
690
                reg eintena;
691
 
692
 
693
                ints = $random>>30;
694
 
695
                intena = $random>>30;
696
 
697
                eintena = $random>>31;
698
 
699
 
700
                s.set_intrq(ints[1]);
701
                w.set_int_n(~ints[0]);
702
 
703
                @(posedge clk);
704
 
705
 
30 lvd 706
                z.iord(rstint_port,tmp);
31 lvd 707
                tmp[3:2]=intena;
708
                tmp[6]=eintena;
709
                z.iowr(rstint_port,tmp);
710
 
711
 
30 lvd 712
                z.iord(rstint_port,tmp);
31 lvd 713
 
714
                if( tmp[1]!==ints[1] || tmp[0]!==ints[0] )
30 lvd 715
                begin
31 lvd 716
                        $display("wrong int signals states!");
30 lvd 717
                        $stop;
718
                end
31 lvd 719
 
720
                if( (  (ints&intena) && tmp[7]!==1'b1) ||
721
                    ( !(ints&intena) && tmp[7]!==1'b0) )
30 lvd 722
                begin
31 lvd 723
                        $display("wrong internal int state!");
30 lvd 724
                        $stop;
725
                end
31 lvd 726
 
727
                if( tmp[6]!==eintena )
30 lvd 728
                begin
31 lvd 729
                        $display("wrong eintena state!");
30 lvd 730
                        $stop;
731
                end
31 lvd 732
 
733
                if( (eintena && (ints&intena)) ? (int_n!==1'b0) : (int_n!==1'b1) )
30 lvd 734
                begin
31 lvd 735
                        $display("wrong int_n forming!");
30 lvd 736
                        $stop;
737
                end
31 lvd 738
 
739
 
740
 
741
 
742
        endtask
743
 
744
 
745
 
746
 
747
 
748
 
749
        task test_resets;
750
 
751
                reg [7:0] tmp;
752
 
753
                reg [1:0] resets;
754
 
755
 
756
 
757
                resets = $random>>30;
758
 
759
 
760
                // read-modify-write reset register
761
                z.iord(rstint_port,tmp);
762
 
763
                tmp[5:4] = resets[1:0];
764
 
765
                z.iowr(rstint_port,tmp);
766
 
767
                if( s.get_rst_n() !== resets[1] )
30 lvd 768
                begin
31 lvd 769
                        $display("no control of sl811 reset!");
30 lvd 770
                        $stop;
771
                end
31 lvd 772
 
773
                if( w.get_rst_n() !== resets[0] )
30 lvd 774
                begin
31 lvd 775
                        $display("no control of w5300 reset!");
30 lvd 776
                        $stop;
777
                end
31 lvd 778
 
30 lvd 779
        endtask
780
 
781
 
782
 
31 lvd 783
 
784
        task test_pwon_resets;
785
 
786
                reg [7:0] tmp;
787
 
29 lvd 788
                // test resets state after reset
789
                if( w.get_rst_n() !== 1'b0 )
790
                begin
791
                        $display("w5300 hasn't rst_n=0 after reset!");
792
                        $stop;
793
                end
794
                //
795
                if( s.get_rst_n() !== 1'b0 )
796
                begin
797
                        $display("sl811 hasn't rst_n=0 after reset!");
798
                        $stop;
799
                end
16 lvd 800
 
29 lvd 801
                // read reset register and check it
802
                z.iord(rstint_port,tmp);
803
                if( tmp[5:4]!==2'b00 )
804
                begin
805
                        $display("reset bits in #83AB not 0 after reset!");
806
                        $stop;
807
                end
16 lvd 808
 
30 lvd 809
        endtask
29 lvd 810
 
811
 
812
 
813
 
31 lvd 814
 
815
 
816
 
817
 
818
 
819
 
820
 
821
        // time marks
822
        always
823
        begin : timemarks
824
 
825
                int ms;
826
 
827
                ms = ($time/1000000);
828
 
829
                #1000000.0;
830
 
831
                $display("time mark: %d ms",ms);
832
        end
833
 
834
 
835
 
836
 
837
 
15 lvd 838
endmodule
839