FPGA-RISC-V-CPU / hardware / sim / cache_tb.v
cache_tb.v
Raw
`timescale 1ns/1ns
`define CLK_PERIOD 8

module cache_tb();

    localparam ADDR_WIDTH = 30;
    localparam DATA_WIDTH = 8;
    localparam LINES = 8;
    
    reg clk = 0;
    always #(`CLK_PERIOD/2) clk = ~clk;

    reg rst;
    reg [ADDR_WIDTH-1:0] ra0;
    reg [ADDR_WIDTH-1:0] ra1;

    reg [DATA_WIDTH-1:0] dout0;
    reg [DATA_WIDTH-1:0] dout1;

    reg hit0;
    reg hit1;

    reg [ADDR_WIDTH-1:0] wa;
    reg [DATA_WIDTH-1:0] din;
    reg we;

    bp_cache #(
        .AWIDTH(ADDR_WIDTH),
        .DWIDTH(DATA_WIDTH),
        .LINES(LINES)
    ) cache (
        .clk(clk),
        .reset(rst),
        .ra0(ra0),
        .ra1(ra1),
        .wa(wa),
        .din(din),
        .we(we),
        .hit0(hit0),
        .dout0(dout0),
        .hit1(hit1),
        .dout1(dout1)
    );

    initial begin
        `ifndef IVERILOG
            $vcdpluson;
        `endif
        `ifdef IVERILOG
            $dumpfile("cache_tb.fst");
            $dumpvars(0, cache_tb);
        `endif

        rst = 1;
        @(posedge clk); #1;
        rst = 0;

        repeat (5) @(negedge clk);

        // Test read0, compulsory miss
        ra0 = 30'b0;
        ra1 = 30'b1;
        wa = 30'b0;
        din = 2'b0;
        we = 1'b0;
        #(2*`CLK_PERIOD)
        assert(hit0 == 0) else $display("ERROR: %d", hit0);

        // Test read1, compulsory miss
        ra0 = 1;
        ra1 = 0;
        wa = 0;
        din = 0;
        we = 0;
        #(2*`CLK_PERIOD)
        assert(hit1 == 0) else $display("ERROR: %d", hit1);

        // Test write, read at the same time
        ra0 = 0;
        ra1 = 1;
        wa = 0;
        din = 1;
        we = 1;
        #(4*`CLK_PERIOD)
        assert(dout0 == 1) else $display("ERROR: %d", dout0);
        assert(hit0 == 1) else $display("ERROR: %d", hit0);
        assert(hit1 == 0) else $display("ERROR: %d", hit1);

        // test read miss and hit on 0 and 1
        ra0 = 1;
        ra1 = 0;
        wa = 0;
        din = 0;
        we = 0;
        #(2*`CLK_PERIOD)
        assert(dout1 == 1) else $display("ERROR: %d", dout1);
        assert(hit0 == 0) else $display("ERROR: %d", hit0);
        assert(hit1 == 1) else $display("ERROR: %d", hit1);

        // test cache invalidation
        rst = 1;
        @(posedge clk); #1;
        rst = 0;
        ra0 = 0;
        ra1 = 1;
        wa = 0;
        din = 0;
        we = 0;
        #(2*`CLK_PERIOD)
        assert(hit0 == 0) else $display("ERROR: %d", hit0);
        assert(hit1 == 0) else $display("ERROR: %d", hit1);

        // test cache same index, different tag
        ra0 = 0;
        ra1 = 0;
        wa = 0'b00000000000000000000000000001111;
        din = 2;
        we = 1;
        #(2*`CLK_PERIOD)
        assert(hit0 == 0) else $display("ERROR: %d", hit0);
        assert(hit1 == 0) else $display("ERROR: %d", hit1);

        // same index (111) and different tag (0)
        ra0 = 0'b00000000000000000000000000000111;
        ra1 = 0;
        wa = 0;
        din = 0;
        we = 0;
        #(2*`CLK_PERIOD)
        assert(hit0 == 0) else $display("ERROR: %d", hit0); // should not hit
        assert(hit1 == 0) else $display("ERROR: %d", hit1);

        // same index (111) and different tag (0)
        ra0 = 0;
        ra1 = 0'b00000000000000000000000000000111;
        wa = 0;
        din = 0;
        we = 0;
        #(2*`CLK_PERIOD)
        assert(hit0 == 0) else $display("ERROR: %d", hit0); // should not hit
        assert(hit1 == 0) else $display("ERROR: %d", hit1);


        

        $display("PASSED!");
        $finish();
    end
endmodule