Subversion Repositories ngs

Rev

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

  1. // (c) NedoPC 2014
  2. //
  3. // top-level for testing pgmflash
  4.  
  5. `timescale 1ns/1ps
  6.  
  7. `define HALF_24MHZ (20.833)
  8. `define HALF_FPGA  (50.000)
  9.  
  10. `define HALF_ZX (71.428)
  11.  
  12.  
  13. module tb;
  14.  
  15.         reg clk_24mhz;
  16.         reg clk_fpga;
  17.        
  18.         reg clk_zx;
  19.  
  20.  
  21.  
  22.  
  23.  
  24.         wire clksel0;
  25.         wire clksel1;
  26.  
  27.         reg warmres_n;
  28.  
  29.  
  30.         wire [ 7:0] d;
  31.         wire [15:0] a;
  32.  
  33.         wire iorq_n;
  34.         wire mreq_n;
  35.         wire rd_n;
  36.         wire wr_n;
  37.         wire m1_n;
  38.         wire int_n;
  39.         wire nmi_n;
  40.         wire busrq_n;
  41.         reg  busak_n;
  42.         tri1 z80res_n;
  43.  
  44.  
  45.         wire mema14;
  46.         wire mema15;
  47.         wire mema16;
  48.         wire mema17;
  49.         wire mema18;
  50.         wire [3:0] ramcs_n;
  51.         wire mema21;
  52.         wire romcs_n;
  53.         wire memoe_n;
  54.         wire memwe_n;
  55.  
  56.  
  57.         tri1 [7:0] zxid;
  58.         reg  [7:0] zxa;
  59.         tri0 zxa14;
  60.         tri0 zxa15;
  61.         reg  zxiorq_n = 1'b1;
  62.         reg  zxmreq_n = 1'b1;
  63.         reg  zxrd_n   = 1'b1;
  64.         reg  zxwr_n   = 1'b1;
  65.         wire zxcsrom_n;
  66.         wire zxblkiorq_n;
  67.         wire zxblkrom_n;
  68.         wire zxgenwait_n;
  69.         wire zxbusin;
  70.         wire zxbusena_n;
  71.  
  72.  
  73.         wire dac_bitck;
  74.         wire dac_lrck;
  75.         wire dac_dat;
  76.  
  77.  
  78.         wire sd_clk;
  79.         wire sd_cs;
  80.         wire sd_do;
  81.         tri1 sd_di;
  82.         tri1 sd_wp;
  83.         tri1 sd_det;
  84.  
  85.  
  86.         wire ma_clk;
  87.         wire ma_cs;
  88.         wire ma_do;
  89.         tri1 ma_di;
  90.  
  91.         wire mp3_xreset;
  92.         tri1 mp3_req;
  93.         wire mp3_clk;
  94.         wire mp3_dat;
  95.         wire mp3_sync;
  96.  
  97.         wire led;
  98.  
  99.         int autoinc_ena = 0;
  100.  
  101.        
  102.         tri1 [7:0] zxd;
  103.  
  104.         wire [7:0] zxin;
  105.         reg  [7:0] zxout;
  106.         reg        zxena;
  107.  
  108.  
  109.  
  110.         // rom read & write queues
  111.         int wr_queue [$];
  112.         int rd_addr_queue [$];
  113.         int rd_reta_queue [$];
  114.         int rd_retd_queue [$];
  115.  
  116.         int very_first_read = 1;
  117.  
  118.         int rom_addr  = 0;
  119.         int rom_phase = 0;
  120.  
  121.  
  122.         // zx databus
  123.         assign zxin = zxd;
  124.         assign zxd  = zxena ? zxout : 8'bZZZZ_ZZZZ;
  125.  
  126.  
  127.         // 74*245 emulation
  128.         assign zxd  = (!zxbusena_n && !zxbusin) ? zxid : 8'bZZZZ_ZZZZ;
  129.         assign zxid = (!zxbusena_n &&  zxbusin) ? zxd  : 8'bZZZZ_ZZZZ;
  130.  
  131.  
  132.         // busrq/busak logic emulation
  133.         always @(posedge clk_fpga)
  134.         if( !z80res_n )
  135.                 busak_n <= 1'b1;
  136.         else if( !busrq_n )
  137.                 busak_n <= 1'b0;
  138.         else
  139.                 busak_n <= 1'b1;
  140.  
  141.  
  142.  
  143.  
  144.         // clock gen
  145.         initial
  146.         begin
  147.                 clk_24mhz = 1'b1;
  148.                 forever #(`HALF_24MHZ) clk_24mhz = ~clk_24mhz;
  149.         end
  150.         //
  151.         initial
  152.         begin
  153.                 clk_fpga = 1'b1;
  154.                 forever #(`HALF_FPGA) clk_fpga = ~clk_fpga;
  155.         end
  156.         //
  157.         initial
  158.         begin
  159.                 clk_zx = 1'b1;
  160.                 forever #(`HALF_ZX) clk_zx = ~clk_zx;
  161.         end
  162.  
  163.  
  164.  
  165.         initial
  166.         begin
  167.                 warmres_n = 1'b0;
  168.                 #(1);
  169.                 repeat(2) @(posedge clk_fpga);
  170.                 warmres_n <= 1'b1;
  171.         end
  172.  
  173.  
  174.  
  175.         // DUT
  176.         top top
  177.         (
  178.                 .clk_fpga(clk_fpga),
  179.                 .clk_24mhz(clk_24mhz),
  180.                 .clksel0(clksel0),
  181.                 .clksel1(clksel1),
  182.                 .warmres_n(warmres_n),
  183.                 .d(d),
  184.                 .a(a),
  185.                 .iorq_n(iorq_n),
  186.                 .mreq_n(mreq_n),
  187.                 .rd_n(rd_n),
  188.                 .wr_n(wr_n),
  189.                 .m1_n(m1_n),
  190.                 .int_n(int_n),
  191.                 .nmi_n(nmi_n),
  192.                 .busrq_n(busrq_n),
  193.                 .busak_n(busak_n),
  194.                 .z80res_n(z80res_n),
  195.                 .mema14(mema14),
  196.                 .mema15(mema15),
  197.                 .mema16(mema16),
  198.                 .mema17(mema17),
  199.                 .mema18(mema18),
  200.                 .ram0cs_n(ramcs_n[0]),
  201.                 .ram1cs_n(ramcs_n[1]),
  202.                 .ram2cs_n(ramcs_n[2]),
  203.                 .ram3cs_n(ramcs_n[3]),
  204.                 .mema21(mema21),
  205.                 .romcs_n(romcs_n),
  206.                 .memoe_n(memoe_n),
  207.                 .memwe_n(memwe_n),
  208.                 .zxid(zxid),
  209.                 .zxa(zxa),
  210.                 .zxa14(zxa14),
  211.                 .zxa15(zxa15),
  212.                 .zxiorq_n(zxiorq_n),
  213.                 .zxmreq_n(zxmreq_n),
  214.                 .zxrd_n(zxrd_n),
  215.                 .zxwr_n(zxwr_n),
  216.                 .zxcsrom_n(zxcsrom_n),
  217.                 .zxblkiorq_n(zxblkiorq_n),
  218.                 .zxblkrom_n(zxblkrom_n),
  219.                 .zxgenwait_n(zxgenwait_n),
  220.                 .zxbusin(zxbusin),
  221.                 .zxbusena_n(zxbusena_n),
  222.                 .dac_bitck(dac_bitck),
  223.                 .dac_lrck(dac_lrck),
  224.                 .dac_dat(dac_dat),
  225.                 .sd_clk(sd_clk),
  226.                 .sd_cs(sd_cs),
  227.                 .sd_do(sd_do),
  228.                 .sd_di(sd_di),
  229.                 .sd_wp(sd_wp),
  230.                 .sd_det(sd_det),
  231.                 .ma_clk(ma_clk),
  232.                 .ma_cs(ma_cs),
  233.                 .ma_do(ma_do),
  234.                 .ma_di(ma_di),
  235.                 .mp3_xreset(mp3_xreset),
  236.                 .mp3_req(mp3_req),
  237.                 .mp3_clk(mp3_clk),
  238.                 .mp3_dat(mp3_dat),
  239.                 .mp3_sync(mp3_sync),
  240.                 .led_diag(led)
  241.         );
  242.  
  243.  
  244.  
  245.  
  246.         rom_emu rom_emu
  247.         (
  248.                 .a   ({mema18,mema17,mema16,mema15,mema14,a[13:0]}),
  249.                 .d   (d),
  250.                 .ce_n(romcs_n),
  251.                 .oe_n(memoe_n),
  252.                 .we_n(memwe_n)
  253.         );
  254.  
  255.  
  256.         initial
  257.         begin : test_sequence
  258.  
  259.                 reg [7:0] tmp;
  260.                 int i;
  261.  
  262.                 wait(warmres_n==1'b1);
  263.                 repeat(10) @(negedge clk_zx);
  264.  
  265.  
  266.                 // start polling for init_in_progress end.
  267.                 // first we poll floating bus (==ff), then init_in_progress==1, finally it sets to 0.
  268.                 init_wait();
  269.  
  270.                 // make software init
  271.                 iowr(.addr(8'h33),.data(8'h80));
  272.  
  273.                 // wait for end of init_in_progress again
  274.                 init_wait();
  275.  
  276.                 // play with led
  277.                 led_test();
  278.  
  279.                 // "presence check" check
  280.                 presence_check();
  281.  
  282. $display("rom access!");
  283.                 // check rom access
  284.                 rom_check();
  285.  
  286.  
  287.  
  288.                 $display("TESTS PASSED!");
  289.                 $stop;
  290.         end
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.         task init_wait;
  300.  
  301.                 reg [7:0] tmp;
  302.                 int i;
  303.  
  304.                 for(i=0;i<100;i=i+1)
  305.                 begin
  306.                         iord(.addr(8'h33),.data(tmp));
  307.                         if( !(tmp&8'h80) ) disable init_wait;
  308.                 end
  309.  
  310.                 $display("init_wait() failed: too long waiting for init_in_progress going to 0!");
  311.                 $stop;
  312.         endtask
  313.  
  314.        
  315.         task led_test;
  316.                
  317.                 // assume that led_test called after reset or init, so led initial state is known to be 0.
  318.  
  319.                 int i;
  320.                 int led_state;
  321.  
  322.  
  323.  
  324.                 if( led!==1'b0 )
  325.                 begin
  326.                         $display("led is not 0 at the start of led_test!");
  327.                         $stop;
  328.                 end
  329.  
  330.                 // invert led several times and check
  331.                 led_state = 0;
  332.                 for(i=0;i<20;i=i+1)
  333.                 begin
  334.                         iowr(.addr(8'h33),.data(8'h40));
  335.                        
  336.                         led_state = led_state ^ 1;
  337.  
  338.                         if( led!==led_state[0] )
  339.                         begin
  340.                                 $display("led is not inverted properly after write of 0x40 to 0x33 in led_test!");
  341.                                 $stop;
  342.                         end
  343.                 end
  344.         endtask
  345.  
  346.  
  347.         task presence_check;
  348.  
  349.                 // assume we start after init, so test reg contains zeros. so check it first.
  350.  
  351.                 reg [7:0] tmp;
  352.  
  353.                 int i,treg,rnd;
  354.  
  355.  
  356.                 iord(.addr(8'h3B),.data(tmp));
  357.  
  358.                 if( tmp!==8'd0 )
  359.                 begin
  360.                         $display("test reg at first read is not zero!");
  361.                         $stop;
  362.                 end
  363.  
  364.  
  365.                 treg = 0;
  366.  
  367.                 for(i=0;i<256;i=i+1)
  368.                 begin
  369.                         rnd = $random>>24;
  370.  
  371.                         iowr(.addr(8'h3B),.data(rnd[7:0]));
  372.                        
  373.                         iord(.addr(8'h3B),.data(tmp));
  374.  
  375.                         treg[8:0] = { ~rnd[7:0], treg[8] };
  376.  
  377.                         if( treg[7:0]!==tmp[7:0] )
  378.                         begin
  379.                                 $display("test reg at read after write is wrong!");
  380.                                 $stop;
  381.                         end
  382.                 end
  383.  
  384.         endtask
  385.  
  386.  
  387.         task rom_check;
  388.  
  389.                 int addr = 0;
  390.                 int wrdata;
  391.                 int rddata;
  392.                 reg [7:0] tmp;
  393.                 int rnd;
  394.  
  395.                 int read_nwrite;
  396.                 int addr_init_num = (-1);
  397.                 int autoinc;
  398.                 int old_autoinc = 0;
  399.                 int access_num;
  400.  
  401.                 int i;
  402.  
  403.  
  404.                 forever
  405.                 begin
  406.                         // get some random numbers and decide what to do
  407.  
  408.                         read_nwrite = $random>>31;
  409.  
  410.                         if( addr_init_num<0 )
  411.                                 addr_init_num = 3;
  412.                         else
  413.                                 addr_init_num = $random>>30;
  414.  
  415.                         autoinc = $random>>31;
  416.  
  417.                         access_num = 1 + ($random>>28); // 1..16
  418.  
  419.  
  420.                         // start doing that
  421.                         if( autoinc!=old_autoinc )
  422.                         begin
  423.                                 iowr( .addr(8'h33), .data( autoinc ? 8'h20 : 8'h00 ) );
  424.                                 old_autoinc = autoinc;
  425.                         end
  426.  
  427.                         for(i=0;i<addr_init_num;i=i+1)
  428.                         begin
  429.                                 rnd = $random>>24;
  430.  
  431.                                 addr[i*8 +: 8] = rnd[7:0];
  432.                                 iowr( .addr(8'hB3), .data( rnd[7:0] ) );
  433.                         end
  434.                        
  435.                         if( read_nwrite )
  436.                         begin : read
  437.                                 for(i=0;i<access_num;i=i+1)
  438.                                         iord( .addr(8'hBB), .data(tmp) );
  439.                         end
  440.                         else
  441.                         begin : write
  442.                                 for(i=0;i<access_num;i=i+1)
  443.                                         iowr( .addr(8'hBB), .data($random>>24) );
  444.                         end
  445.                 end
  446.  
  447.         endtask
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.         // IO cycles emulator
  458.         task iord;
  459.  
  460.                 input  [7:0] addr;
  461.  
  462.                 output [7:0] data;
  463.  
  464.                 begin
  465.                         if( addr==8'hBB )
  466.                         begin
  467.                                 rom_phase = 0;
  468.  
  469.                                 rd_addr_queue.push_back(rom_addr);
  470.                         end
  471.                        
  472.                         @(posedge clk_zx);
  473.  
  474.                         zxmreq_n <= 1'b1;
  475.                         zxiorq_n <= 1'b1;
  476.                         zxrd_n   <= 1'b1;
  477.                         zxwr_n   <= 1'b1;
  478.  
  479.                         zxena <= 1'b0;
  480.  
  481.                         zxa <= addr;
  482.  
  483.                         @(negedge clk_zx);
  484.  
  485.                         zxiorq_n <= 1'b0;
  486.                         zxrd_n   <= 1'b0;
  487.  
  488.                         @(negedge clk_zx);
  489.                         @(negedge clk_zx);
  490.  
  491.                         data = zxin;
  492.  
  493.                         zxiorq_n <= 1'b1;
  494.                         zxrd_n   <= 1'b1;
  495.  
  496.                         if( addr==8'hBB )
  497.                         begin : check_read_rom
  498.                                 int taddr, tdata;
  499.  
  500.                                 taddr = rd_reta_queue.pop_front();
  501.  
  502.                                 if( taddr[18:0]!==rom_addr[18:0] )
  503.                                 begin
  504.                                         $display("iord: rom addr error!");
  505.                                         $display("iord: addr from queue: %h",taddr[18:0]);
  506.                                         $display("iord: addr from bus:   %h",rom_addr[18:0]);
  507.                                         $stop;
  508.                                 end
  509.  
  510.                                
  511.                                 if( !very_first_read )
  512.                                 begin
  513.                                         tdata = rd_retd_queue.pop_front();
  514.  
  515.                                         if( tdata[7:0]!==data[7:0] )
  516.                                         begin
  517.                                                 $display("iord: rom data error!");
  518.                                                 $display("iord: data from queue: %h",tdata[7:0]);
  519.                                                 $display("iord: data from bus:   %h",data[7:0]);
  520.                                                 $stop;
  521.                                         end
  522.                                 end
  523.                                 else
  524.                                 begin
  525.                                         very_first_read = 0;
  526.                                 end
  527.                                
  528.                                 if( autoinc_ena ) rom_addr++;
  529.                         end
  530.                 end
  531.  
  532.         endtask
  533.         //
  534.         task iowr;
  535.  
  536.                 input [7:0] addr;
  537.                 input [7:0] data;
  538.  
  539.                 begin
  540.  
  541.                         if( addr==8'h33 )
  542.                         begin
  543.                                 autoinc_ena = data[5];
  544.                         end
  545.  
  546.                         if( addr==8'hB3 )
  547.                         begin
  548.                                 rom_addr[rom_phase*8 +: 8] = data[7:0];
  549.                                 rom_phase = (rom_phase>=2) ? 0 : (rom_phase+1);
  550.                         end
  551.                        
  552.                         if( addr==8'hBB || (addr==8'h33 && (data & 8'h80)) )
  553.                         begin
  554.                                 rom_phase = 0;
  555.                         end
  556.  
  557.                         if( addr==8'hBB )
  558.                         begin
  559.                                 wr_queue.push_back((rom_addr<<8)|data[7:0]);
  560.                                 if( autoinc_ena ) rom_addr++;
  561.                         end
  562.  
  563.  
  564.                         @(posedge clk_zx);
  565.  
  566.                         zxmreq_n <= 1'b1;
  567.                         zxiorq_n <= 1'b1;
  568.                         zxrd_n   <= 1'b1;
  569.                         zxwr_n   <= 1'b1;
  570.  
  571.                         zxena <= 1'b1;
  572.  
  573.                         zxa   <= addr;
  574.                         zxout <= data;
  575.  
  576.                         @(negedge clk_zx);
  577.  
  578.                         zxiorq_n <= 1'b0;
  579.                         zxwr_n   <= 1'b0;
  580.  
  581.                         @(negedge clk_zx);
  582.                         @(negedge clk_zx);
  583.  
  584.                         zxiorq_n <= 1'b1;
  585.                         zxwr_n   <= 1'b1;
  586.  
  587.                         wait(zxwr_n==1'b1); // delta-cycle delay!!!
  588.  
  589.                         zxena <= 1'b0;
  590.  
  591.                 end
  592.  
  593.         endtask
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603. endmodule
  604.  
  605.  
  606.  
  607.  
  608.  
  609.  
  610. module rom_emu
  611. (
  612.         input  wire [18:0] a,
  613.         inout  wire [ 7:0] d,
  614.         input  wire        ce_n,
  615.         input  wire        oe_n,
  616.         input  wire        we_n
  617. );
  618.         wire rd_stb = ~(ce_n|oe_n);
  619.         wire wr_stb = ~(ce_n|we_n);
  620.  
  621.         reg old_wr_stb;
  622.  
  623.         wire [7:0] dwr;
  624.         wire [7:0] drd;
  625.  
  626.         reg [7:0]  read_data;
  627.         reg [7:0] write_data;
  628.  
  629.         assign d = rd_stb ? drd : 8'bZZZZ_ZZZZ;
  630.  
  631.         assign dwr = d;
  632.  
  633.  
  634.        
  635.         always @(posedge rd_stb)
  636.         if( rd_stb==1'b1 )
  637.         begin : test_read
  638.  
  639.                 int taddr;
  640.  
  641.                 read_data = $random>>24;
  642.  
  643.                 tb.rd_reta_queue.push_back(a[18:0]);
  644.                 tb.rd_retd_queue.push_back(read_data);
  645.  
  646.                 taddr = tb.rd_addr_queue.pop_front();
  647.  
  648.                 if( taddr[18:0]!==a[18:0] )
  649.                 begin
  650.                         $display("rom_emu: read address error!");
  651.                         $display("rom_emu: addr from queue: %h",taddr[18:0]);
  652.                         $display("rom_emu: addr from bus:   %h",a[18:0]);
  653.                         $stop;
  654.                 end
  655.         end
  656.         //
  657.         assign drd = read_data;
  658.  
  659.  
  660.         always @(wr_stb)
  661.         if( wr_stb==1'b0 && old_wr_stb==1'b1 )
  662.         begin : test_write
  663.  
  664.                 int taddr;
  665.                 int tdata;
  666.                 int tqueue;
  667.  
  668.                 tqueue = tb.wr_queue.pop_front();
  669.  
  670.                 taddr = tqueue>>8;
  671.                 tdata = tqueue&255;
  672.  
  673.                 if( taddr[18:0]!==a[18:0] )
  674.                 begin
  675.                         $display("rom_emu: write address error!");
  676.                         $stop;
  677.                 end
  678.  
  679.                 if( tdata[7:0]!==dwr[7:0] )
  680.                 begin
  681.                         $display("rom_emu: write data error!");
  682.                         $stop;
  683.                 end
  684.  
  685.                 old_wr_stb = wr_stb;
  686.         end
  687.  
  688.  
  689.  
  690.  
  691. endmodule
  692.  
  693.