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