Subversion Repositories pentevo

Rev

Rev 576 | 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-2012 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. //      wire [15:0] za;
  42. //      wire [ 7:0] zd;
  43.  
  44.         wire [ 7:0] zd_dut_to_z80;
  45. //      wire [ 7:0] zd_z80_to_dut;
  46.  
  47.  
  48.         wire csrom, romoe_n, romwe_n;
  49.         wire rompg0_n, dos_n;
  50.         wire rompg2,rompg3,rompg4;
  51.  
  52.         wire [15:0] rd;
  53.         wire [9:0] ra;
  54.         wire rwe_n,rucas_n,rlcas_n,rras0_n,rras1_n;
  55.  
  56.  
  57.         tri1 [15:0] ide_d;
  58.  
  59.  
  60.         wire hsync,vsync;
  61.         wire [1:0] red,grn,blu;
  62.  
  63.  
  64.  
  65.         // sdcard
  66.         wire sdcs_n, sddo, sddi, sdclk;
  67.  
  68.         // avr
  69.         wire spick, spidi, spido, spics_n;
  70.  
  71.  
  72.  
  73.  
  74.         assign zwait_n = (wait_n==1'b0) ? 1'b0 : 1'b1;
  75.         assign znmi_n = (nmi_n==1'b0) ? 1'b0 : 1'b1;
  76.         assign zint_n = (int_n==1'b0) ? 1'b0 : 1'b1;
  77.  
  78.  
  79.  
  80.  
  81.  
  82.  
  83.         initial
  84.         begin
  85.  
  86.                 fclk = 1'b0;
  87.  
  88.                 forever #`HALF_CLK_PERIOD fclk = ~fclk;
  89.         end
  90.  
  91.  
  92.         assign #`ZCLK_DELAY clkz_in = ~clkz_out;
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.         top DUT( .fclk(fclk),
  101.                  .clkz_out(clkz_out),
  102.                  .clkz_in(clkz_in),
  103.  
  104.                // z80
  105.                  .iorq_n(iorq_n),
  106.                  .mreq_n(mreq_n),
  107.                  .rd_n(rd_n),
  108.                  .wr_n(wr_n),
  109.                  .m1_n(m1_n),
  110.                  .rfsh_n(rfsh_n),
  111.                  .int_n(int_n),
  112.                  .nmi_n(nmi_n),
  113.                  .wait_n(wait_n),
  114.                  .res(res),
  115.                  //
  116.                  .d(zd),
  117.                  .a(za),
  118.  
  119.                  // ROM
  120.                  .csrom(csrom),
  121.                  .romoe_n(romoe_n),
  122.                  .romwe_n(romwe_n),
  123.                  .rompg0_n(rompg0_n),
  124.                  .dos_n(dos_n),
  125.                  .rompg2(rompg2),
  126.                  .rompg3(rompg3),
  127.                  .rompg4(rompg4),
  128.  
  129.                  // DRAM
  130.                  .rd(rd),
  131.                  .ra(ra),
  132.                  .rwe_n(rwe_n),
  133.                  .rucas_n(rucas_n),
  134.                  .rlcas_n(rlcas_n),
  135.                  .rras0_n(rras0_n),
  136.                  .rras1_n(rras1_n),
  137.  
  138.                  // ZX-bus
  139.                  .iorqge1(1'b0),
  140.                  .iorqge2(1'b0),
  141.  
  142.                  // IDE
  143.                  .ide_d(ide_d),
  144.                  .ide_rdy(1'b1),
  145.  
  146.                  // VG93
  147.                  .step(1'b0),
  148.                  .vg_sl(1'b0),
  149.                  .vg_sr(1'b0),
  150.                  .vg_tr43(1'b0),
  151.                  .rdat_b_n(1'b1),
  152.                  .vg_wf_de(1'b0),
  153.                  .vg_drq(1'b1),
  154.                  .vg_irq(1'b1),
  155.                  .vg_wd(1'b0),
  156.  
  157.                  // SDcard SPI
  158.                  .sddi(sddi),
  159.                  .sddo(sddo),
  160.                  .sdcs_n(sdcs_n),
  161.                  .sdclk(sdclk),
  162.  
  163.                  // ATmega SPI
  164.                  .spics_n(spics_n),
  165.                  .spick(spick),
  166.                  .spido(spido),
  167.                  .spidi(spidi),
  168.  
  169.                  .vhsync(hsync),
  170.                  .vvsync(vsync),
  171.                  .vred(red),
  172.                  .vgrn(grn),
  173.                  .vblu(blu)
  174.  
  175.                );
  176.  
  177.  
  178.  
  179.  
  180.         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 ) );
  181.  
  182.  
  183.  
  184.  
  185.  
  186.         wire zrst_n = ~res;
  187.  
  188.         T80a z80( .RESET_n(zrst_n),
  189.                   .CLK_n(clkz_in),
  190.                   .WAIT_n(zwait_n),
  191.                   .INT_n(zint_n),
  192.                   .NMI_n(znmi_n),
  193.                   .M1_n(zm1_n),
  194.                   .RFSH_n(zrfsh_n),
  195.                   .MREQ_n(zmreq_n),
  196.                   .IORQ_n(ziorq_n),
  197.                   .RD_n(zrd_n),
  198.                   .WR_n(zwr_n),
  199.                   .BUSRQ_n(1'b1),
  200.                   .A(za),
  201. //                .D(zd),
  202.                   .D_I(zd_dut_to_z80),
  203.                   .D_O(zd)
  204.                 );
  205.  
  206.         // now make delayed versions of signals
  207.         //
  208.         reg  mreq_wr_n;
  209.         wire iorq_wr_n, full_wr_n;
  210.         //
  211.         // first, assure there is no X's at the start
  212.         //
  213.         initial
  214.         begin
  215.                 m1_n      = 1'b1;
  216.                 rfsh_n    = 1'b1;
  217.                 mreq_n    = 1'b1;
  218.                 iorq_n    = 1'b1;
  219.                 rd_n      = 1'b1;
  220.                 wr_n      = 1'b1;
  221.                 mreq_wr_n = 1'b1;
  222.         end
  223.         //
  224.         always @(zm1_n)
  225.                 if( zm1_n )
  226.                         m1_n <= #`Z80_DELAY_UP zm1_n;
  227.                 else
  228.                         m1_n <= #`Z80_DELAY_DOWN zm1_n;
  229.         //
  230.         always @(zrfsh_n)
  231.                 if( zrfsh_n )
  232.                         rfsh_n <= #`Z80_DELAY_UP zrfsh_n;
  233.                 else
  234.                         rfsh_n <= #`Z80_DELAY_DOWN zrfsh_n;
  235.         //
  236.         always @(zmreq_n)
  237.                 if( zmreq_n )
  238.                         mreq_n <= #`Z80_DELAY_UP zmreq_n;
  239.                 else
  240.                         mreq_n <= #`Z80_DELAY_DOWN zmreq_n;
  241.         //
  242.         always @(ziorq_n)
  243.                 if( ziorq_n )
  244.                         iorq_n <= #`Z80_DELAY_UP ziorq_n;
  245.                 else
  246.                         iorq_n <= #`Z80_DELAY_DOWN ziorq_n;
  247.         //
  248.         always @(zrd_n)
  249.                 if( zrd_n )
  250.                         rd_n <= #`Z80_DELAY_UP zrd_n;
  251.                 else
  252.                         rd_n <= #`Z80_DELAY_DOWN zrd_n;
  253.         //
  254.         //
  255.         // special handling for broken T80 WR_n
  256.         //
  257.         always @(negedge clkz_in)
  258.                 mreq_wr_n <= zwr_n;
  259.         //
  260.         assign iorq_wr_n = ziorq_n | (~zrd_n) | (~zm1_n);
  261.         //
  262.         assign full_wr_n = mreq_wr_n & iorq_wr_n;
  263.         //
  264.         // this way glitches won't affect state of wr_n
  265.         always @(full_wr_n)
  266.                 if( !full_wr_n )
  267.                         #`Z80_DELAY_DOWN wr_n <= full_wr_n;
  268.                 else
  269.                         #`Z80_DELAY_UP wr_n <= full_wr_n;
  270.  
  271.  
  272.  
  273.  
  274.  
  275.         // ROM model
  276.         rom romko(
  277.                    .addr( {rompg4,rompg3,rompg2,dos_n, (~rompg0_n), za[13:0]} ),
  278.                    .data(zd_dut_to_z80),
  279.                    .ce_n( romoe_n | (~csrom) )
  280.                  );
  281.  
  282.         // DRAM model
  283.         drammem dramko1(
  284.                          .ma(ra),
  285.                          .d(rd),
  286.                          .ras_n(rras0_n),
  287.                          .ucas_n(rucas_n),
  288.                          .lcas_n(rlcas_n),
  289.                          .we_n(rwe_n)
  290.                        );
  291.         //
  292.         drammem dramko2(
  293.                          .ma(ra),
  294.                          .d(rd),
  295.                          .ras_n(rras1_n),
  296.                          .ucas_n(rucas_n),
  297.                          .lcas_n(rlcas_n),
  298.                          .we_n(rwe_n)
  299.                        );
  300.         defparam dramko1._verbose_ = 0;
  301.         defparam dramko2._verbose_ = 0;
  302.  
  303.         defparam dramko1._init_ = 0;
  304.         defparam dramko2._init_ = 0;
  305.  
  306.  
  307.  
  308. `ifndef GATE
  309.  
  310.         // trace rom page
  311.         wire rma14,rma15;
  312.  
  313.         assign rma14 = DUT.page[0][0];
  314.         assign rma15 = DUT.page[0][1];
  315.  
  316.  
  317.         always @(rma14 or rma15)
  318.         begin
  319. //              $display("at time %t us",$time/1000000);
  320.  
  321. //              case( {rma15, rma14} )
  322.  
  323. //              2'b00: $display("BASIC 48");
  324. //              2'b01: $display("TR-DOS");
  325. //              2'b10: $display("BASIC 128");
  326. //              2'b11: $display("GLUKROM");
  327. //              default: $display("unknown");
  328.  
  329. //              endcase
  330.  
  331. //              $display("");
  332.         end
  333.  
  334.  
  335.         // trace ram page
  336.         wire [5:0] rpag;
  337.  
  338.         assign rpag=DUT.page[3][5:0];
  339.  
  340.         always @(rpag)
  341.         begin
  342. //              $display("at time %t us",$time/1000000);
  343.  
  344. //              $display("RAM page is %d",rpag);
  345.  
  346. //              $display("");
  347.         end
  348.  
  349.  
  350.  
  351.         // key presses/nmi/whatsoever
  352.         initial
  353.         begin
  354.                 #1;
  355.                 tb.DUT.zkbdmus.kbd = 40'd0;
  356.                 tb.DUT.zkbdmus.kbd[36] = 1'b1;
  357.                 @(negedge int_n);
  358.                 @(negedge int_n);
  359.                 tb.DUT.zkbdmus.kbd[36] = 1'b0;
  360.         end
  361. /*
  362.         initial
  363.         begin : gen_nmi
  364.  
  365.                 reg [21:0] a;
  366.  
  367.                 #1000000000;
  368.  
  369.                 a = 22'h3FC066;
  370.  
  371.                 put_byte(a,8'hF5); a=a+1;
  372.                 put_byte(a,8'hC5); a=a+1;
  373.                 put_byte(a,8'hD5); a=a+1;
  374.                 put_byte(a,8'hE5); a=a+1;
  375.  
  376.                 put_byte(a,8'h10); a=a+1;
  377.                 put_byte(a,8'hFE); a=a+1;
  378.  
  379.                 put_byte(a,8'h14); a=a+1;
  380.  
  381.                 put_byte(a,8'h01); a=a+1;
  382.                 put_byte(a,8'hFE); a=a+1;
  383.                 put_byte(a,8'h7F); a=a+1;
  384.  
  385.                 put_byte(a,8'hED); a=a+1;
  386.                 put_byte(a,8'h51); a=a+1;
  387.  
  388.                 put_byte(a,8'hED); a=a+1;
  389.                 put_byte(a,8'h78); a=a+1;
  390.  
  391.                 put_byte(a,8'h1F); a=a+1;
  392.  
  393.                 put_byte(a,8'hDA); a=a+1;
  394.                 put_byte(a,8'h6A); a=a+1;
  395.                 put_byte(a,8'h00); a=a+1;
  396.  
  397.                 put_byte(a,8'hE1); a=a+1;
  398.                 put_byte(a,8'hD1); a=a+1;
  399.                 put_byte(a,8'hC1); a=a+1;
  400.                 put_byte(a,8'hF1); a=a+1;
  401.  
  402.                 put_byte(a,8'hD3); a=a+1;
  403.                 put_byte(a,8'hBE); a=a+1;
  404.  
  405.                 put_byte(a,8'hED); a=a+1;
  406.                 put_byte(a,8'h45); a=a+1;
  407.  
  408.  
  409.                 @(posedge fclk);
  410.                 tb.DUT.slavespi.cfg0_reg_out[1] = 1'b1;
  411.                 @(posedge fclk);
  412.                 tb.DUT.slavespi.cfg0_reg_out[1] = 1'b0;
  413.  
  414.                 #64000000;
  415.  
  416.                 tb.DUT.zkbdmus.kbd[39] = 1'b1;
  417.                 @(negedge int_n);
  418.                 tb.DUT.zkbdmus.kbd[39] = 1'b0;
  419.         end
  420. */
  421.  
  422. `endif
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431. `ifdef ZLOG
  432.         reg [ 7:0] old_opcode;
  433.         reg [15:0] old_opcode_addr;
  434.  
  435.         wire [7:0] zdd = zd_dut_to_z80;
  436.  
  437.         reg was_m1;
  438.  
  439.         always @(zm1_n)
  440.         if( zm1_n )
  441.                 was_m1 <= 1'b0;
  442.         else
  443.                 was_m1 = 1'b1;
  444.  
  445.         always @(posedge (zmreq_n | zrd_n | zm1_n | (~zrfsh_n)) )
  446.         if( was_m1 )
  447.         begin
  448.                 if( (zdd!==old_opcode) || (za!==old_opcode_addr) )
  449.                 begin
  450.                         if( tb.DUT.z80mem.romnram )
  451. //                              $display("Z80OPROM: addr %x, opcode %x, time %t",za,zdd,$time);
  452.                                 $display("Z80OPROM: addr %x, opcode %x",za,zdd);
  453.                         else
  454. //                              $display("Z80OPRAM: addr %x, opcode %x, time %t",za,zdd,$time);
  455.                                 $display("Z80OPRAM: addr %x, opcode %x",za,zdd);
  456.                 end
  457.  
  458.                 old_opcode      = zdd;
  459.                 old_opcode_addr = za;
  460.         end
  461.  
  462.         always @(posedge (zmreq_n | zrd_n | (~zm1_n) | (~zrfsh_n)) )
  463.         if( !was_m1 )
  464.         begin
  465.                 if( tb.DUT.z80mem.romnram )
  466. //                      $display("Z80RDROM: addr %x, rddata %x, time %t",za,zdd,$time);
  467.                         $display("Z80RDROM: addr %x, rddata %x",za,zdd);
  468.                 else
  469. //                      $display("Z80RDRAM: addr %x, rddata %x, time %t",za,zdd,$time);
  470.                         $display("Z80RDRAM: addr %x, rddata %x",za,zdd);
  471.         end
  472.  
  473.         always @(posedge (zmreq_n | zwr_n | (~zm1_n) | (~zrfsh_n)) )
  474.         begin
  475.                 if( tb.DUT.z80mem.romnram )
  476. //                      $display("Z80WRROM: addr %x, wrdata %x, time %t",za,zd,$time);
  477.                         $display("Z80WRROM: addr %x, wrdata %x",za,zd);
  478.                 else
  479. //                      $display("Z80WRRAM: addr %x, wrdata %x, time %t",za,zd,$time);
  480.                         $display("Z80WRRAM: addr %x, wrdata %x",za,zd);
  481.         end
  482. `endif
  483.  
  484.  
  485.  
  486.  
  487.         // turbo
  488. `ifdef C7MHZ
  489.         initial
  490.                 force tb.DUT.zclock.turbo = 2'b01;
  491. `else
  492.         `ifdef C35MHZ
  493.  
  494.                 initial
  495.                         force tb.DUT.zclock.turbo = 2'b00;
  496.  
  497.         `endif
  498. `endif
  499.  
  500.  
  501.  
  502.  
  503.  
  504.         // force fetch mode
  505. //      initial
  506. //      begin
  507. //              force tb.DUT.dramarb.bw = 2'b11;
  508. //
  509. //              #(64'd2400000000);
  510. //
  511. //              release tb.DUT.dramarb.bw;
  512. //      end
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521. `ifndef NO_PIXER
  522.         // picture out
  523.         pixer pixer
  524.         (
  525.                 .clk(fclk),
  526.  
  527.                 .vsync(vsync),
  528.                 .hsync(hsync),
  529.                 .red(red),
  530.                 .grn(grn),
  531.                 .blu(blu)
  532.         );
  533. `endif
  534.  
  535.  
  536. /*
  537.         // time ticks
  538.         always
  539.         begin : timemark
  540.  
  541.                 integer ms;
  542.  
  543.                 ms = ($time/1000000);
  544.  
  545. //              $display("timemark %d ms",ms);
  546.  
  547.                 #10000000.0; // 1 ms
  548.         end
  549. */
  550.  
  551.  
  552.  
  553.  
  554.         // init dram
  555.         initial
  556.         begin : init_dram
  557.                 integer i;
  558.  
  559.                 for(i=0;i<4*1024*1024;i=i+1)
  560.                 begin
  561.                         put_byte(i,(i%257));
  562.                 end
  563.         end
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570. `ifdef SPITEST
  571.         // spitest printing module
  572.         // does not hurt at any time (yet), so attached forever
  573.  
  574.         spitest_print spitest_print(
  575.                 .sdclk (sdclk ),
  576.                 .sddi  (sddi  ),
  577.                 .sddo  (sddo  ),
  578.                 .sdcs_n(sdcs_n)
  579.         );
  580.  
  581.         // spitest AVR imitator
  582.  
  583.         spitest_avr spitest_avr(
  584.                 .spick  (spick  ),
  585.                 .spics_n(spics_n),
  586.                 .spido  (spido  ),
  587.                 .spidi  (spidi  )
  588.         );
  589. `else
  590.         assign sddi = 1'b1;
  591.  
  592.         assign spics_n = 1'b1;
  593.         assign spick   = 1'b0;
  594.         assign spido   = 1'b1;
  595. `endif
  596.  
  597.  
  598.  
  599.  
  600.  
  601.         // set up breakpoint
  602.         initial
  603.         begin
  604.                 #(650_000_000); // wait 650ms = 650*1000*1000 ns
  605.  
  606.                 @(posedge fclk);
  607.  
  608.                 tb.DUT.zports.brk_ena  = 1'b1;
  609.                 tb.DUT.zports.brk_addr = 16'h0041;
  610.         end
  611.  
  612.  
  613.  
  614.  
  615.  
  616.  
  617.  
  618.  
  619.  
  620.  
  621.  
  622.         task put_byte;
  623.  
  624.                 input [21:0] addr;
  625.                 input [ 7:0] data;
  626.  
  627.  
  628.  
  629.                 reg [19:0] arraddr;
  630.  
  631.                 begin
  632.  
  633.                         arraddr = { addr[21:12], addr[11:2] };
  634.  
  635.                         case( addr[1:0] ) // chipsel, bytesel
  636.  
  637.                         2'b00: tb.dramko1.array[arraddr][15:8] = data;
  638.                         2'b01: tb.dramko1.array[arraddr][ 7:0] = data;
  639.                         2'b10: tb.dramko2.array[arraddr][15:8] = data;
  640.                         2'b11: tb.dramko2.array[arraddr][ 7:0] = data;
  641.  
  642.                         endcase
  643.                 end
  644.  
  645.         endtask
  646.  
  647.  
  648.  
  649.  
  650.  
  651. endmodule
  652.  
  653.  
  654.