Subversion Repositories zxusbnet

Rev

Rev 152 | 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] cfg_port    = 16'h82_AB;
  227.         reg [15:0] wiomap_port = 16'h81_AB;
  228.         reg [15:0] sl_addr     = 16'h80_AB;
  229.         reg [15:0] sl_data     = 16'h7F_AB;
  230.        
  231.         initial
  232.         begin : tests
  233.        
  234.        
  235.                 reg [7:0] tmp;
  236.                 reg [7:0] tmp2;
  237.  
  238.                
  239.                 wait(rst_n===1'b1);
  240.  
  241.                 repeat(10) @(posedge clk);
  242.        
  243.        
  244.  
  245.                 test_pwon_resets();
  246.                 test_pwon_ints();
  247.  
  248.  
  249.  
  250.                 forever // repeat(10000)
  251.                 begin
  252.                         case( $random%6 )
  253.                         0: check_sl811_access();
  254.                         1: check_w5300_mem_access();
  255.                         2: check_w5300_port_access();
  256.                         3: test_resets();
  257.                         4: check_sl811_port();
  258.                         5: test_ints();
  259.                         endcase
  260.                 end
  261.  
  262.                
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.                
  272.  
  273.  
  274.  
  275.  
  276.                
  277.                
  278.                 $display("all tests passed!");
  279.                 $stop;
  280.         end
  281.  
  282.        
  283.        
  284.  
  285.        
  286.        
  287.         task wait_end_access();
  288.  
  289.                 reg a;
  290.  
  291.                 a = 1'b0;
  292.                 wait( brd_n==1'b1 && bwr_n==1'b1 );
  293.  
  294.                 a <= 1'b1;
  295.                 wait(a==1'b1);
  296.  
  297.         endtask
  298.        
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.         // translates memory address to w5300 address in accordance with specs
  307.         function [9:0] mk_w5300_addr( input [13:0] mem_addr );
  308.  
  309.                 if( mem_addr<14'h2000 )
  310.                 begin
  311.                         mk_w5300_addr = mem_addr[9:0];
  312.                 end
  313.                 else if( mem_addr<14'h3000 )
  314.                 begin
  315.                         mk_w5300_addr[9] = 1'b1;
  316.                         mk_w5300_addr[8:6] = mem_addr[11:9];
  317.                         mk_w5300_addr[5:1] = 5'b10111;
  318.                         mk_w5300_addr[0] = mem_addr[0];
  319.                 end
  320.                 else // if( mem_addr<14'h4000 )
  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'b11000;
  325.                         mk_w5300_addr[0] = mem_addr[0];
  326.                 end
  327.  
  328.         endfunction
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.         task check_w5300_port_access();
  336.  
  337.                 reg [7:0] tmp,rddata,wrdata;
  338.                 reg [9:0] waddr;
  339.                 reg       a0_inv;
  340.  
  341.                 reg [15:0] port;
  342.  
  343.  
  344.                 a0_inv = $random>>31;
  345.  
  346.                 waddr = $random>>22;
  347.  
  348.  
  349.  
  350.                 z.iowr(cfg_port,{3'd0,1'b1,a0_inv,3'd0});
  351.  
  352.                 z.iord(cfg_port,tmp);
  353.                 if( tmp[4:0]!=={1'b1,a0_inv,3'd0} )
  354.                 begin
  355.                         $display("can't set w5300 port!");
  356.                         $stop;
  357.                 end
  358.                
  359.  
  360.                 z.iowr(wiomap_port,waddr[9:6]);
  361.                 z.iord(wiomap_port,tmp);
  362.                 if( tmp[3:0]!==waddr[9:6] )
  363.                 begin
  364.                         $display("can't set wiomap port!");
  365.                         $stop;
  366.                 end
  367.  
  368.  
  369.  
  370.                 // make access port address
  371.                 port = sl_data;
  372.                 port[13:8] = waddr[5:0];
  373.  
  374.  
  375.                 w.init_access(); // clear access_* to X
  376.  
  377.  
  378.                 if( $random>>31 )
  379.                 begin
  380.                         wrdata = $random>>24;
  381.                         z.iowr(port,wrdata);
  382.                         wait_end_access();
  383.                         if( w.get_addr()!==(waddr^a0_inv) ||
  384.                             w.get_rnw()!==1'b0            ||
  385.                             w.get_wr_data()!==wrdata      )
  386.                         begin
  387.                                 $display("w5300 port write failed!");
  388.                                 $stop;
  389.                         end
  390.                 end
  391.                 else
  392.                 begin
  393.                         rddata = $random>>24;
  394.                         w.set_rd_data(rddata);
  395.                         z.iord(port,tmp);
  396.                         @(negedge clk);
  397.                         if( w.get_addr()!==(waddr^a0_inv) ||
  398.                             w.get_rnw()!==1'b1            ||
  399.                             tmp!==rddata                  )
  400.                         begin
  401.                                 $display("w5300 port read failed!");
  402.                                 $stop;
  403.                         end
  404.                 end
  405.  
  406.         endtask
  407.  
  408.  
  409.  
  410.  
  411.         task check_w5300_mem_access;
  412.  
  413.                 reg [7:0] tmp,rddata,wrdata;
  414.                 reg [15:0] memaddr;
  415.                 reg [ 9:0] waddr;
  416.  
  417.                 reg [1:0] rom;
  418.                 reg       a0_inv;
  419.                 reg       sub_ena;
  420.  
  421.  
  422.                 rom    = $random>>30;
  423.                 a0_inv = $random>>31;
  424.                 sub_ena= $random>>31;
  425.  
  426.                 z.iowr(cfg_port,{4'd0,a0_inv,sub_ena,rom});
  427.  
  428.                 z.iord(cfg_port,tmp);
  429.                 if( tmp[4:0]!=={1'd0,a0_inv,sub_ena,rom} )
  430.                 begin
  431.                         $display("can't set w5300 port!");
  432.                         $stop;
  433.                 end
  434.  
  435.  
  436.                 if( $random>>31 )
  437.                         where_rom = rom;
  438.                 else
  439.                 begin
  440.                         where_rom = $random>>30;
  441.                         while( where_rom==rom )
  442.                                 where_rom = $random>>30;
  443.                 end
  444.  
  445.  
  446.  
  447.                 w.init_access(); // clear access_* to X
  448.  
  449.  
  450.                 memaddr = $random>>18;
  451.                 memaddr[15:14] = where_rom;
  452.  
  453.  
  454.  
  455.                 if( $random>>31 )
  456.                 begin
  457.                         repeat(10)
  458.                         begin
  459.                                 wrdata = $random>>24;
  460.                                 z.memwr(memaddr,wrdata);
  461.                                 wait_end_access();
  462.                                 if( where_rom==rom && sub_ena )
  463.                                 begin
  464.                                         if( w.get_addr()!==(mk_w5300_addr(memaddr[13:0])^a0_inv) ||
  465.                                             w.get_rnw()!==1'b0                                   ||
  466.                                             w.get_wr_data()!==wrdata                             )
  467.                                         begin
  468.                                                 $display("w5300 write failed!");
  469.                                                 $stop;
  470.                                         end
  471.                                 end
  472.                                 else
  473.                                 begin
  474.                                         if( w.get_addr()!=={10{1'bX}} || w.get_rnw()!==1'bX || w.get_wr_data()!=={8{1'bX}} )
  475.                                         begin
  476.                                                 $display("write succeeded with wrong ROM mapping!");
  477.                                                 $stop;
  478.                                         end
  479.                                 end
  480.                         end
  481.                 end
  482.                 else
  483.                 begin
  484.                         rddata = $random>>24;
  485.                         w.set_rd_data(rddata);
  486.                         z.memrd(memaddr,tmp);
  487.                         @(negedge clk);
  488.                         if( where_rom==rom && sub_ena )
  489.                         begin
  490.                                 if( w.get_addr()!==(mk_w5300_addr(memaddr[13:0])^a0_inv) ||
  491.                                     w.get_rnw()!==1'b1                                   ||
  492.                                     tmp!==rddata                                         )
  493.                                 begin
  494.                                         $display("w5300 read failed!");
  495.                                         $stop;
  496.                                 end
  497.                         end
  498.                         else
  499.                         begin
  500.                                 if( w.get_addr()!=={10{1'bX}} || w.get_rnw()!==1'bX )
  501.                                 begin
  502.                                         $display("read succeeded with wrong ROM mapping!");
  503.                                         $stop;
  504.                                 end
  505.                         end
  506.                 end
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.         endtask
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.         task check_sl811_access;
  529.  
  530.                 reg [7:0] tmp, rddata, wrdata;
  531.  
  532.                 reg [15:0] rdport;
  533.  
  534.  
  535.                 // turn off w5300 port access
  536.                 z.iord(cfg_port,tmp);
  537.                 if( tmp[4]!==1'b0 )
  538.                 begin
  539.                         tmp[4]=1'b0;
  540.                         z.iowr(cfg_port,tmp);
  541.                 end
  542.  
  543.  
  544.                 // check address reg
  545.                 wrdata=$random>>24;
  546.                 z.iowr(sl_addr,wrdata);
  547.                 wait_end_access();
  548.                 if( s.get_rnw()!==1'b0 || s.get_addr()!==1'b0 || s.get_wr_data()!==wrdata )
  549.                 begin
  550.                         $display("sl811 address write failed!");
  551.                         $stop;
  552.                 end
  553.                 //
  554.                 rddata=$random>>24;
  555.                 s.set_rd_data(rddata);
  556.                 z.iord(sl_addr,tmp);
  557.                 @(negedge clk);
  558.                 if( s.get_rnw()!==1'b1 || s.get_addr()!==1'b0 || tmp!==rddata )
  559.                 begin
  560.                         $display("sl811 address read failed!");
  561.                         $stop;
  562.                 end
  563.  
  564.  
  565.  
  566.                 // check data reg
  567.                 rdport=sl_data;
  568.                 rdport[14:8]=$random>>25;
  569.                 wrdata=$random>>24;
  570.                 z.iowr(rdport,wrdata);
  571.                 wait_end_access();
  572.                 if( s.get_rnw()!==1'b0 || s.get_addr()!==1'b1 || s.get_wr_data()!==wrdata )
  573.                 begin
  574.                         $display("sl811 data write failed!");
  575.                         $stop;
  576.                 end
  577.                 //
  578.                 rddata=$random>>24;
  579.                 s.set_rd_data(rddata);
  580.                 z.iord(rdport,tmp);
  581.                 @(negedge clk);
  582.                 if( s.get_rnw()!==1'b1 || s.get_addr()!==1'b1 || tmp!==rddata )
  583.                 begin
  584.                         $display("sl811 data read failed!");
  585.                         $stop;
  586.                 end
  587.  
  588.         endtask
  589.  
  590.  
  591.  
  592.  
  593.         task check_sl811_port;
  594.  
  595.                 reg [7:0] tmp;
  596.  
  597.                 reg ms;
  598.  
  599.                 ms=$random>>31;
  600.  
  601.                 z.iowr(cfg_port,{1'b0,ms,6'd0});
  602.                 wait_end_access();
  603.  
  604.                 @(posedge clk);
  605.                 if( (rst_n===1'b1 && s.get_ms()!==ms   ) ||
  606.                     (rst_n===1'b0 && s.get_ms()!==1'b1 ) )
  607.                 begin
  608.                         $display("sl811_ms_n behaves wrong!");
  609.                         $stop;
  610.                 end
  611.  
  612.                
  613.                 usb_power <= $random>>31;
  614.                 @(posedge clk);
  615.                 z.iord(cfg_port,tmp);
  616.                 if( tmp[7]!==usb_power )
  617.                 begin
  618.                         $display("can't sense usb_power!");
  619.                         $stop;
  620.                 end
  621.  
  622.         endtask
  623.  
  624.  
  625.  
  626.  
  627.  
  628.         task test_pwon_ints;
  629.  
  630.                 reg [7:0] tmp;
  631.  
  632.                 // check ints
  633.                 z.iord(rstint_port,tmp);
  634.                 if( tmp[1:0]!==2'b00 )
  635.                 begin
  636.                         $display("int requests after reset!");
  637.                         $stop;
  638.                 end
  639.                 if( tmp[3:2]!==2'b00 )
  640.                 begin
  641.                         $display("ints enabled after reset!");
  642.                         $stop;
  643.                 end
  644.                 if( tmp[7]!==1'b0 )
  645.                 begin
  646.                         $display("internal int is on after reset!");
  647.                         $stop;
  648.                 end
  649.                 if( tmp[6]!==1'b0 )
  650.                 begin
  651.                         $display("ext.int assertion enabled after reset!");
  652.                         $stop;
  653.                 end
  654.                 if( int_n!==1'b1 )
  655.                 begin
  656.                         $display("ext.int asserted after reset!");
  657.                         $stop;
  658.                 end
  659.         endtask
  660.        
  661.  
  662.  
  663.  
  664.  
  665.         task test_ints;
  666.  
  667.                 reg [7:0] tmp;
  668.  
  669.                 reg [1:0] ints,intena;
  670.  
  671.                 reg eintena;
  672.  
  673.                
  674.                 ints = $random>>30;
  675.  
  676.                 intena = $random>>30;
  677.  
  678.                 eintena = $random>>31;
  679.  
  680.                
  681.                 s.set_intrq(ints[1]);
  682.                 w.set_int_n(~ints[0]);
  683.  
  684.                 @(posedge clk);
  685.  
  686.  
  687.                 z.iord(rstint_port,tmp);
  688.                 tmp[3:2]=intena;
  689.                 tmp[6]=eintena;
  690.                 z.iowr(rstint_port,tmp);
  691.  
  692.                
  693.                 z.iord(rstint_port,tmp);
  694.  
  695.                 if( tmp[1]!==ints[1] || tmp[0]!==ints[0] )
  696.                 begin
  697.                         $display("wrong int signals states!");
  698.                         $stop;
  699.                 end
  700.  
  701.                 if( (  (ints&intena) && tmp[7]!==1'b1) ||
  702.                     ( !(ints&intena) && tmp[7]!==1'b0) )
  703.                 begin
  704.                         $display("wrong internal int state!");
  705.                         $stop;
  706.                 end
  707.  
  708.                 if( tmp[6]!==eintena )
  709.                 begin
  710.                         $display("wrong eintena state!");
  711.                         $stop;
  712.                 end
  713.  
  714.                 if( (eintena && (ints&intena)) ? (int_n!==1'b0) : (int_n!==1'b1) )
  715.                 begin
  716.                         $display("wrong int_n forming!");
  717.                         $stop;
  718.                 end
  719.  
  720.  
  721.  
  722.  
  723.         endtask
  724.  
  725.        
  726.        
  727.  
  728.  
  729.  
  730.         task test_resets;
  731.  
  732.                 reg [7:0] tmp;
  733.  
  734.                 reg [1:0] resets;
  735.  
  736.  
  737.                
  738.                 resets = $random>>30;
  739.  
  740.  
  741.                 // read-modify-write reset register
  742.                 z.iord(rstint_port,tmp);
  743.  
  744.                 tmp[5:4] = resets[1:0];
  745.  
  746.                 z.iowr(rstint_port,tmp);
  747.  
  748.                 if( s.get_rst_n() !== resets[1] )
  749.                 begin
  750.                         $display("no control of sl811 reset!");
  751.                         $stop;
  752.                 end
  753.  
  754.                 if( w.get_rst_n() !== resets[0] )
  755.                 begin
  756.                         $display("no control of w5300 reset!");
  757.                         $stop;
  758.                 end
  759.  
  760.         endtask
  761.        
  762.  
  763.  
  764.  
  765.         task test_pwon_resets;
  766.  
  767.                 reg [7:0] tmp;
  768.  
  769.                 // test resets state after reset
  770.                 if( w.get_rst_n() !== 1'b0 )
  771.                 begin
  772.                         $display("w5300 hasn't rst_n=0 after reset!");
  773.                         $stop;
  774.                 end
  775.                 //
  776.                 if( s.get_rst_n() !== 1'b0 )
  777.                 begin
  778.                         $display("sl811 hasn't rst_n=0 after reset!");
  779.                         $stop;
  780.                 end
  781.  
  782.                 // read reset register and check it
  783.                 z.iord(rstint_port,tmp);
  784.                 if( tmp[5:4]!==2'b00 )
  785.                 begin
  786.                         $display("reset bits in #83AB not 0 after reset!");
  787.                         $stop;
  788.                 end
  789.  
  790.         endtask
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801.  
  802.         // time marks
  803.         always
  804.         begin : timemarks
  805.  
  806.                 int ms;
  807.  
  808.                 ms = ($time/1000000);
  809.  
  810.                 #1000000.0;
  811.  
  812.                 $display("time mark: %d ms",ms);
  813.         end
  814.  
  815.  
  816.  
  817.  
  818.  
  819. endmodule
  820.  
  821.