Subversion Repositories pentevo

Rev

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

Rev Author Line No. Line
29 lvd 1
// simulate fpga top-level with external dram, rom, z80
722 lvd 2
// (c) 2010-2016 NedoPC
29 lvd 3
 
4
`include "../include/tune.v"
5
 
31 lvd 6
 
467 lvd 7
 
8
//`define ZLOG 1
9
 
10
 
11
 
29 lvd 12
`define HALF_CLK_PERIOD (17.8)
13
 
37 lvd 14
`define ZCLK_DELAY      (9.5)
34 lvd 15
 
16
// toshibo
37 lvd 17
//`define Z80_DELAY_DOWN  (17.0)
18
//`define Z80_DELAY_UP    (22.0)
33 lvd 19
 
34 lvd 20
// z0840008
37 lvd 21
`define Z80_DELAY_DOWN   34
22
`define Z80_DELAY_UP     30
33 lvd 23
 
29 lvd 24
module tb;
25
 
26
        reg fclk;
27
 
28
        wire clkz_out,clkz_in;
29
 
30
        reg iorq_n,mreq_n,rd_n,wr_n; // has some delays relative to z*_n (below)
31
        reg m1_n,rfsh_n;             //
32
 
425 lvd 33
        wire res;                    //
29 lvd 34
        tri1 ziorq_n,zmreq_n,zrd_n,zwr_n,zm1_n,zrfsh_n; // connected to Z80
35
 
425 lvd 36
        tri1 int_n,wait_n,nmi_n;
37
        wire zint_n,zwait_n,znmi_n;
200 lvd 38
 
467 lvd 39
        wire [15:0] #((`Z80_DELAY_DOWN+`Z80_DELAY_UP)/2) za;
40
        wire [ 7:0] #((`Z80_DELAY_DOWN+`Z80_DELAY_UP)/2) zd;
29 lvd 41
 
684 lvd 42
        tri1 [ 7:0] zd_dut_to_z80;
29 lvd 43
 
467 lvd 44
 
684 lvd 45
        reg [15:0] reset_pc = 16'h0000;
46
        reg [15:0] reset_sp = 16'hFFFF;
47
 
48
 
49
 
29 lvd 50
        wire csrom, romoe_n, romwe_n;
200 lvd 51
        wire rompg0_n, dos_n;
425 lvd 52
        wire rompg2,rompg3,rompg4;
29 lvd 53
 
54
        wire [15:0] rd;
55
        wire [9:0] ra;
56
        wire rwe_n,rucas_n,rlcas_n,rras0_n,rras1_n;
57
 
58
 
941 lvd 59
        tri1 [15:0] ide_d;
29 lvd 60
 
61
 
425 lvd 62
        wire hsync,vsync;
63
        wire [1:0] red,grn,blu;
29 lvd 64
 
425 lvd 65
 
66
 
543 lvd 67
        // sdcard
68
        wire sdcs_n, sddo, sddi, sdclk;
425 lvd 69
 
543 lvd 70
        // avr
71
        wire spick, spidi, spido, spics_n;
72
 
73
 
74
 
75
 
280 lvd 76
        assign zwait_n = (wait_n==1'b0) ? 1'b0 : 1'b1;
77
        assign znmi_n = (nmi_n==1'b0) ? 1'b0 : 1'b1;
425 lvd 78
        assign zint_n = (int_n==1'b0) ? 1'b0 : 1'b1;
280 lvd 79
 
80
 
81
 
425 lvd 82
 
83
 
84
 
29 lvd 85
        initial
86
        begin
87
 
88
                fclk = 1'b0;
89
 
90
                forever #`HALF_CLK_PERIOD fclk = ~fclk;
91
        end
92
 
93
 
200 lvd 94
        assign #`ZCLK_DELAY clkz_in = ~clkz_out;
29 lvd 95
 
96
 
97
 
98
 
99
 
100
 
101
 
102
        top DUT( .fclk(fclk),
103
                 .clkz_out(clkz_out),
104
                 .clkz_in(clkz_in),
105
 
106
               // z80
107
                 .iorq_n(iorq_n),
108
                 .mreq_n(mreq_n),
109
                 .rd_n(rd_n),
110
                 .wr_n(wr_n),
111
                 .m1_n(m1_n),
112
                 .rfsh_n(rfsh_n),
113
                 .int_n(int_n),
114
                 .nmi_n(nmi_n),
115
                 .wait_n(wait_n),
116
                 .res(res),
117
                 //
118
                 .d(zd),
119
                 .a(za),
120
 
121
                 // ROM
122
                 .csrom(csrom),
123
                 .romoe_n(romoe_n),
124
                 .romwe_n(romwe_n),
200 lvd 125
                 .rompg0_n(rompg0_n),
126
                 .dos_n(dos_n),
425 lvd 127
                 .rompg2(rompg2),
128
                 .rompg3(rompg3),
129
                 .rompg4(rompg4),
29 lvd 130
 
131
                 // DRAM
132
                 .rd(rd),
133
                 .ra(ra),
134
                 .rwe_n(rwe_n),
135
                 .rucas_n(rucas_n),
136
                 .rlcas_n(rlcas_n),
137
                 .rras0_n(rras0_n),
138
                 .rras1_n(rras1_n),
139
 
140
                 // ZX-bus
141
                 .iorqge1(1'b0),
142
                 .iorqge2(1'b0),
143
 
144
                 // IDE
145
                 .ide_d(ide_d),
146
                 .ide_rdy(1'b1),
147
 
148
                 // VG93
149
                 .step(1'b0),
150
                 .vg_sl(1'b0),
151
                 .vg_sr(1'b0),
152
                 .vg_tr43(1'b0),
153
                 .rdat_b_n(1'b1),
154
                 .vg_wf_de(1'b0),
155
                 .vg_drq(1'b1),
156
                 .vg_irq(1'b1),
157
                 .vg_wd(1'b0),
158
 
159
                 // SDcard SPI
543 lvd 160
                 .sddi(sddi),
161
                 .sddo(sddo),
162
                 .sdcs_n(sdcs_n),
163
                 .sdclk(sdclk),
29 lvd 164
 
165
                 // ATmega SPI
543 lvd 166
                 .spics_n(spics_n),
167
                 .spick(spick),
168
                 .spido(spido),
169
                 .spidi(spidi),
29 lvd 170
 
425 lvd 171
                 .vhsync(hsync),
172
                 .vvsync(vsync),
173
                 .vred(red),
174
                 .vgrn(grn),
175
                 .vblu(blu)
176
 
29 lvd 177
               );
178
 
179
 
467 lvd 180
 
181
 
722 lvd 182
//      assign zd_dut_to_z80 = tb.DUT.ena_ram ? tb.DUT.dout_ram : ( tb.DUT.ena_ports ? tb.DUT.dout_ports : ( tb.DUT.drive_ff ? 8'hFF : 8'bZZZZZZZZ ) );
183
        assign zd_dut_to_z80 = tb.DUT.d_ena ? tb.DUT.d_pre_out : 8'bZZZZ_ZZZZ;
467 lvd 184
 
185
 
186
 
187
 
29 lvd 188
        wire zrst_n = ~res;
189
 
190
        T80a z80( .RESET_n(zrst_n),
191
                  .CLK_n(clkz_in),
280 lvd 192
                  .WAIT_n(zwait_n),
425 lvd 193
                  .INT_n(zint_n),
280 lvd 194
                  .NMI_n(znmi_n),
29 lvd 195
                  .M1_n(zm1_n),
196
                  .RFSH_n(zrfsh_n),
197
                  .MREQ_n(zmreq_n),
198
                  .IORQ_n(ziorq_n),
199
                  .RD_n(zrd_n),
200
                  .WR_n(zwr_n),
201
                  .BUSRQ_n(1'b1),
202
                  .A(za),
467 lvd 203
                  .D_I(zd_dut_to_z80),
684 lvd 204
                  .D_O(zd),
205
                  .ResetPC(reset_pc),
206
                  .ResetSP(reset_sp)
29 lvd 207
                );
208
 
209
        // now make delayed versions of signals
210
        //
280 lvd 211
        reg  mreq_wr_n;
212
        wire iorq_wr_n, full_wr_n;
213
        //
214
        // first, assure there is no X's at the start
215
        //
216
        initial
217
        begin
218
                m1_n      = 1'b1;
219
                rfsh_n    = 1'b1;
220
                mreq_n    = 1'b1;
221
                iorq_n    = 1'b1;
222
                rd_n      = 1'b1;
223
                wr_n      = 1'b1;
224
                mreq_wr_n = 1'b1;
225
        end
226
        //
29 lvd 227
        always @(zm1_n)
228
                if( zm1_n )
229
                        m1_n <= #`Z80_DELAY_UP zm1_n;
230
                else
231
                        m1_n <= #`Z80_DELAY_DOWN zm1_n;
232
        //
233
        always @(zrfsh_n)
234
                if( zrfsh_n )
235
                        rfsh_n <= #`Z80_DELAY_UP zrfsh_n;
236
                else
237
                        rfsh_n <= #`Z80_DELAY_DOWN zrfsh_n;
238
        //
239
        always @(zmreq_n)
240
                if( zmreq_n )
241
                        mreq_n <= #`Z80_DELAY_UP zmreq_n;
242
                else
243
                        mreq_n <= #`Z80_DELAY_DOWN zmreq_n;
244
        //
245
        always @(ziorq_n)
246
                if( ziorq_n )
247
                        iorq_n <= #`Z80_DELAY_UP ziorq_n;
248
                else
249
                        iorq_n <= #`Z80_DELAY_DOWN ziorq_n;
250
        //
251
        always @(zrd_n)
252
                if( zrd_n )
253
                        rd_n <= #`Z80_DELAY_UP zrd_n;
254
                else
255
                        rd_n <= #`Z80_DELAY_DOWN zrd_n;
256
        //
280 lvd 257
        //
258
        // special handling for broken T80 WR_n
511 lvd 259
        //
29 lvd 260
        always @(negedge clkz_in)
280 lvd 261
                mreq_wr_n <= zwr_n;
262
        //
263
        assign iorq_wr_n = ziorq_n | (~zrd_n) | (~zm1_n);
264
        //
265
        assign full_wr_n = mreq_wr_n & iorq_wr_n;
266
        //
267
        // this way glitches won't affect state of wr_n
268
        always @(full_wr_n)
269
                if( !full_wr_n )
270
                        #`Z80_DELAY_DOWN wr_n <= full_wr_n;
29 lvd 271
                else
280 lvd 272
                        #`Z80_DELAY_UP wr_n <= full_wr_n;
29 lvd 273
 
274
 
280 lvd 275
 
276
 
277
 
29 lvd 278
        // ROM model
279
        rom romko(
425 lvd 280
                   .addr( {rompg4,rompg3,rompg2,dos_n, (~rompg0_n), za[13:0]} ),
467 lvd 281
                   .data(zd_dut_to_z80),
29 lvd 282
                   .ce_n( romoe_n | (~csrom) )
283
                 );
284
 
285
        // DRAM model
286
        drammem dramko1(
287
                         .ma(ra),
288
                         .d(rd),
289
                         .ras_n(rras0_n),
290
                         .ucas_n(rucas_n),
291
                         .lcas_n(rlcas_n),
292
                         .we_n(rwe_n)
293
                       );
294
        //
295
        drammem dramko2(
296
                         .ma(ra),
297
                         .d(rd),
298
                         .ras_n(rras1_n),
299
                         .ucas_n(rucas_n),
300
                         .lcas_n(rlcas_n),
301
                         .we_n(rwe_n)
302
                       );
303
        defparam dramko1._verbose_ = 0;
304
        defparam dramko2._verbose_ = 0;
305
 
510 lvd 306
        defparam dramko1._init_ = 0;
307
        defparam dramko2._init_ = 0;
29 lvd 308
 
309
 
510 lvd 310
 
280 lvd 311
`ifndef GATE
200 lvd 312
 
313
        // trace rom page
314
        wire rma14,rma15;
315
 
316
        assign rma14 = DUT.page[0][0];
317
        assign rma15 = DUT.page[0][1];
318
 
319
 
320
        always @(rma14 or rma15)
321
        begin
467 lvd 322
//              $display("at time %t us",$time/1000000);
200 lvd 323
 
467 lvd 324
//              case( {rma15, rma14} )
200 lvd 325
 
467 lvd 326
//              2'b00: $display("BASIC 48");
327
//              2'b01: $display("TR-DOS");
328
//              2'b10: $display("BASIC 128");
329
//              2'b11: $display("GLUKROM");
330
//              default: $display("unknown");
200 lvd 331
 
467 lvd 332
//              endcase
200 lvd 333
 
467 lvd 334
//              $display("");
200 lvd 335
        end
336
 
337
 
338
        // trace ram page
339
        wire [5:0] rpag;
340
 
341
        assign rpag=DUT.page[3][5:0];
342
 
343
        always @(rpag)
344
        begin
467 lvd 345
//              $display("at time %t us",$time/1000000);
200 lvd 346
 
467 lvd 347
//              $display("RAM page is %d",rpag);
200 lvd 348
 
467 lvd 349
//              $display("");
200 lvd 350
        end
351
 
352
 
353
 
425 lvd 354
        // key presses/nmi/whatsoever
200 lvd 355
        initial
356
        begin
425 lvd 357
                #1;
200 lvd 358
                tb.DUT.zkbdmus.kbd = 40'd0;
425 lvd 359
                tb.DUT.zkbdmus.kbd[36] = 1'b1;
360
                @(negedge int_n);
469 lvd 361
                @(negedge int_n);
425 lvd 362
                tb.DUT.zkbdmus.kbd[36] = 1'b0;
363
        end
364
 
467 lvd 365
`endif
366
 
367
 
368
 
369
 
370
 
371
 
372
 
373
 
374
`ifdef ZLOG
375
        reg [ 7:0] old_opcode;
376
        reg [15:0] old_opcode_addr;
377
 
378
        wire [7:0] zdd = zd_dut_to_z80;
379
 
380
        reg was_m1;
381
 
382
        always @(zm1_n)
383
        if( zm1_n )
384
                was_m1 <= 1'b0;
511 lvd 385
        else
467 lvd 386
                was_m1 = 1'b1;
387
 
388
        always @(posedge (zmreq_n | zrd_n | zm1_n | (~zrfsh_n)) )
389
        if( was_m1 )
390
        begin
391
                if( (zdd!==old_opcode) || (za!==old_opcode_addr) )
511 lvd 392
                begin
467 lvd 393
                        if( tb.DUT.z80mem.romnram )
394
//                              $display("Z80OPROM: addr %x, opcode %x, time %t",za,zdd,$time);
395
                                $display("Z80OPROM: addr %x, opcode %x",za,zdd);
396
                        else
397
//                              $display("Z80OPRAM: addr %x, opcode %x, time %t",za,zdd,$time);
398
                                $display("Z80OPRAM: addr %x, opcode %x",za,zdd);
399
                end
400
 
401
                old_opcode      = zdd;
402
                old_opcode_addr = za;
200 lvd 403
        end
467 lvd 404
 
405
        always @(posedge (zmreq_n | zrd_n | (~zm1_n) | (~zrfsh_n)) )
406
        if( !was_m1 )
407
        begin
408
                if( tb.DUT.z80mem.romnram )
409
//                      $display("Z80RDROM: addr %x, rddata %x, time %t",za,zdd,$time);
410
                        $display("Z80RDROM: addr %x, rddata %x",za,zdd);
411
                else
412
//                      $display("Z80RDRAM: addr %x, rddata %x, time %t",za,zdd,$time);
413
                        $display("Z80RDRAM: addr %x, rddata %x",za,zdd);
414
        end
415
 
416
        always @(posedge (zmreq_n | zwr_n | (~zm1_n) | (~zrfsh_n)) )
417
        begin
418
                if( tb.DUT.z80mem.romnram )
419
//                      $display("Z80WRROM: addr %x, wrdata %x, time %t",za,zd,$time);
420
                        $display("Z80WRROM: addr %x, wrdata %x",za,zd);
421
                else
422
//                      $display("Z80WRRAM: addr %x, wrdata %x, time %t",za,zd,$time);
423
                        $display("Z80WRRAM: addr %x, wrdata %x",za,zd);
424
        end
425 lvd 425
`endif
200 lvd 426
 
427
 
428
 
429
 
467 lvd 430
        // turbo
431
`ifdef C7MHZ
432
        initial
433
                force tb.DUT.zclock.turbo = 2'b01;
434
`else
435
        `ifdef C35MHZ
200 lvd 436
 
467 lvd 437
                initial
438
                        force tb.DUT.zclock.turbo = 2'b00;
425 lvd 439
 
467 lvd 440
        `endif
441
`endif
425 lvd 442
 
443
 
684 lvd 444
        // raster type
445
`ifdef CCONTEND
446
        initial
447
                force tb.DUT.modes_raster = 2'b10;
448
`endif
425 lvd 449
 
467 lvd 450
 
451
 
684 lvd 452
 
721 lvd 453
`ifdef NMITEST2
454
 `define M48K
455
 
456
        initial
457
        begin
458
                int i,fd;
459
                logic [7:0] ldbyte;
460
 
727 lvd 461
                reset_pc=16'h8000;
721 lvd 462
                reset_sp=16'h8000;
463
 
464
                fd = $fopen("dimkanmi.bin","rb");
465
                if( !fd )
466
                begin
467
                        $display("Can't open 'dimkanmi.bin'!");
468
                        $stop;
469
                end
470
 
727 lvd 471
                i='h8000;
721 lvd 472
 
473
                begin : load_loop
474
                        while(1)
475
                        begin
476
                                if( 1!=$fread(ldbyte,fd) ) disable load_loop;
477
                                put_byte_48k(i,ldbyte);
478
                                i=i+1;
479
                        end
480
                end
481
                $fclose(fd);
722 lvd 482
 
737 lvd 483
 
484
                wait(res===1'b0);
485
                #(0.2);
738 lvd 486
                tb.DUT.zports.atm_turbo = 1'b1;
737 lvd 487
                tb.DUT.zports.peff7_int[4] = 1'b0;
488
 
489
 
722 lvd 490
                #(100000); // 100 us
491
 
492
                //force nmi_n = 1'b0;
493
                @(posedge fclk);
494
                force tb.DUT.imm_nmi = 1'b1;
495
                @(posedge fclk);
496
                release tb.DUT.imm_nmi;
721 lvd 497
        end
738 lvd 498
`endif
721 lvd 499
 
738 lvd 500
 
501
 
502
`ifdef NMITEST3
503
 `define M48K
504
 
505
        initial
506
        begin
507
                int i,fd;
508
                logic [7:0] ldbyte;
509
 
510
                reset_pc=16'h0068;
511
                reset_sp=16'h8000;
512
 
513
 
514
                #(0.1); // let M48K rom load execute
515
 
516
                fd = $fopen("dimkarom.bin","rb");
517
                if( !fd )
518
                begin
519
                        $display("Can't open 'dimkarom.bin'!");
520
                        $stop;
521
                end
522
 
523
                i='h0066;
524
                begin : load_loop
525
                        while(1)
526
                        begin
527
                                if( 1!=$fread(ldbyte,fd) ) disable load_loop;
528
                                tb.romko.zxevo_rom.mem[i]=ldbyte;
529
                                i=i+1;
530
                        end
531
                end
532
                $fclose(fd);
533
 
534
 
535
                wait(res===1'b0);
536
                #(0.2);
537
                tb.DUT.zports.atm_turbo = 1'b1;
538
                tb.DUT.zports.peff7_int[4] = 1'b0;
539
 
540
 
541
                #(1000000); // 1 ms
542
 
543
                //force nmi_n = 1'b0;
544
                @(posedge fclk);
545
                force tb.DUT.imm_nmi = 1'b1;
546
                @(posedge fclk);
547
                release tb.DUT.imm_nmi;
548
        end
549
`endif
550
 
551
 
727 lvd 552
        // port #FE monitor
553
        wire fe_write;
554
        assign fe_write = (za[7:0]==8'hFE) && !wr_n && !iorq_n;
555
        always @(negedge fe_write)
737 lvd 556
                $display("port #FE monitor: border is %d at %t",zd[2:0],$time());
557
        always @(negedge nmi_n)
558
                $display("nmi monitor: negative edge at %t",$time());  
721 lvd 559
 
560
 
737 lvd 561
 
721 lvd 562
 
684 lvd 563
        // start in 48k mode
564
`ifdef M48K
565
        initial
566
        begin : force_48k_mode
567
 
568
                int i;
569
                int fd;
715 lvd 570
 
738 lvd 571
                fd = $fopen("48.rom","rb");
572
                if( 16384!=$fread(tb.romko.zxevo_rom.mem,fd) )
573
                begin
574
                        $display("Couldn't load 48k ROM!\n");
575
                        $stop;
576
                end
577
                $fclose(fd);
578
 
579
 
715 lvd 580
                wait(res===1'b0);
581
                #(0.1);
684 lvd 582
 
715 lvd 583
                tb.DUT.zports.atm_turbo = 1'b0;
584
                tb.DUT.zports.atm_pen = 1'b0;
585
                tb.DUT.zports.atm_cpm_n = 1'b1;
586
                tb.DUT.zports.atm_pen2 = 1'b0;
587
 
588
                tb.DUT.zdos.dos = 1'b0;
589
 
590
 
720 lvd 591
                tb.DUT.instantiate_atm_pagers[0].atm_pager.pages[0] = 'd0;
592
                tb.DUT.instantiate_atm_pagers[1].atm_pager.pages[0] = 'd5;
593
                tb.DUT.instantiate_atm_pagers[2].atm_pager.pages[0] = 'd2;
594
                tb.DUT.instantiate_atm_pagers[3].atm_pager.pages[0] = 'd0;
595
                tb.DUT.instantiate_atm_pagers[0].atm_pager.pages[1] = 'd0;
596
                tb.DUT.instantiate_atm_pagers[1].atm_pager.pages[1] = 'd5;
597
                tb.DUT.instantiate_atm_pagers[2].atm_pager.pages[1] = 'd2;
598
                tb.DUT.instantiate_atm_pagers[3].atm_pager.pages[1] = 'd0;
599
 
600
                tb.DUT.instantiate_atm_pagers[0].atm_pager.ramnrom[0] = 'd0;
601
                tb.DUT.instantiate_atm_pagers[1].atm_pager.ramnrom[0] = 'd1;
602
                tb.DUT.instantiate_atm_pagers[2].atm_pager.ramnrom[0] = 'd1;
603
                tb.DUT.instantiate_atm_pagers[3].atm_pager.ramnrom[0] = 'd1;
604
                tb.DUT.instantiate_atm_pagers[0].atm_pager.ramnrom[1] = 'd0;
605
                tb.DUT.instantiate_atm_pagers[1].atm_pager.ramnrom[1] = 'd1;
606
                tb.DUT.instantiate_atm_pagers[2].atm_pager.ramnrom[1] = 'd1;
607
                tb.DUT.instantiate_atm_pagers[3].atm_pager.ramnrom[1] = 'd1;
608
 
715 lvd 609
                tb.DUT.zports.atm_scr_mode = 3'b011;
684 lvd 610
 
720 lvd 611
                tb.DUT.zports.peff7_int = 8'h14;
612
                tb.DUT.zports.p7ffd_int = 8'h30;
715 lvd 613
 
720 lvd 614
 
615
 
684 lvd 616
                for(i=0;i<512;i=i+1)
617
                begin : set_palette //                                            R                               G                              B
618
                        tb.DUT.video_top.video_palframe.palette[i] = { (i[1]?{1'b1,i[3]}:2'b00), 1'b0, (i[2]?{1'b1,i[3]}:2'b00), 1'b0, (i[0]?{1'b1,i[3]}:2'b00) };
619
                end
620
 
621
        end
622
`endif
623
 
624
 
625
        // load and start some code after we've reached "1982 Sinclair research ltd"
626
`ifdef START_LOAD
627
        initial
628
        begin
629
                int i,fd;
630
                logic [7:0] ldbyte;
631
 
632
                wait( za==16'h15e0 && zmreq_n==1'b0 && zrd_n == 1'b0 );
633
 
634
                $display("loading and starting...");
635
 
636
                fd = $fopen(`START_NAME,"rb");
637
                for(i=`START_ADDR;i<`START_ADDR+`START_LEN;i=i+1)
638
                begin
639
                        if( 1!=$fread(ldbyte,fd) )
640
                        begin
641
                                $display("can't read byte from input file!");
642
                                $stop;
643
                        end
644
 
645
                        put_byte_48k(i,ldbyte);
646
                end
647
                $fclose(fd);
648
 
649
                $display("load ok!");
650
 
651
                reset_pc = 16'h9718;
652
                reset_sp = 16'h6000;
653
                @(posedge clkz_in);
654
                force tb.zrst_n = 1'b0;
655
                repeat(3) @(posedge clkz_in);
656
                release tb.zrst_n;
657
                @(posedge clkz_in);
658
                reset_pc = 16'h0000;
659
                reset_sp = 16'hFFFF;
660
        end
661
`endif
662
 
663
 
664
 
665
 
666
 
667
 
668
 
669
 
670
 
671
 
467 lvd 672
 
673
 
674
 
511 lvd 675
`ifndef NO_PIXER
425 lvd 676
        // picture out
677
        pixer pixer
678
        (
679
                .clk(fclk),
680
 
681
                .vsync(vsync),
682
                .hsync(hsync),
683
                .red(red),
684
                .grn(grn),
685
                .blu(blu)
686
        );
511 lvd 687
`endif
425 lvd 688
 
689
 
510 lvd 690
/*
280 lvd 691
        // time ticks
692
        always
693
        begin : timemark
200 lvd 694
 
280 lvd 695
                integer ms;
696
 
697
                ms = ($time/1000000);
698
 
467 lvd 699
//              $display("timemark %d ms",ms);
280 lvd 700
 
701
                #10000000.0; // 1 ms
702
        end
510 lvd 703
*/
280 lvd 704
 
705
 
510 lvd 706
        // init dram
721 lvd 707
`ifndef NMITEST2
510 lvd 708
        initial
511 lvd 709
        begin : init_dram
510 lvd 710
                integer i;
941 lvd 711
 
712
                integer page;
713
                integer offset;
714
 
715
                reg [7:0] trd [0:655359];
280 lvd 716
 
941 lvd 717
                integer fd;
942 lvd 718
                integer size;
941 lvd 719
 
720
 
721
 
722
 
510 lvd 723
                for(i=0;i<4*1024*1024;i=i+1)
724
                begin
725
                        put_byte(i,(i%257));
726
                end
941 lvd 727
 
728
                // load TRD
729
                fd = $fopen("boot.trd","rb");
942 lvd 730
                size=$fread(trd,fd);
941 lvd 731
 
942 lvd 732
                if( size>655360 || size<=0 )
941 lvd 733
                begin
942 lvd 734
                        $display("Couldn't load or wrong boot.trd!\n");
941 lvd 735
                        $stop;
736
                end
942 lvd 737
                $fclose(fd);
941 lvd 738
 
942 lvd 739
 
941 lvd 740
                // copy TRD to RAM
942 lvd 741
                page = 32'h0F4;
941 lvd 742
                offset = 0;
743
 
942 lvd 744
                for(i=0;i<size;i=i+1)
941 lvd 745
                begin
746
                        put_byte( .addr(page*16384+offset), .data(trd[i]) );
747
 
748
                        offset = offset + 1;
749
                        if( offset>=16384 )
750
                        begin
751
                                offset = 0;
752
                                page = page - 1;
753
                        end
754
                end
942 lvd 755
 
941 lvd 756
 
942 lvd 757
                $display("boot.trd loaded!\n");
510 lvd 758
        end
721 lvd 759
`endif
280 lvd 760
 
761
 
762
 
763
 
425 lvd 764
 
684 lvd 765
        // cmos simulation
766
        wire [7:0] cmos_addr;
767
        wire [7:0] cmos_read;
768
        wire [7:0] cmos_write;
769
        wire       cmos_rnw;
770
        wire       cmos_req;
771
 
772
        cmosemu cmosemu
773
        (
774
                .zclk(clkz_in),
775
 
776
                .cmos_req  (cmos_req  ),
777
                .cmos_addr (cmos_addr ),
778
                .cmos_rnw  (cmos_rnw  ),
779
                .cmos_read (cmos_read ),
780
                .cmos_write(cmos_write)
781
        );
782
 
783
        assign cmos_req   = tb.DUT.wait_start_gluclock;
784
        assign cmos_rnw   = tb.DUT.wait_rnw;
785
        assign cmos_addr  = tb.DUT.gluclock_addr;
786
        assign cmos_write = tb.DUT.wait_write;
787
 
788
        always @*
789
                force tb.DUT.wait_read = cmos_read;
790
 
791
 
792
 
793
 
543 lvd 794
`ifdef SPITEST
795
        // spitest printing module
796
        // does not hurt at any time (yet), so attached forever
510 lvd 797
 
543 lvd 798
        spitest_print spitest_print(
799
                .sdclk (sdclk ),
800
                .sddi  (sddi  ),
801
                .sddo  (sddo  ),
802
                .sdcs_n(sdcs_n)
803
        );
510 lvd 804
 
543 lvd 805
        // spitest AVR imitator
510 lvd 806
 
543 lvd 807
        spitest_avr spitest_avr(
808
                .spick  (spick  ),
809
                .spics_n(spics_n),
810
                .spido  (spido  ),
811
                .spidi  (spidi  )
812
        );
813
`else
814
        assign sddi = 1'b1;
510 lvd 815
 
543 lvd 816
        assign spics_n = 1'b1;
817
        assign spick   = 1'b0;
818
        assign spido   = 1'b1;
819
`endif
820
 
821
 
822
 
823
 
824
 
943 lvd 825
        // set up breakpoint
826
/*
827
        wire bpt = za===16'h3FEC && zmreq_n===1'b0 && zrd_n===1'b0 && zm1_n===1'b0;
828
        initial
829
        begin
830
                #(1_800_000_000);
831
                @(posedge fclk);
832
                forever
833
                begin
834
                        @(posedge bpt);
835
                        $display("Stop at breakpoint");
836
                        $stop;
837
                end
838
        end
839
*/
576 lvd 840
 
943 lvd 841
        // log INI command
842
        wire [15:0] #(0.1) dza;
843
        wire [ 7:0] #(0.1) dzw;
844
        wire [ 7:0] #(0.1) dzr;
576 lvd 845
 
943 lvd 846
        typedef enum {FETCH,MRD,MWR,IORD,IOWR,IACK} cycle_t;
576 lvd 847
 
943 lvd 848
        cycle_t curr_cycle;
849
        cycle_t cycles[0:3];
850
        logic [15:0] addrs[0:3];
851
        logic [ 7:0] wdata[0:3];
852
        logic [ 7:0] rdata[0:3];
576 lvd 853
 
943 lvd 854
        wire is_fetch, is_mrd, is_mwr, is_iord, is_iowr, is_iack;
576 lvd 855
 
943 lvd 856
        wire is_any;
576 lvd 857
 
858
 
859
 
860
 
943 lvd 861
        assign dza = za;
862
        assign dzw = zd;
863
        assign dzr = zd_dut_to_z80;
576 lvd 864
 
943 lvd 865
        assign is_fetch = zm1_n===1'b0 && zmreq_n===1'b0 &&                   zrd_n===1'b0;
866
        assign is_mrd   = zm1_n===1'b1 && zmreq_n===1'b0 &&                   zrd_n===1'b0;
867
        assign is_mwr   =                 zmreq_n===1'b0 &&                                   zwr_n===1'b0;
868
        assign is_iord  =                                   ziorq_n===1'b0 && zrd_n===1'b0;
869
        assign is_iowr  =                                   ziorq_n===1'b0 &&                 zwr_n===1'b0;
870
        assign is_iack  = zm1_n===1'b0 &&                   ziorq_n===1'b0;
576 lvd 871
 
943 lvd 872
        assign is_any = is_fetch || is_mrd || is_mwr || is_iord || is_iowr || is_iack;
873
 
874
 
875
        always @(negedge is_any)
876
        begin : remember
877
                int i;
878
 
879
                for(i=1;i<4;i++)
880
                begin
881
                        addrs [i]  <= addrs [i-1];
882
                        cycles[i]  <= cycles[i-1];
883
 
884
                        wdata [i]  <= wdata [i-1];
885
                        rdata [i]  <= rdata [i-1];
886
                end
887
 
888
                addrs[0] <= dza;
889
                cycles[0] <= curr_cycle;
890
 
891
                wdata[0] <= dzw;
892
                rdata[0] <= dzr;
893
        end
894
 
895
        always @(posedge is_any)
896
        if(      is_fetch ) curr_cycle <= FETCH;
897
        else if( is_mrd )   curr_cycle <= MRD;
898
        else if( is_mwr )   curr_cycle <= MWR;
899
        else if( is_iord )  curr_cycle <= IORD;
900
        else if( is_iowr )  curr_cycle <= IOWR;
901
        else if( is_iack )  curr_cycle <= IACK;
902
        else
903
        begin
904
                $display("Spurious cycle detect!");
905
                $stop;
906
        end
907
 
908
 
909
        // actual break
910
        always @(negedge is_any)
911
        begin
912
                if( cycles[3]==FETCH && addrs[3][15:0 ]==16'h3FEC && rdata[3]==8'hED &&
913
                    cycles[2]==FETCH &&                              rdata[2]==8'hA2 &&
914
                    cycles[1]==IORD  &&
915
                    cycles[0]==MWR   && addrs[0][15:14]== 2'd0
916
                )
917
                begin
945 lvd 918
                        $display("trd INI caught! port=%04x, wraddr=%04x, time=%t",addrs[1],addrs[0],$time());
943 lvd 919
                end
920
        end
921
 
922
 
923
 
924
 
925
 
926
 
927
 
928
 
929
 
930
 
951 lvd 931
        // timestamps
932
        always
933
        begin
934
                $display("Running for %t ms",$time()/1000000000.0);
935
                #1000000.0;
936
        end
943 lvd 937
 
938
 
939
 
940
 
941
 
968 lvd 942
        // generate nmi after 2s
943
        initial
944
        begin
945
                #2000000000.0;
943 lvd 946
 
968 lvd 947
                force DUT.set_nmi[0] = 1'b1;
948
                #1000000.0;
949
                release DUT.set_nmi[0];
950
        end
943 lvd 951
 
952
 
953
 
951 lvd 954
 
955
 
956
 
957
 
958
 
959
 
960
 
425 lvd 961
        task put_byte;
962
 
963
                input [21:0] addr;
964
                input [ 7:0] data;
965
 
966
 
511 lvd 967
 
425 lvd 968
                reg [19:0] arraddr;
969
 
970
                begin
971
 
972
                        arraddr = { addr[21:12], addr[11:2] };
973
 
974
                        case( addr[1:0] ) // chipsel, bytesel
975
 
976
                        2'b00: tb.dramko1.array[arraddr][15:8] = data;
977
                        2'b01: tb.dramko1.array[arraddr][ 7:0] = data;
978
                        2'b10: tb.dramko2.array[arraddr][15:8] = data;
979
                        2'b11: tb.dramko2.array[arraddr][ 7:0] = data;
980
 
981
                        endcase
982
                end
983
 
984
        endtask
985
 
684 lvd 986
        task put_byte_48k
987
        (
988
                input [15:0] addr,
989
                input [ 7:0] data
990
        );
425 lvd 991
 
684 lvd 992
                case( addr[15:14] )
993
                        2'b01: put_byte(addr-16'h4000 + 22'h14000,data);
994
                        2'b10: put_byte(addr-16'h8000 + 22'h08000,data);
995
                        2'b11: put_byte(addr-16'hc000 + 22'h00000,data);
996
                endcase
997
        endtask
425 lvd 998
 
999
 
1000
 
684 lvd 1001
 
29 lvd 1002
endmodule
1003
 
1004