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 |