Top secrets sources NedoPC zxusbnet

Rev

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

// ZXiznet project
// (c) NedoPC 2018
//
// testbench


`timescale 1ns/100ps

//// CPU at 14 or 28MHz
`ifdef CPU28MHZ
 `define HALF_CPU_PERIOD (17.8)
`else
 `define HALF_CPU_PERIOD (35.7)
`endif


// CPU at 7MHz
//`define HALF_CPU_PERIOD (70)

// filter clock
`define HALF_FCLK_PERIOD (10.4)

module tb;

        reg rst_n;
        reg clk;

        reg fclk;


        tri1 iorq_n,
             mreq_n,
             rd_n,
             wr_n;

        tri1 int_n;

        wire csrom_n;

        wire iorqge,
             blkrom;
       

        wire [15:0] a;
        wire [ 7:0] d;

        tri  [ 7:0] #1 bd;

        wire brd_n, bwr_n;


        reg [7:0] tmp;




        wire [9:0] w5300_addr;
        wire       w5300_rst_n;
        wire       w5300_cs_n;
        wire       w5300_int_n;

        wire       sl811_rst_n;
        wire       sl811_a0;
        wire       sl811_cs_n;
        wire       sl811_ms_n;
        wire       sl811_intrq;

       
       
        reg usb_power;


        reg [1:0] where_rom;




        // filter clock
        initial
        begin
                fclk = 1'b1;

                forever #`HALF_FCLK_PERIOD fclk = ~fclk;
        end


        initial
        begin
                clk = 1'b1;

                forever #`HALF_CPU_PERIOD clk = ~clk;
        end


        initial
        begin
                rst_n = 1'b0;

                repeat(3) @(posedge clk);

                rst_n <= 1'b1;
        end



        initial
        begin
                where_rom = 2'b00;

                usb_power = 1'b0;
        end








        top DUT
        (
                .fclk(fclk),

                .za(a),
                .zd(d),

                .ziorq_n(iorq_n),
                .zmreq_n(mreq_n),
                .zrd_n(rd_n),
                .zwr_n(wr_n),

                .zcsrom_n(csrom_n),
               
                .ziorqge(iorqge),
                .zblkrom(blkrom),

                .zrst_n(rst_n),
                .zint_n(int_n),

                .bd(bd),

                .bwr_n(bwr_n),
                .brd_n(brd_n),


                .w5300_rst_n(w5300_rst_n),
                .w5300_addr (w5300_addr ),
                .w5300_cs_n (w5300_cs_n ),
                .w5300_int_n(w5300_int_n),
               
                .sl811_rst_n(sl811_rst_n),
                .sl811_intrq(sl811_intrq),
                .sl811_ms_n (sl811_ms_n ),
                .sl811_cs_n (sl811_cs_n ),
                .sl811_a0   (sl811_a0   ),

                .usb_power(usb_power)

        );












        ssz80 z
        (
                .clk  (clk  ),
                .rst_n(rst_n),

                .iorq_n(iorq_n),
                .mreq_n(mreq_n),
                .rd_n  (rd_n  ),
                .wr_n  (wr_n  ),

                .a(a),
                .d(d)
        );





        w5300 w
        (
                .rst_n(w5300_rst_n),
                .addr (w5300_addr ),
                .cs_n (w5300_cs_n ),
                .rd_n (brd_n      ),
                .wr_n (bwr_n      ),
                .int_n(w5300_int_n),
                .d(bd)
        );


        sl811 s
        (
                .rst_n(sl811_rst_n),
                .a0   (sl811_a0   ),
                .cs_n (sl811_cs_n ),
                .wr_n (bwr_n      ),
                .rd_n (brd_n      ),
                .ms   (~sl811_ms_n),
                .intrq(sl811_intrq),
                .d(bd)
        );


        // csrom gen
        assign csrom_n = !(a[15:14]==where_rom[1:0]);

       
       
       
       
       
////////////////////////////////////////////////////////////////////////////////       
////////////////////////////////////////////////////////////////////////////////       
////////////////////////////////////////////////////////////////////////////////       
/// here start tests

        reg [15:0] rstint_port = 16'h83_AB;
//      reg [15:0] w5300_port  = 16'h82_AB;
//      reg [15:0] sl811_port  = 16'h81_AB;
        reg [15:0] cfg_port    = 16'h82_AB;
        reg [15:0] wiomap_port = 16'h81_AB;
        reg [15:0] sl_addr     = 16'h80_AB;
        reg [15:0] sl_data     = 16'h7F_AB;
       
        initial
        begin : tests
       
       
                reg [7:0] tmp;
                reg [7:0] tmp2;

               
                wait(rst_n===1'b1);

                repeat(10) @(posedge clk);
       
       

                test_pwon_resets();
                test_pwon_ints();



                forever // repeat(10000)
                begin
                        case( $random%6 )
                        0: check_sl811_access();
//`ifndef CPU28MHZ
//                      1: check_w5300_mem_access();
//`endif
                        2: check_w5300_port_access();
                        3: test_resets();
                        4: check_sl811_port();
                        5: test_ints();
                        endcase
                end

               








               




               
               
                $display("all tests passed!");
                $stop;
        end

       
       

       
       
        task wait_end_access();

                reg a;

                a = 1'b0;
                wait( brd_n==1'b1 && bwr_n==1'b1 );

                a <= 1'b1;
                wait(a==1'b1);

        endtask
       







        // translates memory address to w5300 address in accordance with specs
        function [9:0] mk_w5300_addr( input [13:0] mem_addr );

                if( mem_addr<14'h2000 )
                begin
                        mk_w5300_addr = mem_addr[9:0];
                end
                else if( mem_addr<14'h3000 )
                begin
                        mk_w5300_addr[9] = 1'b1;
                        mk_w5300_addr[8:6] = mem_addr[11:9];
                        mk_w5300_addr[5:1] = 5'b10111;
                        mk_w5300_addr[0] = mem_addr[0];
                end
                else // if( mem_addr<14'h4000 )
                begin
                        mk_w5300_addr[9] = 1'b1;
                        mk_w5300_addr[8:6] = mem_addr[11:9];
                        mk_w5300_addr[5:1] = 5'b11000;
                        mk_w5300_addr[0] = mem_addr[0];
                end

        endfunction






        task check_w5300_port_access();

                reg [7:0] tmp,rddata,wrdata;
                reg [9:0] waddr;
                reg       a0_inv;

                reg [15:0] port;


                a0_inv = $random>>31;

                waddr = $random>>22;



                z.iowr(cfg_port,{3'd0,1'b1,a0_inv,3'd0});

                z.iord(cfg_port,tmp);
                if( tmp[4:0]!=={1'b1,a0_inv,3'd0} )
                begin
                        $display("can't set w5300 port!");
                        $stop;
                end
               

                z.iowr(wiomap_port,waddr[9:6]);
                z.iord(wiomap_port,tmp);
                if( tmp[3:0]!==waddr[9:6] )
                begin
                        $display("can't set wiomap port!");
                        $stop;
                end



                // make access port address
                port = sl_data;
                port[13:8] = waddr[5:0];


                w.init_access(); // clear access_* to X


                if( $random>>31 )
                begin
                        wrdata = $random>>24;
                        z.iowr(port,wrdata);
                        wait_end_access();
                        if( w.get_addr()!==(waddr^a0_inv) ||
                            w.get_rnw()!==1'b0            ||
                            w.get_wr_data()!==wrdata      )
                        begin
                                $display("w5300 port write failed!");
                                $stop;
                        end
                end
                else
                begin
                        rddata = $random>>24;
                        w.set_rd_data(rddata);
                        z.iord(port,tmp);
`ifdef CPU28MHZ
                        wait_end_access();
`else
                        @(negedge clk);
`endif
                        if( w.get_addr()!==(waddr^a0_inv) ||
                            w.get_rnw()!==1'b1            ||
                            tmp!==rddata                  )
                        begin
                                $display("w5300 port read failed!");
                                $stop;
                        end
                end

        endtask




        task check_w5300_mem_access;

                reg [7:0] tmp,rddata,wrdata;
                reg [15:0] memaddr;
                reg [ 9:0] waddr;

                reg [1:0] rom;
                reg       a0_inv;
                reg       sub_ena;


                rom    = $random>>30;
                a0_inv = $random>>31;
                sub_ena= $random>>31;

                z.iowr(cfg_port,{4'd0,a0_inv,sub_ena,rom});

                z.iord(cfg_port,tmp);
                if( tmp[4:0]!=={1'd0,a0_inv,sub_ena,rom} )
                begin
                        $display("can't set w5300 port!");
                        $stop;
                end


                if( $random>>31 )
                        where_rom = rom;
                else
                begin
                        where_rom = $random>>30;
                        while( where_rom==rom )
                                where_rom = $random>>30;
                end



                w.init_access(); // clear access_* to X


                memaddr = $random>>18;
                memaddr[15:14] = where_rom;



                if( $random>>31 )
                begin
                        repeat(10)
                        begin
                                wrdata = $random>>24;
                                z.memwr(memaddr,wrdata);
                                wait_end_access();
                                if( where_rom==rom && sub_ena )
                                begin
                                        if( w.get_addr()!==(mk_w5300_addr(memaddr[13:0])^a0_inv) ||
                                            w.get_rnw()!==1'b0                                   ||
                                            w.get_wr_data()!==wrdata                             )
                                        begin
                                                $display("w5300 write failed!");
                                                $stop;
                                        end
                                end
                                else
                                begin
                                        if( w.get_addr()!=={10{1'bX}} || w.get_rnw()!==1'bX || w.get_wr_data()!=={8{1'bX}} )
                                        begin
                                                $display("write succeeded with wrong ROM mapping!");
                                                $stop;
                                        end
                                end
                        end
                end
                else
                begin
                        rddata = $random>>24;
                        w.set_rd_data(rddata);
                        z.memrd(memaddr,tmp);
                        @(negedge clk);
                        if( where_rom==rom && sub_ena )
                        begin
                                if( w.get_addr()!==(mk_w5300_addr(memaddr[13:0])^a0_inv) ||
                                    w.get_rnw()!==1'b1                                   ||
                                    tmp!==rddata                                         )
                                begin
                                        $display("w5300 read failed!");
                                        $stop;
                                end
                        end
                        else
                        begin
                                if( w.get_addr()!=={10{1'bX}} || w.get_rnw()!==1'bX )
                                begin
                                        $display("read succeeded with wrong ROM mapping!");
                                        $stop;
                                end
                        end
                end













        endtask







        task check_sl811_access;

                reg [7:0] tmp, rddata, wrdata;

                reg [15:0] rdport;


                // turn off w5300 port access
                z.iord(cfg_port,tmp);
                if( tmp[4]!==1'b0 )
                begin
                        tmp[4]=1'b0;
                        z.iowr(cfg_port,tmp);
                end


                // check address reg
                wrdata=$random>>24;
                z.iowr(sl_addr,wrdata);
                wait_end_access();
                if( s.get_rnw()!==1'b0 || s.get_addr()!==1'b0 || s.get_wr_data()!==wrdata )
                begin
                        $display("sl811 address write failed!");
                        $stop;
                end
                //
                rddata=$random>>24;
                s.set_rd_data(rddata);
                z.iord(sl_addr,tmp);
`ifdef CPU28MHZ
                wait_end_access();
`else
                @(negedge clk);
`endif
                if( s.get_rnw()!==1'b1 || s.get_addr()!==1'b0 || tmp!==rddata )
                begin
                        $display("sl811 address read failed! rddata=%h, tmp=%h, get_rnw=%d, reg_addr=%h",rddata,tmp,s.get_rnw(),s.get_addr());
                        $stop;
                end



                // check data reg
                rdport=sl_data;
                rdport[14:8]=$random>>25;
                wrdata=$random>>24;
                z.iowr(rdport,wrdata);
                wait_end_access();
                if( s.get_rnw()!==1'b0 || s.get_addr()!==1'b1 || s.get_wr_data()!==wrdata )
                begin
                        $display("sl811 data write failed!");
                        $stop;
                end
                //
                rddata=$random>>24;
                s.set_rd_data(rddata);
                z.iord(rdport,tmp);
`ifdef CPU28MHZ
                wait_end_access();
`else
                @(negedge clk);
`endif
                if( s.get_rnw()!==1'b1 || s.get_addr()!==1'b1 || tmp!==rddata )
                begin
                        $display("sl811 data read failed!");
                        $stop;
                end

        endtask




        task check_sl811_port;

                reg [7:0] tmp;

                reg ms;

                ms=$random>>31;

                z.iowr(cfg_port,{1'b0,ms,6'd0});
                wait_end_access();

                @(posedge clk);
                if( (rst_n===1'b1 && s.get_ms()!==ms   ) ||
                    (rst_n===1'b0 && s.get_ms()!==1'b1 ) )
                begin
                        $display("sl811_ms_n behaves wrong!");
                        $stop;
                end

               
                usb_power <= $random>>31;
                @(posedge clk);
                z.iord(cfg_port,tmp);
                if( tmp[7]!==usb_power )
                begin
                        $display("can't sense usb_power!");
                        $stop;
                end

        endtask





        task test_pwon_ints;

                reg [7:0] tmp;

                // check ints
                z.iord(rstint_port,tmp);
                if( tmp[1:0]!==2'b00 )
                begin
                        $display("int requests after reset!");
                        $stop;
                end
                if( tmp[3:2]!==2'b00 )
                begin
                        $display("ints enabled after reset!");
                        $stop;
                end
                if( tmp[7]!==1'b0 )
                begin
                        $display("internal int is on after reset!");
                        $stop;
                end
                if( tmp[6]!==1'b0 )
                begin
                        $display("ext.int assertion enabled after reset!");
                        $stop;
                end
                if( int_n!==1'b1 )
                begin
                        $display("ext.int asserted after reset!");
                        $stop;
                end
        endtask
       




        task test_ints;

                reg [7:0] tmp;

                reg [1:0] ints,intena;

                reg eintena;

               
                ints = $random>>30;

                intena = $random>>30;

                eintena = $random>>31;

               
                s.set_intrq(ints[1]);
                w.set_int_n(~ints[0]);

                @(posedge clk);


                z.iord(rstint_port,tmp);
                tmp[3:2]=intena;
                tmp[6]=eintena;
                z.iowr(rstint_port,tmp);

               
                z.iord(rstint_port,tmp);

                if( tmp[1]!==ints[1] || tmp[0]!==ints[0] )
                begin
                        $display("wrong int signals states!");
                        $stop;
                end

                if( (  (ints&intena) && tmp[7]!==1'b1) ||
                    ( !(ints&intena) && tmp[7]!==1'b0) )
                begin
                        $display("wrong internal int state!");
                        $stop;
                end

                if( tmp[6]!==eintena )
                begin
                        $display("wrong eintena state!");
                        $stop;
                end

                if( (eintena && (ints&intena)) ? (int_n!==1'b0) : (int_n!==1'b1) )
                begin
                        $display("wrong int_n forming!");
                        $stop;
                end




        endtask

       
       



        task test_resets;

                reg [7:0] tmp;

                reg [1:0] resets;


               
                resets = $random>>30;


                // read-modify-write reset register
                z.iord(rstint_port,tmp);

                tmp[5:4] = resets[1:0];

                z.iowr(rstint_port,tmp);

                if( s.get_rst_n() !== resets[1] )
                begin
                        $display("no control of sl811 reset!");
                        $stop;
                end

                if( w.get_rst_n() !== resets[0] )
                begin
                        $display("no control of w5300 reset!");
                        $stop;
                end

        endtask
       



        task test_pwon_resets;

                reg [7:0] tmp;

                // test resets state after reset
                if( w.get_rst_n() !== 1'b0 )
                begin
                        $display("w5300 hasn't rst_n=0 after reset!");
                        $stop;
                end
                //
                if( s.get_rst_n() !== 1'b0 )
                begin
                        $display("sl811 hasn't rst_n=0 after reset!");
                        $stop;
                end

                // read reset register and check it
                z.iord(rstint_port,tmp);
                if( tmp[5:4]!==2'b00 )
                begin
                        $display("reset bits in #83AB not 0 after reset!");
                        $stop;
                end

        endtask











        // time marks
        always
        begin : timemarks

                int ms;

                ms = ($time/1000000);

                #1000000.0;

                $display("time mark: %d ms",ms);
        end





endmodule