OpenCores
URL https://opencores.org/ocsvn/pci/pci/trunk

Subversion Repositories pci

[/] [pci/] [tags/] [rel_7/] [apps/] [test/] [bench/] [verilog/] [test_bench.v] - Rev 154

Compare with Previous | Blame | View Log

`include "timescale.v"
`include "pci_testbench_defines.v"
 
`define TIME $display("Time %t", $time) 
`define ERROR(TEXT) $display("*E, %s", TEXT)
`define INVALID_DATA(FROM) $display("*E, Data read from %s not as expected!", FROM)
`define VALUES(EXPECTED,ACTUAL) $display("Expected %h, Actual %h", EXPECTED, ACTUAL)
 
module test_bench
(
);
 
 
reg clk,
    rst ;
 
assign glbl.GSR = rst ;
 
wire wbm_cyc_o,
     wbm_stb_o,
     wbm_cab_o,
     wbm_we_o ;
 
wire [31:0] wbm_adr_o ;
wire [3:0]  wbm_sel_o ;
 
wire [31:0] wbm_dat_o,
            wbm_dat_i ;
 
wire wbm_ack_i,
     wbm_rty_i,
     wbm_err_i ;
 
wire wbs_cyc_i,
     wbs_stb_i,
     wbs_cab_i,
     wbs_we_i ;
 
wire [31:0] wbs_adr_i ;
wire [3:0]  wbs_sel_i ;
 
wire [31:0] wbs_dat_i,
            wbs_dat_o ;
 
wire wbs_ack_o,
     wbs_rty_o,
     wbs_err_o ;
 
reg pci_clk,
    pci_irdy_reg,
    pci_irdy_en_reg,
    pci_trdy_reg ;
 
reg [31:0] pci_ad_reg ;
 
test i_test
(
    .clk_i      (clk),
    .rst_i      (rst),
 
    .pci_clk_i  (pci_clk),
 
    .wbm_cyc_o  (wbm_cyc_o),
    .wbm_stb_o  (wbm_stb_o),
    .wbm_cab_o  (wbm_cab_o),
    .wbm_we_o   (wbm_we_o ),
    .wbm_adr_o  (wbm_adr_o),
    .wbm_sel_o  (wbm_sel_o),
    .wbm_dat_o  (wbm_dat_o),
    .wbm_dat_i  (wbm_dat_i),
    .wbm_ack_i  (wbm_ack_i),
    .wbm_rty_i  (wbm_rty_i),
    .wbm_err_i  (wbm_err_i),
 
    .wbs_cyc_i  (wbs_cyc_i),
    .wbs_stb_i  (wbs_stb_i),
    .wbs_cab_i  (wbs_cab_i),
    .wbs_we_i   (wbs_we_i ),
    .wbs_adr_i  (wbs_adr_i),
    .wbs_sel_i  (wbs_sel_i),
    .wbs_dat_i  (wbs_dat_i),
    .wbs_dat_o  (wbs_dat_o),
    .wbs_ack_o  (wbs_ack_o),
    .wbs_rty_o  (wbs_rty_o),
    .wbs_err_o  (wbs_err_o),
 
    .pci_irdy_reg_i    (pci_irdy_reg),
    .pci_irdy_en_reg_i (pci_irdy_en_reg),
    .pci_trdy_reg_i    (pci_trdy_reg),
    .pci_ad_reg_i      (pci_ad_reg)
);
 
WB_MASTER_BEHAVIORAL wishbone_master
(
    .CLK_I(clk),
    .RST_I(rst),
    .TAG_I(`WB_TAG_WIDTH'h0),
    .TAG_O(),
    .ACK_I(wbs_ack_o),
    .ADR_O(wbs_adr_i),
    .CYC_O(wbs_cyc_i),
    .DAT_I(wbs_dat_o),
    .DAT_O(wbs_dat_i),
    .ERR_I(1'b0),
    .RTY_I(1'b0),
    .SEL_O(wbs_sel_i),
    .STB_O(wbs_stb_i),
    .WE_O (wbs_we_i),
    .CAB_O(wbs_cab_i)
);
 
WB_SLAVE_BEHAVIORAL wishbone_slave
(
    .CLK_I              (clk),
    .RST_I              (rst),
    .ACK_O              (wbm_ack_i),
    .ADR_I              (wbm_adr_o),
    .CYC_I              (wbm_cyc_o),
    .DAT_O              (wbm_dat_i),
    .DAT_I              (wbm_dat_o),
    .ERR_O              (),
    .RTY_O              (),
    .SEL_I              (wbm_sel_o),
    .STB_I              (wbm_stb_o),
    .WE_I               (wbm_we_o),
    .CAB_I              (wbm_cab_o)
);
 
integer wbs_mon_log_file_desc, wbm_mon_log_file_desc ;
 
WB_BUS_MON wbs_wb_mon(
                    .CLK_I(clk),
                    .RST_I(rst),
                    .ACK_I(wbs_ack_o),
                    .ADDR_O(wbs_adr_i),
                    .CYC_O(wbs_cyc_i),
                    .DAT_I(wbs_dat_o),
                    .DAT_O(wbs_dat_i),
                    .ERR_I(1'b0),
                    .RTY_I(1'b0),
                    .SEL_O(wbs_sel_i),
                    .STB_O(wbs_stb_i),
                    .WE_O (wbs_we_i),
                    .TAG_I( `WB_TAG_WIDTH'h0 ),
                    .TAG_O(),
                    .CAB_O(wbs_cab_i),
                    .log_file_desc ( wbs_mon_log_file_desc )
                  ) ;
 
WB_BUS_MON wbm_wb_mon(
                    .CLK_I(clk),
                    .RST_I(rst),
                    .ACK_I(wbm_ack_i),
                    .ADDR_O(wbm_adr_o),
                    .CYC_O(wbm_cyc_o),
                    .DAT_I(wbm_dat_i),
                    .DAT_O(wbm_dat_o),
                    .ERR_I(1'b0),
                    .RTY_I(1'b0),
                    .SEL_O(wbm_sel_o),
                    .STB_O(wbm_stb_o),
                    .WE_O (wbm_we_o),
                    .TAG_I( `WB_TAG_WIDTH'h0 ),
                    .TAG_O(),
                    .CAB_O(wbm_cab_o),
                    .log_file_desc ( wbm_mon_log_file_desc )
                  ) ;
 
 
// clock generation
always
    #(10) clk = ~clk ;
 
always
    #15 pci_clk = ~pci_clk ;
 
integer wb_master_waits ;
initial
begin
    wbs_mon_log_file_desc = $fopen("../log/wbs_mon.log") ;
    wbm_mon_log_file_desc = $fopen("../log/wbm_mon.log") ;
    clk = 1'b1 ;
    rst = 1'b1 ;
 
    pci_clk         = 1'b1 ;
    pci_irdy_reg    = 1'b1 ;
    pci_irdy_en_reg = 1'b1 ;
    pci_trdy_reg    = 1'b1 ;
    pci_ad_reg      = 0 ;
 
    wb_master_waits = 0 ;
 
    repeat(10)
        @(posedge clk) ;
 
    rst <= 1'b0 ;
 
    run_tests ;
 
    $stop ;
end
 
task run_tests ;
begin
/*    
    wbs_fill_with_singles(0) ;
    wbs_check_data_with_singles(0) ;
 
    wbs_fill_with_singles(1) ;
    wbs_check_data_with_bursts(1, 1024) ;
 
    wbs_fill_with_bursts(0, 2) ;
    wbs_check_data_with_singles(0) ;
 
    wbs_fill_with_bursts(1, 4) ;
    wbs_check_data_with_bursts(1, 2) ;
 
    wbs_fill_with_singles(2) ;
    wbs_check_data_with_bursts(2, 16) ;
 
    wbs_fill_with_bursts(3, 64) ;
    wbs_check_data_with_bursts(3, 128) ;
 
    test_master_writes ;
    test_master_reads ;
 
    test_slave_error_detection ;
 
    test_master_transaction_counts ;
*/
    test_master_data_errors ;
end
endtask
 
task wbs_fill_with_singles ;
    input [3:0] pattern_select ;
    integer i ;
    reg [31:0] current_data ;
    reg [31:0] current_address ;
begin
    current_address = 0 ;
 
    current_data = get_first_data(pattern_select) ;
 
    for (i = 0 ; i < 1024 ; i = i + 1)
    begin
        wb_master_single_write(current_address, current_data) ;
        current_data = get_next_data (pattern_select, current_data) ;
        current_address = current_address + 4 ;
    end
end
endtask
 
task wbs_fill_with_bursts ;
    input [3:0]  pattern_select ;
    input [31:0] burst_sizes ;
 
    integer i ;
    reg [31:0] current_data ;
    reg [31:0] current_address ;
 
    reg `WRITE_STIM_TYPE   write_data ;
begin
    current_address = 0 ;
 
    write_data = 0 ;
 
    write_data`WRITE_SEL = 4'hF ;
 
    current_data = get_first_data (pattern_select) ;
 
    for (i = 0 ; i < 1024 ; i = i + 1)
    begin
 
        write_data`WRITE_ADDRESS = current_address ;
        write_data`WRITE_DATA    = current_data ;
 
        wishbone_master.blk_write_data[i % burst_sizes] = write_data ;
 
        if ((i % burst_sizes) == (burst_sizes - 1))
            wb_master_burst_write(burst_sizes) ;
 
        current_address = current_address + 4 ;
        current_data = get_next_data(pattern_select, current_data) ;
    end
end
endtask
 
task wbs_check_data_with_singles ;
    input [3:0] pattern_select ;
 
    integer i ;
    reg [31:0] current_data ;
    reg [31:0] current_address ;
begin
    current_address = 0 ;
 
    current_data = get_first_data(pattern_select) ;
 
    for (i = 0 ; i < 1024 ; i = i + 1)
    begin
 
        wb_master_single_read(current_address, current_data) ;
        current_address = current_address + 4 ;
        current_data    = get_next_data(pattern_select, current_data) ;
    end
end
endtask
 
task wb_master_single_write ;
    input [31:0] adr_i ;
    input [31:0] data_i ;
 
    reg `WRITE_STIM_TYPE   write_data ;
    reg `WRITE_RETURN_TYPE write_status ;
    reg `WB_TRANSFER_FLAGS write_flags ;
begin
    write_flags = 0 ;
    write_flags`INIT_WAITS   = wb_master_waits ;
    write_flags`SUBSEQ_WAITS = wb_master_waits ;
 
    write_data  = 0 ;
 
    write_data`WRITE_DATA    = data_i ;
    write_data`WRITE_ADDRESS = adr_i ;
    write_data`WRITE_SEL     = 4'hF ;
 
    wishbone_master.wb_single_write( write_data, write_flags, write_status ) ;
 
    if (write_status`CYC_ACTUAL_TRANSFER !== 1)
    begin
        `TIME ;
        `ERROR("Single writes must always be succesfull") ;
        $stop ;
    end
end
endtask // wb_master_single_write
 
task wb_master_burst_write ;
    input [31:0] size_i ;
 
    reg `WRITE_RETURN_TYPE write_status ;
    reg `WB_TRANSFER_FLAGS write_flags ;
 
    integer i ;
begin
    write_flags = 0 ;
    write_flags`WB_TRANSFER_SIZE = size_i ;
    write_flags`WB_TRANSFER_CAB  = 1'b1 ;
 
    write_flags`INIT_WAITS   = wb_master_waits ;
    write_flags`SUBSEQ_WAITS = wb_master_waits ;
 
    wishbone_master.wb_block_write( write_flags, write_status ) ;
 
    if (write_status`CYC_ACTUAL_TRANSFER !== size_i)
    begin
        `TIME ;
        `ERROR("Burst writes must always be succesfull") ;
        $stop ;
    end
end
endtask // wb_master_single_write
 
task wb_master_single_read ;
    input [31:0] adr_i ;
    input [31:0] data_i ;
 
    reg `READ_STIM_TYPE   read_data ;
    reg `READ_RETURN_TYPE read_status ;
    reg `WB_TRANSFER_FLAGS read_flags ;
begin
    read_flags = 0 ;
    read_data  = 0 ;
 
    read_data`READ_ADDRESS = adr_i ;
    read_data`READ_SEL     = 4'hF ;
 
    read_flags`INIT_WAITS   = wb_master_waits ;
    read_flags`SUBSEQ_WAITS = wb_master_waits ;
 
    wishbone_master.wb_single_read( read_data, read_flags, read_status ) ;
 
    if (read_status`CYC_ACTUAL_TRANSFER !== 1)
    begin
        `TIME ;
        `ERROR("Single reads must always be succesfull") ;
        $stop ;
    end
 
    if (read_status`READ_DATA !== data_i)
    begin
        `TIME ;
        `INVALID_DATA("Test module") ;
        `VALUES(data_i, read_status`READ_DATA) ;
        $stop ;
    end
end
endtask // wb_master_single_read
 
task wb_master_burst_read ;
    input [31:0] size_i ;
 
    reg `READ_RETURN_TYPE read_status ;
    reg `WB_TRANSFER_FLAGS read_flags ;
begin
    read_flags = 0 ;
 
    read_flags`WB_TRANSFER_SIZE = size_i ;
    read_flags`WB_TRANSFER_CAB  = 1'b1 ;
 
    read_flags`INIT_WAITS   = wb_master_waits ;
    read_flags`SUBSEQ_WAITS = wb_master_waits ;
 
    wishbone_master.wb_block_read( read_flags, read_status ) ;
 
    if (read_status`CYC_ACTUAL_TRANSFER !== size_i)
    begin
        `TIME ;
        `ERROR("Burst reads must always be succesfull") ;
        $stop ;
    end
 
end
endtask // wb_master_burst_read
 
task wbs_check_data_with_bursts ;
    input [3:0]  pattern_select ;
    input [31:0] burst_sizes ;
 
    integer i ;
    reg [31:0] current_data ;
    reg [31:0] current_address ;
 
    reg `READ_RETURN_TYPE read_status ;
    reg `READ_STIM_TYPE   read_data ;
 
    integer j ;
begin
    current_address = 0 ;
 
    read_data          = 0 ;
    read_data`READ_SEL = 4'hF ;
 
    current_data = get_first_data(pattern_select) ;
 
    for (i = 0 ; i < 1024 ; i = i + 1)
    begin
        read_data`READ_ADDRESS = current_address ;
        wishbone_master.blk_read_data_in[i % burst_sizes] = read_data ;
 
        if ((i % burst_sizes) == (burst_sizes - 1))
        begin
            wb_master_burst_read(burst_sizes) ;
            for (j = 0 ; j <= (i % burst_sizes) ; j = j + 1)
            begin
                read_status = wishbone_master.blk_read_data_out[j] ;
                if (read_status`READ_DATA !== current_data)
                begin
                    `TIME ;
                    `INVALID_DATA("Test module") ;
                    `VALUES(current_data, read_status`READ_DATA) ;
                    $stop ;
                end
 
                current_data = get_next_data(pattern_select, current_data) ;
            end
        end
 
        current_address = current_address + 4 ;
    end
end
endtask
 
task test_slave_error_detection ;
    integer i ;
    integer current_test_size ;
    reg [10:0] offset_for_dat_err ;
    reg [10:0] offset_for_adr_err ;
 
    reg `WRITE_STIM_TYPE   write_data ;
    reg `WRITE_RETURN_TYPE write_status ;
    reg `WB_TRANSFER_FLAGS write_flags ;
 
    reg [31:0] current_start_address ;
    reg [31:0] current_start_data ;
 
    reg [31:0] current_address ;
    reg [31:0] current_data ;
 
    reg [9:0]  current_data_error_offset ;
    reg [9:0]  current_address_error_offset ;
begin
 
    write_flags = 0 ;
    write_flags`INIT_WAITS   = wb_master_waits ;
    write_flags`SUBSEQ_WAITS = wb_master_waits ;
 
    write_data  = 0 ;
 
    write_data`WRITE_SEL     = 4'hF ;
 
    for (current_test_size = 1 ; current_test_size <= 1024 ; current_test_size = current_test_size * 'd2)
    begin
 
        // select random address
        current_start_address       = $random ;
        // set the right offset in the 4KB space
        current_start_address[11:0] = ('d1024 - current_test_size) * 4 ;
        // set 13th bit to 0 to select internal rams not registers!
        current_start_address[12]   = 1'b0 ;
 
        current_start_data = $random ;
 
        current_data    = current_start_data ;
        current_address = current_start_address ;
 
        for (i = 0 ; i < current_test_size ; i = i + 1)
        begin
            write_data`WRITE_DATA    = current_data ;
            write_data`WRITE_ADDRESS = current_address ;
            wishbone_master.blk_write_data[i] = write_data ;
 
            current_data    = {current_data[30:0], current_data[31]} ;
            current_address = current_address + 4 ;
        end
 
        // put in the last write out of sequence
        write_data`WRITE_ADDRESS = current_start_address ;
        write_data`WRITE_DATA    = current_start_data ;
        wishbone_master.blk_write_data[i] = write_data ;
 
        write_flags`WB_TRANSFER_SIZE = current_test_size + 1;
 
        configure_slave_registers
        (
            current_start_address,      // start_adr
            current_start_data,         // start_dat
            current_test_size[10:0],    // test_size
            1'b1,                       // clear_burst_cnt
            1'b1                        // clear_errors
        ) ;
 
        wishbone_master.wb_block_write(write_flags, write_status) ;
        if (write_status`CYC_ACTUAL_TRANSFER !== current_test_size + 1)
        begin
            `TIME ;
            `ERROR("Block writes must always be succesfull") ;
            $stop ;
        end
 
        // now test for errors - non should be detected
        check_slave_errors
        (
            1'b0,   // expect_adr_err
            1'b0    // expect_dat_err
        ) ;
 
        // repeat same thing with one single data sequence error
        current_data_error_offset    = current_test_size - 1 ;
        write_data   = wishbone_master.blk_write_data[current_data_error_offset] ;
        current_data = write_data`WRITE_DATA ;
 
        // change the value in the data sequence
        current_data                                              = {current_data[0], current_data[31:1]} ;
        write_data`WRITE_DATA                                     = current_data ;
        wishbone_master.blk_write_data[current_data_error_offset] = write_data ;
 
        configure_slave_registers
        (
            current_start_address,      // start_adr
            current_start_data,         // start_dat
            current_test_size[10:0],    // test_size
            1'b0,                       // clear_burst_cnt
            1'b0                        // clear_errors
        ) ;
 
        write_flags`WB_TRANSFER_SIZE = current_test_size ;
 
        wishbone_master.wb_block_write(write_flags, write_status) ;
        if (write_status`CYC_ACTUAL_TRANSFER !== current_test_size)
        begin
            `TIME ;
            `ERROR("Block writes must always be succesfull") ;
            $stop ;
        end
 
        // now test for errors - data error should be detected
        check_slave_errors
        (
            1'b0,   // expect_adr_err
            1'b1    // expect_dat_err
        ) ;
 
        // repair the data
        current_data = {current_data[30:0], current_data[31]} ;
        write_data`WRITE_DATA = current_data ;
        wishbone_master.blk_write_data[current_data_error_offset] = write_data ;
 
        // repeat same thing with one single address sequence error
        current_address_error_offset = 0 ;
        write_data = wishbone_master.blk_write_data[current_address_error_offset] ;
        current_address = write_data`WRITE_ADDRESS ;
        current_address[11:2] = current_address[11:2] - 1'b1 ;
        write_data`WRITE_ADDRESS = current_address ;
        wishbone_master.blk_write_data[current_address_error_offset] = write_data ;
 
        configure_slave_registers
        (
            current_start_address,      // start_adr
            current_start_data,         // start_dat
            current_test_size[10:0],    // test_size
            1'b0,                       // clear_burst_cnt
            1'b1                        // clear_errors
        ) ;
 
        wishbone_master.wb_block_write(write_flags, write_status) ;
        if (write_status`CYC_ACTUAL_TRANSFER !== current_test_size)
        begin
            `TIME ;
            `ERROR("Block writes must always be succesfull") ;
            $stop ;
        end
 
        // now test for errors - address error should be detected
        check_slave_errors
        (
            1'b1,   // expect_adr_err
            1'b0    // expect_dat_err
        ) ;
 
        // repair the address
        current_address[11:2] = current_address[11:2] + 1'b1 ;
        write_data`WRITE_ADDRESS = current_address ;
        wishbone_master.blk_write_data[current_address_error_offset] = write_data ;        
 
 
        // repeat same thing with both errors
 
        current_data_error_offset    = 0 ;
        current_address_error_offset = current_test_size - 1;
 
        write_data = wishbone_master.blk_write_data[current_address_error_offset] ;
        current_address = write_data`WRITE_ADDRESS ;
        current_address[11:2] = current_address[11:2] + 1'b1 ;
        write_data`WRITE_ADDRESS = current_address ;
        wishbone_master.blk_write_data[current_address_error_offset] = write_data ;
 
        write_data   = wishbone_master.blk_write_data[current_data_error_offset] ;
        current_data = write_data`WRITE_DATA ;
 
        // change the value in the data sequence
        current_data                                              = {current_data[30:0], current_data[31]} ;
        write_data`WRITE_DATA                                     = current_data ;
        wishbone_master.blk_write_data[current_data_error_offset] = write_data ;
 
        configure_slave_registers
        (
            current_start_address,      // start_adr
            current_start_data,         // start_dat
            current_test_size[10:0],    // test_size
            1'b0,                       // clear_burst_cnt
            1'b1                        // clear_errors
        ) ;
 
        wishbone_master.wb_block_write(write_flags, write_status) ;
        if (write_status`CYC_ACTUAL_TRANSFER !== current_test_size)
        begin
            `TIME ;
            `ERROR("Block writes must always be succesfull") ;
            $stop ;
        end
 
        // now test for errors - address error should be detected
        check_slave_errors
        (
            1'b1,   // expect_adr_err
            1'b1    // expect_dat_err
        ) ;
 
        // now do test without errors and check if error statuses remain set
        write_data = wishbone_master.blk_write_data[current_address_error_offset] ;
        current_address = write_data`WRITE_ADDRESS ;
        current_address[11:2] = current_address[11:2] - 1'b1 ;
        write_data`WRITE_ADDRESS = current_address ;
        wishbone_master.blk_write_data[current_address_error_offset] = write_data ;
 
        write_data   = wishbone_master.blk_write_data[current_data_error_offset] ;
        current_data = write_data`WRITE_DATA ;
 
        // change the value in the data sequence
        current_data                                              = {current_data[0], current_data[31:1]} ;
        write_data`WRITE_DATA                                     = current_data ;
        wishbone_master.blk_write_data[current_data_error_offset] = write_data ;
 
        configure_slave_registers
        (
            current_start_address,      // start_adr
            current_start_data,         // start_dat
            current_test_size[10:0],    // test_size
            1'b0,                       // clear_burst_cnt
            1'b0                        // clear_errors
        ) ;
 
        wishbone_master.wb_block_write(write_flags, write_status) ;
        if (write_status`CYC_ACTUAL_TRANSFER !== current_test_size)
        begin
            `TIME ;
            `ERROR("Block writes must always be succesfull") ;
            $stop ;
        end
 
        // now test for errors - address error should be detected
        check_slave_errors
        (
            1'b1,   // expect_adr_err
            1'b1    // expect_dat_err
        ) ;
 
 
    end
end
endtask // test_slave_error_detection
 
task test_master_transaction_counts ;
    integer i ;
    reg     ok_wb ;
    reg [2:0] wait_cycles ;
    integer num_of_transactions ;
    reg [31:0] current_address ;
begin
    wait_cycles = 0 ;
    for (i = 1 ; i <= 4096 ; i = i * 2)
    begin
        if (i <= 1024)
            num_of_transactions = 1 ;
 
        if (i == 2048)
            num_of_transactions = 2 ;
 
        if (i == 4096)
            num_of_transactions = 4 ;
 
        configure_master_registers 
        (
            i / num_of_transactions,    //transaction_size
            1,                          //opcode
            0,                          //base_address
            1,                          //clear_transaction_counts
            0,                          //initiate_test
            0,                          //test size
            0                           //start_dat
        );
 
        current_address = 0 ;
        fork
        begin
            wishbone_slave.cycle_response({1'b0, 1'b0, 1'b0}, wait_cycles, 0) ;
            fork
            begin
                activate_master(num_of_transactions) ;
                wishbone_slave.cycle_response({1'b1, 1'b0, 1'b0}, wait_cycles, 0) ;
            end
                repeat (num_of_transactions)
                begin
                    wb_transaction_progress_monitor
                    (
                        current_address,            // address
                        1'b1,                       // write
                        i / num_of_transactions,    // num_of_transfers
                        1'b1,                       // check_transfers
                        ok_wb                       // ok
                    ) ;
 
                    if (ok_wb !== 1'b1)
                    begin
                        `TIME ;
                        `ERROR("Transaction progress monitor detected invalid transaction!") ;
                        $stop ;
                    end
                    current_address = current_address + 4096 ;
                end
            join
        end
        begin
            @(posedge clk) ;
            while(~wbm_cyc_o | ~wbm_stb_o | ~wbm_ack_i)
                @(posedge clk) ;
 
            repeat(2)
                @(posedge pci_clk) ;
 
            pci_irdy_reg    <= 1'b1 ;
            pci_irdy_en_reg <= 1'b1 ;
            pci_trdy_reg    <= 1'b0 ;
 
            repeat(i)
            begin
                repeat (wait_cycles)
                begin
                    @(posedge pci_clk) ;
                    pci_irdy_reg <= 1'b1 ;
                end
 
                @(posedge pci_clk) ;
                pci_irdy_reg    <= 1'b0 ;
                pci_irdy_en_reg <= 1'b1 ;
                pci_trdy_reg    <= 1'b0 ;
            end
 
            @(posedge pci_clk) ;
            pci_irdy_reg <= 1'b1 ;
        end
        join
 
        // check numbers of transactions recorded
        wb_master_single_read(32'hFFFF_F024, i) ;
        wb_master_single_read(32'h0000_1028, i) ;
 
        wait_cycles = wait_cycles + 1 ;
    end
end
endtask // test_master_transaction_counts
 
task test_master_data_errors ;
    integer i ;
    integer current_error_offset ;
    integer num_of_transfers ;
    reg [31:0] tmp ;
begin
    for (i = 1 ; i <= 4096 ; i = i * 2)
    begin
        pci_ad_reg = get_first_data(3) ;
        configure_master_registers
        (
            0,          //transaction_size
            1,          //opcode
            0,          //base_address
            1,          //clear_transaction_counts
            1,          //initiate_test
            i,          //test size
            pci_ad_reg  //start_dat
        );
 
        @(posedge pci_clk) ;
        pci_irdy_reg    <= 1'b0 ;
        pci_irdy_en_reg <= 1'b1 ;
        pci_trdy_reg    <= 1'b0 ;
 
        repeat(i)
        begin
            @(posedge pci_clk)
                pci_ad_reg <= get_next_data(3, pci_ad_reg) ;
        end
 
        pci_irdy_reg    <= 1'b0 ;
        pci_irdy_en_reg <= 1'b1 ;
        pci_trdy_reg    <= 1'b1 ;
 
        @(posedge pci_clk) ;
 
        // check for errors detected during the test
        check_master_errors(0) ;
 
        // now create an error during the simulated transfers - at first, second, one before last and last transfers
        current_error_offset = 1 ;
        while (current_error_offset <= i)
        begin
 
 
            num_of_transfers = 0 ;
            pci_ad_reg = get_first_data(2) ;
            configure_master_registers
            (
                0,          //transaction_size
                1,          //opcode
                0,          //base_address
                1,          //clear_transaction_counts
                1,          //initiate_test
                i,          //test size
                pci_ad_reg  //start_dat
            );
 
            @(posedge pci_clk) ;
 
            if ((num_of_transfers + 1) == current_error_offset)
            begin
                tmp = pci_ad_reg ;
                pci_ad_reg <= ~pci_ad_reg ;
            end
 
            pci_irdy_reg    <= 1'b0 ;
            pci_irdy_en_reg <= 1'b1 ;
            pci_trdy_reg    <= 1'b0 ;
 
            repeat(i)
            begin
                @(posedge pci_clk)
                begin
                    num_of_transfers = num_of_transfers + 1 ;
                    if (num_of_transfers == current_error_offset)
                    begin
                        pci_ad_reg <= get_next_data(2, tmp) ;
                    end
                    else if ((num_of_transfers + 1) == current_error_offset)
                    begin
                        tmp = pci_ad_reg ;
                        pci_ad_reg <= ~pci_ad_reg ;
                    end
                    else
                    begin
                        pci_ad_reg <= get_next_data(2, pci_ad_reg) ;
                    end
                end
            end
 
            pci_irdy_reg    <= 1'b0 ;
            pci_irdy_en_reg <= 1'b1 ;
            pci_trdy_reg    <= 1'b1 ;
 
            @(posedge pci_clk) ;
 
            // check for errors detected during the test
            check_master_errors(1) ;
 
            current_error_offset = current_error_offset * 2 ;
        end
    end
end
endtask // test_master_data_errors
 
function [31:0] get_next_data ;
    input [3:0]  pattern_select ;
    input [31:0] current_data ;
 
    reg [31:0] new_value ;
begin
    case (pattern_select)
        4'h0:
        begin
            new_value = current_data + 4 ;
        end
        4'h1:
        begin
            new_value = ~((~current_data) + 4) ;
        end
        4'h2, 4'h3:
        begin
            new_value = {current_data[30:0], current_data[31]} ;
        end
        4'h4:
        begin
            new_value     = current_data ;
            new_value[0]  = current_data[21] ^ current_data[5] ;
            new_value     = {new_value[30:0], new_value[31]} ;
        end
        default:
        begin
            new_value = 0 ;
        end
    endcase
 
    get_next_data = new_value ;
end
endfunction // get_next_data
 
function [31:0] get_first_data ;
    input [3:0] pattern_select ;
    reg [31:0] value ;
begin
    case (pattern_select)
        4'h0:
        begin
            value = 0 ;
        end
        4'h1:
        begin
            value = 32'hFFFF_FFFF ;
        end
        4'h2:
        begin
            value = 32'h0000_0001 ;
        end
        4'h3:
        begin
            value = 32'hFFFF_FFFE ;
        end
        4'h4:
        begin
            value = 32'hFFFF_FFFF ;
        end
        default:
        begin
            value = 0 ;
        end
    endcase
 
    get_first_data = value ;
end
endfunction // get_first_data
 
task test_master_writes ;
    integer i ;
    integer j ;
    reg [31:0] current_address ;
    reg ok_wb ;
    reg [3:0] pattern ;
    reg [3:0] wait_states ;
begin
 
    pattern = 0 ;
    wait_states = 0 ;
 
    wb_master_waits = 0 ;
 
    for (j = 1 ; j <= 1024 ; j = j * 2)
    begin
 
        current_address = j * 4 ;
 
        // configure registers to enable master writes
        configure_master_registers(j, 1, current_address, 1'b0, 1'b0, 0, 0) ;
 
        // fill block rams with patterns
        wbs_fill_with_bursts(pattern, j) ;
 
        // deactivate slave
        wishbone_slave.cycle_response(0, 0, 0) ;
 
        fork
        begin
            // activate_master
            activate_master('d1024 / j) ;
 
            // enable slave
            wishbone_slave.cycle_response({1'b1, 1'b0, 1'b0}, wait_states, 0) ;
        end
        begin
            for (i = 0 ; i < ('d1024 / j) ; i = i + 1) 
            begin
                wb_transaction_progress_monitor
                (
                    current_address,    // address
                    1'b1,               // write
                    j,                  // num_of_transfers
                    1'b1,               // check_transfers
                    ok_wb               // ok
                ) ;
 
                if (ok_wb !== 1'b1)
                begin
                    `TIME ;
                    `ERROR("Transaction progress monitor detected invalid transaction!") ;
                    $stop ;
                end
                current_address = current_address + (j * 4) ;
            end
        end
        join
 
        // check the data
        current_address = get_first_data(pattern) ;
        for (i = 0 ; i < j ; i = i + 1)
        begin
            current_address = get_next_data(pattern, current_address) ;
        end
 
        for (i = 0 ; i < 1024 ; i = i + 1)
        begin
            if ((i + j) == 1024)
                current_address = get_first_data(pattern) ;
 
            if (wishbone_slave.wb_memory[i + j] !== current_address)
            begin
                `TIME ;
                `ERROR("Test Master written wrong data value to the slave") ;
                `VALUES(current_address, wishbone_slave.wb_memory[i]) ;
                $stop ;
            end
 
            current_address = get_next_data(pattern, current_address) ;
        end
 
        pattern = pattern + 1 ;
        if (pattern > 4)
            pattern = 0 ;
 
        wait_states = wait_states + 1 ;
        wb_master_waits = wb_master_waits + 1 ;
    end
 
    wb_master_waits = 0 ;
end
endtask // test_master_writes
 
task test_master_reads ;
    integer i ;
    integer j ;
    reg [31:0] current_address ;
    reg ok_wb ;
    reg [3:0] pattern ;
    reg [3:0] wait_states ;
begin
 
    pattern = 0 ;
    wait_states = 0 ;
 
    wb_master_waits = 0 ;
 
    for (j = 1 ; j <= 1024 ; j = j * 2)
    begin
 
        current_address = j * 4 ;
 
        // configure registers to enable master reads
        configure_master_registers(j, 0, current_address, 1'b0, 1'b0, 0, 0) ;
 
        current_address = get_first_data(pattern) ;
        for (i = 0 ; i < j ; i = i + 1)
        begin
            current_address = get_next_data(pattern, current_address) ;
        end
 
        // fill slave memory with patterns
        for (i = j ; i < (1024 + j) ; i = i + 1)
        begin
            if (i == 1024)
                current_address = get_first_data(pattern) ;
 
            wishbone_slave.wb_memory[i] = current_address ;
            current_address = get_next_data(pattern, current_address) ;
        end
 
        // deactivate slave
        wishbone_slave.cycle_response(0, 0, 0) ;
 
        current_address = j * 4 ;
 
        fork
        begin
            // activate_master
            activate_master('d1024 / j) ;
 
            // enable slave
            wishbone_slave.cycle_response({1'b1, 1'b0, 1'b0}, wait_states, 0) ;
        end
        begin
            for (i = 0 ; i < ('d1024 / j) ; i = i + 1) 
            begin
                wb_transaction_progress_monitor
                (
                    current_address,    // address
                    1'b0,               // write
                    j,                  // num_of_transfers
                    1'b1,               // check_transfers
                    ok_wb               // ok
                ) ;
 
                if (ok_wb !== 1'b1)
                begin
                    `TIME ;
                    `ERROR("Transaction progress monitor detected invalid transaction!") ;
                    $stop ;
                end
                current_address = current_address + (j * 4) ;
            end
        end
        join
 
        // check the data
        wbs_check_data_with_bursts(pattern, j) ;
 
        pattern = pattern + 1 ;
        if (pattern > 4)
            pattern = 0 ;
 
        wait_states = wait_states + 1 ;
        wb_master_waits = wb_master_waits + 1 ;
    end
 
    wb_master_waits = 0 ;
end
endtask // test_master_reads
 
task configure_master_registers ;
    input [10:0] transaction_size ;
    input        opcode ;
    input [31:0] base_address ;
    input        clear_transaction_counts ;
    input        initiate_test ;
    input [20:0] test_size ;
    input [31:0] start_dat ;
begin
    // write transaction size
    wb_master_single_write(32'h0000_1000, {21'h1FFF_FF, transaction_size}) ;
    wb_master_single_read (32'hFFFF_F000, {21'h0000_00, transaction_size}) ;
 
    // write opcode
    wb_master_single_write(32'h0000_1008, {31'h7FFF_FFFF, opcode}) ;
    wb_master_single_read (32'hFFFF_F008, {31'h0000_0000, opcode}) ;
 
    // write base address
    wb_master_single_write(32'h0000_100C, base_address) ;
    wb_master_single_read (32'hFFFF_F00C, {base_address[31:2], 2'b00}) ;
 
    // if clear of wb and pci transaction counters is requested clear them
    if (clear_transaction_counts)
    begin
        wb_master_single_write(32'hFFFF_F024, 32'hFFFF_FFFF) ;
        repeat(3)
            @(posedge pci_clk) ;
 
        wb_master_single_read(32'h0000_1024, 32'h0) ;
        wb_master_single_read(32'h0000_1028, 32'h0) ;
    end
 
    if (initiate_test)
    begin
        wb_master_single_write(32'hFFFF_F030, start_dat) ;
        wb_master_single_read(32'h0000_1030, start_dat) ;
 
        wb_master_single_write(32'hFFFF_F02C, {11'h0, test_size}) ;
        wb_master_single_read(32'h0000_102C, {11'h0, test_size}) ;
 
        repeat(2)
            @(posedge pci_clk) ;
 
        repeat(2)
            @(posedge clk) ;
 
        // check the write - it should not be succesfull, since test is not done yet
        wb_master_single_write(32'hFFFF_F02C, 0) ;
 
        wb_master_single_read(32'h0000_102C, {11'h0, test_size}) ;
 
        // all reported errors should be cleared by now!
        wb_master_single_read(32'h0000_1034, 32'h0) ;
    end
end
endtask // configure_master_registers
 
task configure_slave_registers ;
    input [31:0] start_adr ;
    input [31:0] start_dat ;
    input [10:0] test_size ;
    input        clear_burst_cnt ;
    input        clear_errors ;
begin
    if (clear_burst_cnt)
    begin
        wb_master_single_write(32'h0000_1010, 32'hFFFF_FFFF) ;
        wb_master_single_read (32'hFFFF_F010, 32'h0) ;
    end
 
    if (clear_errors)
    begin
        wb_master_single_write(32'h0000_1020, 32'hFFFF_FFFF) ;
        wb_master_single_read (32'hFFFF_F020, 32'h0        ) ;
    end
 
 
    wb_master_single_write(32'h0000_1018, start_adr) ;
    wb_master_single_read (32'hFFFF_F018, start_adr) ;
 
    wb_master_single_write(32'h0000_101C, start_dat) ;
    wb_master_single_read (32'hFFFF_F01C, start_dat) ;
 
    wb_master_single_write(32'h0000_1014, {21'h1F_FFFF, test_size}) ;
    wb_master_single_read (32'hFFFF_F014, {21'h0, test_size}) ;
 
end
endtask // configure_slave_registers
 
task check_slave_errors ;
    input expect_adr_err ;
    input expect_dat_err ;
begin
    wb_master_single_read (32'hFFFF_F020, {30'h0, expect_adr_err, expect_dat_err}) ;
end
endtask // check_slave_errors
 
task check_master_errors ;
    input expect_dat_err ;
begin
    wb_master_single_read(32'h0000_1034, {31'h0, expect_dat_err}) ;
end
endtask // check_master_errors
 
task activate_master ;
    input [10:0] num_of_transactions ;
begin
    wb_master_single_write(32'h0000_1004, {21'h1FFF_FF, num_of_transactions}) ;
    wb_master_single_read (32'hFFFF_F004, {21'h0000_00, num_of_transactions}) ;
end
endtask // activate_master
 
reg wbm_cyc_o_previous ;
 
always@(posedge clk)
    wbm_cyc_o_previous <= wbm_cyc_o ;
 
task wb_transaction_progress_monitor ;
    input [31:0] address ;
    input        write ;
    input [31:0] num_of_transfers ;
    input check_transfers ;
    output ok ;
    reg in_use ;
    integer deadlock_counter ;
    integer transfer_counter ;
    integer deadlock_max_val ;
    reg [2:0] slave_termination ;
    reg       cab_asserted ;
begin:main
    if ( in_use === 1 )
    begin
        $display("wb_transaction_progress_monitor task re-entered! Time %t ", $time) ;
        ok = 0 ;
        disable main ;
    end
 
    // number of cycles on WB bus for maximum transaction length
    deadlock_max_val = 50 ;
 
    in_use       = 1 ;
    ok           = 1 ;
    cab_asserted = 0 ;
 
    fork
    begin:wait_start
        deadlock_counter = 0 ;
        @(posedge clk) ;
        while ( (wbm_cyc_o !== 0 && wbm_cyc_o_previous !== 0) && (deadlock_counter < deadlock_max_val) )
        begin
        	if ((!wbm_stb_o) || (!wbm_ack_i))
            	deadlock_counter = deadlock_counter + 1 ;
            else
            	deadlock_counter = 0;
            @(posedge clk) ;
        end
        if ( wbm_cyc_o !== 0 && wbm_cyc_o_previous !== 0)
        begin
            $display("wb_transaction_progress_monitor task waited for 50 cycles for previous transaction to complete! Time %t ", $time) ;
            in_use = 0 ;
            ok     = 0 ;
            disable main ;
        end
 
        deadlock_counter = 0 ;
        while ( (wbm_cyc_o !== 1) && (deadlock_counter < deadlock_max_val) )
        begin
            deadlock_counter = deadlock_counter + 1 ;
            @(posedge clk) ;
        end
 
        if ( wbm_cyc_o !== 1 )
        begin
            $display("wb_transaction_progress_monitor task waited for 50 cycles for transaction to start! Time %t ", $time) ;
            in_use = 0 ;
            ok     = 0 ;
            disable main ;
        end
    end //wait_start
    begin:addr_monitor
        @(posedge clk) ;
        while ( wbm_cyc_o !== 0 && wbm_cyc_o_previous !== 0)
            @(posedge clk) ;
 
        while( wbm_cyc_o !== 1 )
            @(posedge clk) ;
 
        while (wbm_stb_o !== 1 )
            @(posedge clk) ;
 
        if ( wbm_we_o !== write )
        begin
            $display("wb_transaction_progress_monitor detected unexpected transaction on WB bus! Time %t ", $time) ;
            if ( write !== 1 )
                $display("Expected read transaction, wbm_we_o signal value %b ", wbm_we_o) ;
            else
                $display("Expected write transaction, wbm_we_o signal value %b ", wbm_we_o) ;
        end
 
        if ( wbm_adr_o !== address )
        begin
            $display("wb_transaction_progress_monitor detected unexpected address on WB bus! Time %t ", $time) ;
            $display("Expected address = %h, detected address = %h ", address, wbm_adr_o) ;
            ok = 0 ;
        end
    end
    begin:transfer_checker
        transfer_counter = 0 ;
        @(posedge clk) ;
        while ( wbm_cyc_o !== 0 && wbm_cyc_o_previous !== 0)
            @(posedge clk) ;
 
        while( wbm_cyc_o !== 1 )
            @(posedge clk) ;
 
        while( (wbm_cyc_o === 1) && (transfer_counter <= 1024) )
        begin
 
            if (!cab_asserted)
                cab_asserted = (wbm_cab_o !== 1'b0) ;
 
            if (wbm_stb_o === 1)
            begin
                slave_termination = {wbm_ack_i, wbm_err_i, wbm_rty_i} ;
                if (wbm_ack_i)
                    transfer_counter = transfer_counter + 1 ;
            end
            @(posedge clk) ;
        end
 
        if (cab_asserted)
        begin
            // cab was sampled asserted
            // if number of transfers was less than 2 - check for extraordinary terminations
            if (transfer_counter < 2)
            begin
                // if cycle was terminated because of no response, error or retry, than it is OK to have CAB_O asserted while transfering 0 or 1 data.
                // any other cases are wrong
                case (slave_termination)
                3'b000:begin end
                3'b001:begin end
                3'b010:begin end
                default:begin
                            ok = 0 ;
                            $display("Time %t", $time) ;
                            $display("WB_MASTER asserted CAB_O for single transfer") ;
                        end
                endcase
            end
        end
        else
        begin
            // if cab is not asserted, then WB_MASTER should not read more than one data.
            if (transfer_counter > 1)
            begin
                ok = 0 ;
                $display("Time %t", $time) ;
                $display("WB_MASTER didn't assert CAB_O for consecutive block transfer") ;
            end
        end
 
        if ( check_transfers === 1 )
        begin
            if ( transfer_counter !== num_of_transfers )
            begin
                $display("wb_transaction_progress_monitor detected unexpected transaction! Time %t ", $time) ;
                $display("Expected transfers in transaction = %d, actual transfers = %d ", num_of_transfers, transfer_counter) ;
                ok = 0 ;
            end
        end
    end //transfer_checker
    join
 
    in_use = 0 ;
end
endtask // wb_transaction_progress_monitor
 
endmodule // test_bench
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.