Subversion Repositories zxusbnet

Rev

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