Subversion Repositories zxusbnet

Rev

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

  1. // ZXiznet project
  2. // (c) NedoPC 2018
  3. //
  4. // testbench
  5.  
  6.  
  7. `timescale 1ns/100ps
  8.  
  9. //// CPU at 14 or 28MHz
  10. `ifdef CPU28MHZ
  11.  `define HALF_CPU_PERIOD (17.8)
  12. `else
  13.  `define HALF_CPU_PERIOD (35.7)
  14. `endif
  15.  
  16.  
  17. // CPU at 7MHz
  18. //`define HALF_CPU_PERIOD (70)
  19.  
  20. // filter clock
  21. `define HALF_FCLK_PERIOD (10.4)
  22.  
  23. module tb;
  24.  
  25.         reg rst_n;
  26.         reg clk;
  27.  
  28.         reg fclk;
  29.  
  30.  
  31.         tri1 iorq_n,
  32.              mreq_n,
  33.              rd_n,
  34.              wr_n;
  35.  
  36.         tri1 int_n;
  37.  
  38.         wire csrom_n;
  39.  
  40.         wire iorqge,
  41.              blkrom;
  42.        
  43.  
  44.         wire [15:0] a;
  45.         wire [ 7:0] d;
  46.  
  47.         tri  [ 7:0] #1 bd;
  48.  
  49.         wire brd_n, bwr_n;
  50.  
  51.  
  52.         reg [7:0] tmp;
  53.  
  54.  
  55.  
  56.  
  57.         wire [9:0] w5300_addr;
  58.         wire       w5300_rst_n;
  59.         wire       w5300_cs_n;
  60.         wire       w5300_int_n;
  61.  
  62.         wire       sl811_rst_n;
  63.         wire       sl811_a0;
  64.         wire       sl811_cs_n;
  65.         wire       sl811_ms_n;
  66.         wire       sl811_intrq;
  67.  
  68.        
  69.        
  70.         reg usb_power;
  71.  
  72.  
  73.         reg [1:0] where_rom;
  74.  
  75.  
  76.  
  77.  
  78.         // filter clock
  79.         initial
  80.         begin
  81.                 fclk = 1'b1;
  82.  
  83.                 forever #`HALF_FCLK_PERIOD fclk = ~fclk;
  84.         end
  85.  
  86.  
  87.         initial
  88.         begin
  89.                 clk = 1'b1;
  90.  
  91.                 forever #`HALF_CPU_PERIOD clk = ~clk;
  92.         end
  93.  
  94.  
  95.         initial
  96.         begin
  97.                 rst_n = 1'b0;
  98.  
  99.                 repeat(3) @(posedge clk);
  100.  
  101.                 rst_n <= 1'b1;
  102.         end
  103.  
  104.  
  105.  
  106.         initial
  107.         begin
  108.                 where_rom = 2'b00;
  109.  
  110.                 usb_power = 1'b0;
  111.         end
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.         top DUT
  121.         (
  122.                 .fclk(fclk),
  123.  
  124.                 .za(a),
  125.                 .zd(d),
  126.  
  127.                 .ziorq_n(iorq_n),
  128.                 .zmreq_n(mreq_n),
  129.                 .zrd_n(rd_n),
  130.                 .zwr_n(wr_n),
  131.  
  132.                 .zcsrom_n(csrom_n),
  133.                
  134.                 .ziorqge(iorqge),
  135.                 .zblkrom(blkrom),
  136.  
  137.                 .zrst_n(rst_n),
  138.                 .zint_n(int_n),
  139.  
  140.                 .bd(bd),
  141.  
  142.                 .bwr_n(bwr_n),
  143.                 .brd_n(brd_n),
  144.  
  145.  
  146.                 .w5300_rst_n(w5300_rst_n),
  147.                 .w5300_addr (w5300_addr ),
  148.                 .w5300_cs_n (w5300_cs_n ),
  149.                 .w5300_int_n(w5300_int_n),
  150.                
  151.                 .sl811_rst_n(sl811_rst_n),
  152.                 .sl811_intrq(sl811_intrq),
  153.                 .sl811_ms_n (sl811_ms_n ),
  154.                 .sl811_cs_n (sl811_cs_n ),
  155.                 .sl811_a0   (sl811_a0   ),
  156.  
  157.                 .usb_power(usb_power)
  158.  
  159.         );
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.         ssz80 z
  173.         (
  174.                 .clk  (clk  ),
  175.                 .rst_n(rst_n),
  176.  
  177.                 .iorq_n(iorq_n),
  178.                 .mreq_n(mreq_n),
  179.                 .rd_n  (rd_n  ),
  180.                 .wr_n  (wr_n  ),
  181.  
  182.                 .a(a),
  183.                 .d(d)
  184.         );
  185.  
  186.  
  187.  
  188.  
  189.  
  190.         w5300 w
  191.         (
  192.                 .rst_n(w5300_rst_n),
  193.                 .addr (w5300_addr ),
  194.                 .cs_n (w5300_cs_n ),
  195.                 .rd_n (brd_n      ),
  196.                 .wr_n (bwr_n      ),
  197.                 .int_n(w5300_int_n),
  198.                 .d(bd)
  199.         );
  200.  
  201.  
  202.         sl811 s
  203.         (
  204.                 .rst_n(sl811_rst_n),
  205.                 .a0   (sl811_a0   ),
  206.                 .cs_n (sl811_cs_n ),
  207.                 .wr_n (bwr_n      ),
  208.                 .rd_n (brd_n      ),
  209.                 .ms   (~sl811_ms_n),
  210.                 .intrq(sl811_intrq),
  211.                 .d(bd)
  212.         );
  213.  
  214.  
  215.         // csrom gen
  216.         assign csrom_n = !(a[15:14]==where_rom[1:0]);
  217.  
  218.        
  219.        
  220.        
  221.        
  222.        
  223. ////////////////////////////////////////////////////////////////////////////////       
  224. ////////////////////////////////////////////////////////////////////////////////       
  225. ////////////////////////////////////////////////////////////////////////////////       
  226. /// here start tests
  227.  
  228.         reg [15:0] rstint_port = 16'h83_AB;
  229. //      reg [15:0] w5300_port  = 16'h82_AB;
  230. //      reg [15:0] sl811_port  = 16'h81_AB;
  231.         reg [15:0] cfg_port    = 16'h82_AB;
  232.         reg [15:0] wiomap_port = 16'h81_AB;
  233.         reg [15:0] sl_addr     = 16'h80_AB;
  234.         reg [15:0] sl_data     = 16'h7F_AB;
  235.        
  236.         initial
  237.         begin : tests
  238.        
  239.        
  240.                 reg [7:0] tmp;
  241.                 reg [7:0] tmp2;
  242.  
  243.                
  244.                 wait(rst_n===1'b1);
  245.  
  246.                 repeat(10) @(posedge clk);
  247.        
  248.        
  249.  
  250.                 test_pwon_resets();
  251.                 test_pwon_ints();
  252.  
  253.  
  254.  
  255.                 forever // repeat(10000)
  256.                 begin
  257.                         case( $random%6 )
  258.                         0: check_sl811_access();
  259. //`ifndef CPU28MHZ
  260. //                      1: check_w5300_mem_access();
  261. //`endif
  262.                         2: check_w5300_port_access();
  263.                         3: test_resets();
  264.                         4: check_sl811_port();
  265.                         5: test_ints();
  266.                         endcase
  267.                 end
  268.  
  269.                
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.                
  279.  
  280.  
  281.  
  282.  
  283.                
  284.                
  285.                 $display("all tests passed!");
  286.                 $stop;
  287.         end
  288.  
  289.        
  290.        
  291.  
  292.        
  293.        
  294.         task wait_end_access();
  295.  
  296.                 reg a;
  297.  
  298.                 a = 1'b0;
  299.                 wait( brd_n==1'b1 && bwr_n==1'b1 );
  300.  
  301.                 a <= 1'b1;
  302.                 wait(a==1'b1);
  303.  
  304.         endtask
  305.        
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.         // translates memory address to w5300 address in accordance with specs
  314.         function [9:0] mk_w5300_addr( input [13:0] mem_addr );
  315.  
  316.                 if( mem_addr<14'h2000 )
  317.                 begin
  318.                         mk_w5300_addr = mem_addr[9:0];
  319.                 end
  320.                 else if( mem_addr<14'h3000 )
  321.                 begin
  322.                         mk_w5300_addr[9] = 1'b1;
  323.                         mk_w5300_addr[8:6] = mem_addr[11:9];
  324.                         mk_w5300_addr[5:1] = 5'b10111;
  325.                         mk_w5300_addr[0] = mem_addr[0];
  326.                 end
  327.                 else // if( mem_addr<14'h4000 )
  328.                 begin
  329.                         mk_w5300_addr[9] = 1'b1;
  330.                         mk_w5300_addr[8:6] = mem_addr[11:9];
  331.                         mk_w5300_addr[5:1] = 5'b11000;
  332.                         mk_w5300_addr[0] = mem_addr[0];
  333.                 end
  334.  
  335.         endfunction
  336.  
  337.  
  338.  
  339.  
  340.  
  341.  
  342.         task check_w5300_port_access();
  343.  
  344.                 reg [7:0] tmp,rddata,wrdata;
  345.                 reg [9:0] waddr;
  346.                 reg       a0_inv;
  347.  
  348.                 reg [15:0] port;
  349.  
  350.  
  351.                 a0_inv = $random>>31;
  352.  
  353.                 waddr = $random>>22;
  354.  
  355.  
  356.  
  357.                 z.iowr(cfg_port,{3'd0,1'b1,a0_inv,3'd0});
  358.  
  359.                 z.iord(cfg_port,tmp);
  360.                 if( tmp[4:0]!=={1'b1,a0_inv,3'd0} )
  361.                 begin
  362.                         $display("can't set w5300 port!");
  363.                         $stop;
  364.                 end
  365.                
  366.  
  367.                 z.iowr(wiomap_port,waddr[9:6]);
  368.                 z.iord(wiomap_port,tmp);
  369.                 if( tmp[3:0]!==waddr[9:6] )
  370.                 begin
  371.                         $display("can't set wiomap port!");
  372.                         $stop;
  373.                 end
  374.  
  375.  
  376.  
  377.                 // make access port address
  378.                 port = sl_data;
  379.                 port[13:8] = waddr[5:0];
  380.  
  381.  
  382.                 w.init_access(); // clear access_* to X
  383.  
  384.  
  385.                 if( $random>>31 )
  386.                 begin
  387.                         wrdata = $random>>24;
  388.                         z.iowr(port,wrdata);
  389.                         wait_end_access();
  390.                         if( w.get_addr()!==(waddr^a0_inv) ||
  391.                             w.get_rnw()!==1'b0            ||
  392.                             w.get_wr_data()!==wrdata      )
  393.                         begin
  394.                                 $display("w5300 port write failed!");
  395.                                 $stop;
  396.                         end
  397.                 end
  398.                 else
  399.                 begin
  400.                         rddata = $random>>24;
  401.                         w.set_rd_data(rddata);
  402.                         z.iord(port,tmp);
  403. `ifdef CPU28MHZ
  404.                         wait_end_access();
  405. `else
  406.                         @(negedge clk);
  407. `endif
  408.                         if( w.get_addr()!==(waddr^a0_inv) ||
  409.                             w.get_rnw()!==1'b1            ||
  410.                             tmp!==rddata                  )
  411.                         begin
  412.                                 $display("w5300 port read failed!");
  413.                                 $stop;
  414.                         end
  415.                 end
  416.  
  417.         endtask
  418.  
  419.  
  420.  
  421.  
  422.         task check_w5300_mem_access;
  423.  
  424.                 reg [7:0] tmp,rddata,wrdata;
  425.                 reg [15:0] memaddr;
  426.                 reg [ 9:0] waddr;
  427.  
  428.                 reg [1:0] rom;
  429.                 reg       a0_inv;
  430.                 reg       sub_ena;
  431.  
  432.  
  433.                 rom    = $random>>30;
  434.                 a0_inv = $random>>31;
  435.                 sub_ena= $random>>31;
  436.  
  437.                 z.iowr(cfg_port,{4'd0,a0_inv,sub_ena,rom});
  438.  
  439.                 z.iord(cfg_port,tmp);
  440.                 if( tmp[4:0]!=={1'd0,a0_inv,sub_ena,rom} )
  441.                 begin
  442.                         $display("can't set w5300 port!");
  443.                         $stop;
  444.                 end
  445.  
  446.  
  447.                 if( $random>>31 )
  448.                         where_rom = rom;
  449.                 else
  450.                 begin
  451.                         where_rom = $random>>30;
  452.                         while( where_rom==rom )
  453.                                 where_rom = $random>>30;
  454.                 end
  455.  
  456.  
  457.  
  458.                 w.init_access(); // clear access_* to X
  459.  
  460.  
  461.                 memaddr = $random>>18;
  462.                 memaddr[15:14] = where_rom;
  463.  
  464.  
  465.  
  466.                 if( $random>>31 )
  467.                 begin
  468.                         repeat(10)
  469.                         begin
  470.                                 wrdata = $random>>24;
  471.                                 z.memwr(memaddr,wrdata);
  472.                                 wait_end_access();
  473.                                 if( where_rom==rom && sub_ena )
  474.                                 begin
  475.                                         if( w.get_addr()!==(mk_w5300_addr(memaddr[13:0])^a0_inv) ||
  476.                                             w.get_rnw()!==1'b0                                   ||
  477.                                             w.get_wr_data()!==wrdata                             )
  478.                                         begin
  479.                                                 $display("w5300 write failed!");
  480.                                                 $stop;
  481.                                         end
  482.                                 end
  483.                                 else
  484.                                 begin
  485.                                         if( w.get_addr()!=={10{1'bX}} || w.get_rnw()!==1'bX || w.get_wr_data()!=={8{1'bX}} )
  486.                                         begin
  487.                                                 $display("write succeeded with wrong ROM mapping!");
  488.                                                 $stop;
  489.                                         end
  490.                                 end
  491.                         end
  492.                 end
  493.                 else
  494.                 begin
  495.                         rddata = $random>>24;
  496.                         w.set_rd_data(rddata);
  497.                         z.memrd(memaddr,tmp);
  498.                         @(negedge clk);
  499.                         if( where_rom==rom && sub_ena )
  500.                         begin
  501.                                 if( w.get_addr()!==(mk_w5300_addr(memaddr[13:0])^a0_inv) ||
  502.                                     w.get_rnw()!==1'b1                                   ||
  503.                                     tmp!==rddata                                         )
  504.                                 begin
  505.                                         $display("w5300 read failed!");
  506.                                         $stop;
  507.                                 end
  508.                         end
  509.                         else
  510.                         begin
  511.                                 if( w.get_addr()!=={10{1'bX}} || w.get_rnw()!==1'bX )
  512.                                 begin
  513.                                         $display("read succeeded with wrong ROM mapping!");
  514.                                         $stop;
  515.                                 end
  516.                         end
  517.                 end
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.         endtask
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.  
  539.         task check_sl811_access;
  540.  
  541.                 reg [7:0] tmp, rddata, wrdata;
  542.  
  543.                 reg [15:0] rdport;
  544.  
  545.  
  546.                 // turn off w5300 port access
  547.                 z.iord(cfg_port,tmp);
  548.                 if( tmp[4]!==1'b0 )
  549.                 begin
  550.                         tmp[4]=1'b0;
  551.                         z.iowr(cfg_port,tmp);
  552.                 end
  553.  
  554.  
  555.                 // check address reg
  556.                 wrdata=$random>>24;
  557.                 z.iowr(sl_addr,wrdata);
  558.                 wait_end_access();
  559.                 if( s.get_rnw()!==1'b0 || s.get_addr()!==1'b0 || s.get_wr_data()!==wrdata )
  560.                 begin
  561.                         $display("sl811 address write failed!");
  562.                         $stop;
  563.                 end
  564.                 //
  565.                 rddata=$random>>24;
  566.                 s.set_rd_data(rddata);
  567.                 z.iord(sl_addr,tmp);
  568. `ifdef CPU28MHZ
  569.                 wait_end_access();
  570. `else
  571.                 @(negedge clk);
  572. `endif
  573.                 if( s.get_rnw()!==1'b1 || s.get_addr()!==1'b0 || tmp!==rddata )
  574.                 begin
  575.                         $display("sl811 address read failed! rddata=%h, tmp=%h, get_rnw=%d, reg_addr=%h",rddata,tmp,s.get_rnw(),s.get_addr());
  576.                         $stop;
  577.                 end
  578.  
  579.  
  580.  
  581.                 // check data reg
  582.                 rdport=sl_data;
  583.                 rdport[14:8]=$random>>25;
  584.                 wrdata=$random>>24;
  585.                 z.iowr(rdport,wrdata);
  586.                 wait_end_access();
  587.                 if( s.get_rnw()!==1'b0 || s.get_addr()!==1'b1 || s.get_wr_data()!==wrdata )
  588.                 begin
  589.                         $display("sl811 data write failed!");
  590.                         $stop;
  591.                 end
  592.                 //
  593.                 rddata=$random>>24;
  594.                 s.set_rd_data(rddata);
  595.                 z.iord(rdport,tmp);
  596. `ifdef CPU28MHZ
  597.                 wait_end_access();
  598. `else
  599.                 @(negedge clk);
  600. `endif
  601.                 if( s.get_rnw()!==1'b1 || s.get_addr()!==1'b1 || tmp!==rddata )
  602.                 begin
  603.                         $display("sl811 data read failed!");
  604.                         $stop;
  605.                 end
  606.  
  607.         endtask
  608.  
  609.  
  610.  
  611.  
  612.         task check_sl811_port;
  613.  
  614.                 reg [7:0] tmp;
  615.  
  616.                 reg ms;
  617.  
  618.                 ms=$random>>31;
  619.  
  620.                 z.iowr(cfg_port,{1'b0,ms,6'd0});
  621.                 wait_end_access();
  622.  
  623.                 @(posedge clk);
  624.                 if( (rst_n===1'b1 && s.get_ms()!==ms   ) ||
  625.                     (rst_n===1'b0 && s.get_ms()!==1'b1 ) )
  626.                 begin
  627.                         $display("sl811_ms_n behaves wrong!");
  628.                         $stop;
  629.                 end
  630.  
  631.                
  632.                 usb_power <= $random>>31;
  633.                 @(posedge clk);
  634.                 z.iord(cfg_port,tmp);
  635.                 if( tmp[7]!==usb_power )
  636.                 begin
  637.                         $display("can't sense usb_power!");
  638.                         $stop;
  639.                 end
  640.  
  641.         endtask
  642.  
  643.  
  644.  
  645.  
  646.  
  647.         task test_pwon_ints;
  648.  
  649.                 reg [7:0] tmp;
  650.  
  651.                 // check ints
  652.                 z.iord(rstint_port,tmp);
  653.                 if( tmp[1:0]!==2'b00 )
  654.                 begin
  655.                         $display("int requests after reset!");
  656.                         $stop;
  657.                 end
  658.                 if( tmp[3:2]!==2'b00 )
  659.                 begin
  660.                         $display("ints enabled after reset!");
  661.                         $stop;
  662.                 end
  663.                 if( tmp[7]!==1'b0 )
  664.                 begin
  665.                         $display("internal int is on after reset!");
  666.                         $stop;
  667.                 end
  668.                 if( tmp[6]!==1'b0 )
  669.                 begin
  670.                         $display("ext.int assertion enabled after reset!");
  671.                         $stop;
  672.                 end
  673.                 if( int_n!==1'b1 )
  674.                 begin
  675.                         $display("ext.int asserted after reset!");
  676.                         $stop;
  677.                 end
  678.         endtask
  679.        
  680.  
  681.  
  682.  
  683.  
  684.         task test_ints;
  685.  
  686.                 reg [7:0] tmp;
  687.  
  688.                 reg [1:0] ints,intena;
  689.  
  690.                 reg eintena;
  691.  
  692.                
  693.                 ints = $random>>30;
  694.  
  695.                 intena = $random>>30;
  696.  
  697.                 eintena = $random>>31;
  698.  
  699.                
  700.                 s.set_intrq(ints[1]);
  701.                 w.set_int_n(~ints[0]);
  702.  
  703.                 @(posedge clk);
  704.  
  705.  
  706.                 z.iord(rstint_port,tmp);
  707.                 tmp[3:2]=intena;
  708.                 tmp[6]=eintena;
  709.                 z.iowr(rstint_port,tmp);
  710.  
  711.                
  712.                 z.iord(rstint_port,tmp);
  713.  
  714.                 if( tmp[1]!==ints[1] || tmp[0]!==ints[0] )
  715.                 begin
  716.                         $display("wrong int signals states!");
  717.                         $stop;
  718.                 end
  719.  
  720.                 if( (  (ints&intena) && tmp[7]!==1'b1) ||
  721.                     ( !(ints&intena) && tmp[7]!==1'b0) )
  722.                 begin
  723.                         $display("wrong internal int state!");
  724.                         $stop;
  725.                 end
  726.  
  727.                 if( tmp[6]!==eintena )
  728.                 begin
  729.                         $display("wrong eintena state!");
  730.                         $stop;
  731.                 end
  732.  
  733.                 if( (eintena && (ints&intena)) ? (int_n!==1'b0) : (int_n!==1'b1) )
  734.                 begin
  735.                         $display("wrong int_n forming!");
  736.                         $stop;
  737.                 end
  738.  
  739.  
  740.  
  741.  
  742.         endtask
  743.  
  744.        
  745.        
  746.  
  747.  
  748.  
  749.         task test_resets;
  750.  
  751.                 reg [7:0] tmp;
  752.  
  753.                 reg [1:0] resets;
  754.  
  755.  
  756.                
  757.                 resets = $random>>30;
  758.  
  759.  
  760.                 // read-modify-write reset register
  761.                 z.iord(rstint_port,tmp);
  762.  
  763.                 tmp[5:4] = resets[1:0];
  764.  
  765.                 z.iowr(rstint_port,tmp);
  766.  
  767.                 if( s.get_rst_n() !== resets[1] )
  768.                 begin
  769.                         $display("no control of sl811 reset!");
  770.                         $stop;
  771.                 end
  772.  
  773.                 if( w.get_rst_n() !== resets[0] )
  774.                 begin
  775.                         $display("no control of w5300 reset!");
  776.                         $stop;
  777.                 end
  778.  
  779.         endtask
  780.        
  781.  
  782.  
  783.  
  784.         task test_pwon_resets;
  785.  
  786.                 reg [7:0] tmp;
  787.  
  788.                 // test resets state after reset
  789.                 if( w.get_rst_n() !== 1'b0 )
  790.                 begin
  791.                         $display("w5300 hasn't rst_n=0 after reset!");
  792.                         $stop;
  793.                 end
  794.                 //
  795.                 if( s.get_rst_n() !== 1'b0 )
  796.                 begin
  797.                         $display("sl811 hasn't rst_n=0 after reset!");
  798.                         $stop;
  799.                 end
  800.  
  801.                 // read reset register and check it
  802.                 z.iord(rstint_port,tmp);
  803.                 if( tmp[5:4]!==2'b00 )
  804.                 begin
  805.                         $display("reset bits in #83AB not 0 after reset!");
  806.                         $stop;
  807.                 end
  808.  
  809.         endtask
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.  
  821.         // time marks
  822.         always
  823.         begin : timemarks
  824.  
  825.                 int ms;
  826.  
  827.                 ms = ($time/1000000);
  828.  
  829.                 #1000000.0;
  830.  
  831.                 $display("time mark: %d ms",ms);
  832.         end
  833.  
  834.  
  835.  
  836.  
  837.  
  838. endmodule
  839.  
  840.