Subversion Repositories pentevo

Rev

Rev 951 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. // simulate fpga top-level with external dram, rom, z80
  2. // (c) 2010-2016 NedoPC
  3.  
  4. `include "../include/tune.v"
  5.  
  6.  
  7.  
  8. //`define ZLOG 1
  9.  
  10.  
  11.  
  12. `define HALF_CLK_PERIOD (17.8)
  13.  
  14. `define ZCLK_DELAY      (9.5)
  15.  
  16. // toshibo
  17. //`define Z80_DELAY_DOWN  (17.0)
  18. //`define Z80_DELAY_UP    (22.0)
  19.  
  20. // z0840008
  21. `define Z80_DELAY_DOWN   34
  22. `define Z80_DELAY_UP     30
  23.  
  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.  
  33.         wire res;                    //
  34.         tri1 ziorq_n,zmreq_n,zrd_n,zwr_n,zm1_n,zrfsh_n; // connected to Z80
  35.  
  36.         tri1 int_n,wait_n,nmi_n;
  37.         wire zint_n,zwait_n,znmi_n;
  38.  
  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.  
  42.         tri1 [ 7:0] zd_dut_to_z80;
  43.  
  44.  
  45.         reg [15:0] reset_pc = 16'h0000;
  46.         reg [15:0] reset_sp = 16'hFFFF;
  47.  
  48.  
  49.  
  50.         wire csrom, romoe_n, romwe_n;
  51.         wire rompg0_n, dos_n;
  52.         wire rompg2,rompg3,rompg4;
  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.  
  59.         tri1 [15:0] ide_d;
  60.  
  61.  
  62.         wire hsync,vsync;
  63.         wire [1:0] red,grn,blu;
  64.  
  65.  
  66.  
  67.         // sdcard
  68.         wire sdcs_n, sddo, sddi, sdclk;
  69.  
  70.         // avr
  71.         wire spick, spidi, spido, spics_n;
  72.  
  73.  
  74.  
  75.  
  76.         assign zwait_n = (wait_n==1'b0) ? 1'b0 : 1'b1;
  77.         assign znmi_n = (nmi_n==1'b0) ? 1'b0 : 1'b1;
  78.         assign zint_n = (int_n==1'b0) ? 1'b0 : 1'b1;
  79.  
  80.  
  81.  
  82.  
  83.  
  84.  
  85.         initial
  86.         begin
  87.  
  88.                 fclk = 1'b0;
  89.  
  90.                 forever #`HALF_CLK_PERIOD fclk = ~fclk;
  91.         end
  92.  
  93.  
  94.         assign #`ZCLK_DELAY clkz_in = ~clkz_out;
  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),
  125.                  .rompg0_n(rompg0_n),
  126.                  .dos_n(dos_n),
  127.                  .rompg2(rompg2),
  128.                  .rompg3(rompg3),
  129.                  .rompg4(rompg4),
  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
  160.                  .sddi(sddi),
  161.                  .sddo(sddo),
  162.                  .sdcs_n(sdcs_n),
  163.                  .sdclk(sdclk),
  164.  
  165.                  // ATmega SPI
  166.                  .spics_n(spics_n),
  167.                  .spick(spick),
  168.                  .spido(spido),
  169.                  .spidi(spidi),
  170.  
  171.                  .vhsync(hsync),
  172.                  .vvsync(vsync),
  173.                  .vred(red),
  174.                  .vgrn(grn),
  175.                  .vblu(blu)
  176.  
  177.                );
  178.  
  179.  
  180.  
  181.  
  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;
  184.  
  185.  
  186.  
  187.  
  188.         wire zrst_n = ~res;
  189.  
  190.         T80a z80( .RESET_n(zrst_n),
  191.                   .CLK_n(clkz_in),
  192.                   .WAIT_n(zwait_n),
  193.                   .INT_n(zint_n),
  194.                   .NMI_n(znmi_n),
  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),
  203.                   .D_I(zd_dut_to_z80),
  204.                   .D_O(zd),
  205.                   .ResetPC(reset_pc),
  206.                   .ResetSP(reset_sp)
  207.                 );
  208.  
  209.         // now make delayed versions of signals
  210.         //
  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.         //
  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.         //
  257.         //
  258.         // special handling for broken T80 WR_n
  259.         //
  260.         always @(negedge clkz_in)
  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;
  271.                 else
  272.                         #`Z80_DELAY_UP wr_n <= full_wr_n;
  273.  
  274.  
  275.  
  276.  
  277.  
  278.         // ROM model
  279.         rom romko(
  280.                    .addr( {rompg4,rompg3,rompg2,dos_n, (~rompg0_n), za[13:0]} ),
  281.                    .data(zd_dut_to_z80),
  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.  
  306.         defparam dramko1._init_ = 0;
  307.         defparam dramko2._init_ = 0;
  308.  
  309.  
  310.  
  311. `ifndef GATE
  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
  322. //              $display("at time %t us",$time/1000000);
  323.  
  324. //              case( {rma15, rma14} )
  325.  
  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");
  331.  
  332. //              endcase
  333.  
  334. //              $display("");
  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
  345. //              $display("at time %t us",$time/1000000);
  346.  
  347. //              $display("RAM page is %d",rpag);
  348.  
  349. //              $display("");
  350.         end
  351.  
  352.  
  353.  
  354.         // key presses/nmi/whatsoever
  355.         initial
  356.         begin
  357.                 #1;
  358.                 tb.DUT.zkbdmus.kbd = 40'd0;
  359.                 tb.DUT.zkbdmus.kbd[36] = 1'b1;
  360.                 @(negedge int_n);
  361.                 @(negedge int_n);
  362.                 tb.DUT.zkbdmus.kbd[36] = 1'b0;
  363.         end
  364.  
  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;
  385.         else
  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) )
  392.                 begin
  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;
  403.         end
  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. `endif
  426.  
  427.  
  428.  
  429.  
  430.         // turbo
  431. `ifdef C7MHZ
  432.         initial
  433.                 force tb.DUT.zclock.turbo = 2'b01;
  434. `else
  435.         `ifdef C35MHZ
  436.  
  437.                 initial
  438.                         force tb.DUT.zclock.turbo = 2'b00;
  439.  
  440.         `endif
  441. `endif
  442.  
  443.  
  444.         // raster type
  445. `ifdef CCONTEND
  446.         initial
  447.                 force tb.DUT.modes_raster = 2'b10;
  448. `endif
  449.  
  450.  
  451.  
  452.  
  453. `ifdef NMITEST2
  454.  `define M48K
  455.  
  456.         initial
  457.         begin
  458.                 int i,fd;
  459.                 logic [7:0] ldbyte;
  460.  
  461.                 reset_pc=16'h8000;
  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.  
  471.                 i='h8000;
  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);
  482.  
  483.  
  484.                 wait(res===1'b0);
  485.                 #(0.2);
  486.                 tb.DUT.zports.atm_turbo = 1'b1;
  487.                 tb.DUT.zports.peff7_int[4] = 1'b0;
  488.                
  489.                
  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;
  497.         end
  498. `endif
  499.  
  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.  
  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)
  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());  
  559.  
  560.  
  561.  
  562.  
  563.         // start in 48k mode
  564. `ifdef M48K
  565.         initial
  566.         begin : force_48k_mode
  567.  
  568.                 int i;
  569.                 int fd;
  570.        
  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.                
  580.                 wait(res===1'b0);
  581.                 #(0.1);
  582.  
  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.  
  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.  
  609.                 tb.DUT.zports.atm_scr_mode = 3'b011;
  610.                
  611.                 tb.DUT.zports.peff7_int = 8'h14;
  612.                 tb.DUT.zports.p7ffd_int = 8'h30;
  613.  
  614.  
  615.  
  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.  
  672.  
  673.  
  674.  
  675. `ifndef NO_PIXER
  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.         );
  687. `endif
  688.  
  689.  
  690. /*
  691.         // time ticks
  692.         always
  693.         begin : timemark
  694.  
  695.                 integer ms;
  696.  
  697.                 ms = ($time/1000000);
  698.  
  699. //              $display("timemark %d ms",ms);
  700.  
  701.                 #10000000.0; // 1 ms
  702.         end
  703. */
  704.  
  705.  
  706.         // init dram
  707. `ifndef NMITEST2
  708.         initial
  709.         begin : init_dram
  710.                 integer i;
  711.                
  712.                 integer page;
  713.                 integer offset;
  714.                
  715.                 reg [7:0] trd [0:655359];
  716.  
  717.                 integer fd;
  718.                 integer size;
  719.  
  720.  
  721.  
  722.  
  723.                 for(i=0;i<4*1024*1024;i=i+1)
  724.                 begin
  725.                         put_byte(i,(i%257));
  726.                 end
  727.  
  728.                 // load TRD
  729.                 fd = $fopen("boot.trd","rb");
  730.                 size=$fread(trd,fd);
  731.  
  732.                 if( size>655360 || size<=0 )
  733.                 begin
  734.                         $display("Couldn't load or wrong boot.trd!\n");
  735.                         $stop;
  736.                 end
  737.                 $fclose(fd);
  738.  
  739.  
  740.                 // copy TRD to RAM
  741.                 page = 32'h0F4;
  742.                 offset = 0;
  743.  
  744.                 for(i=0;i<size;i=i+1)
  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
  755.                
  756.  
  757.                 $display("boot.trd loaded!\n");
  758.         end
  759. `endif
  760.  
  761.  
  762.  
  763.  
  764.  
  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.  
  794. `ifdef SPITEST
  795.         // spitest printing module
  796.         // does not hurt at any time (yet), so attached forever
  797.  
  798.         spitest_print spitest_print(
  799.                 .sdclk (sdclk ),
  800.                 .sddi  (sddi  ),
  801.                 .sddo  (sddo  ),
  802.                 .sdcs_n(sdcs_n)
  803.         );
  804.  
  805.         // spitest AVR imitator
  806.  
  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;
  815.  
  816.         assign spics_n = 1'b1;
  817.         assign spick   = 1'b0;
  818.         assign spido   = 1'b1;
  819. `endif
  820.  
  821.  
  822.  
  823.  
  824.  
  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. */
  840.  
  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;
  845.  
  846.         typedef enum {FETCH,MRD,MWR,IORD,IOWR,IACK} cycle_t;
  847.  
  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];
  853.  
  854.         wire is_fetch, is_mrd, is_mwr, is_iord, is_iowr, is_iack;
  855.  
  856.         wire is_any;
  857.  
  858.  
  859.  
  860.  
  861.         assign dza = za;
  862.         assign dzw = zd;
  863.         assign dzr = zd_dut_to_z80;
  864.  
  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;
  871.  
  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
  918.                         $display("trd INI caught! port=%04x, wraddr=%04x, time=%t",addrs[1],addrs[0],$time());
  919.                 end
  920.         end
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.         // timestamps
  932.         always
  933.         begin
  934.                 $display("Running for %t ms",$time()/1000000000.0);
  935.                 #1000000.0;
  936.         end
  937.  
  938.  
  939.  
  940.  
  941.  
  942.         // generate nmi after 2s
  943.         initial
  944.         begin
  945.                 #2000000000.0;
  946.  
  947.                 force DUT.set_nmi[0] = 1'b1;
  948.                 #1000000.0;
  949.                 release DUT.set_nmi[0];
  950.         end
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.         task put_byte;
  962.  
  963.                 input [21:0] addr;
  964.                 input [ 7:0] data;
  965.  
  966.  
  967.  
  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.  
  986.         task put_byte_48k
  987.         (
  988.                 input [15:0] addr,
  989.                 input [ 7:0] data
  990.         );
  991.  
  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
  998.  
  999.  
  1000.  
  1001.  
  1002. endmodule
  1003.  
  1004.  
  1005.