veriloghdlmodelsimtest-benchalu

ALU test bench using test vector file not working


I'm new to this, and the question might seem silly, but I've spent hours on this and the test bench just doesn't want to load the right values into the register before performing the arithmetic.

Here's what happens when I go to run the simulation

# [         0]Success: inputs: a=00000000 | b=00000000 | f=0
#       outputs: y=00000000 | y_ex=00000000 | zero=1
# [         1]Error: inputs: a=00000007 | b=ffffffff | f=0
#       outputs: y=00000007 | y_ex=fffffff8 | zero=0
# [         2]Error: inputs: a=0000000f | b=fffffff8 | f=0
#       outputs: y=00000008 | y_ex=00000000 | zero=1
# [         3]Error: inputs: a=000007f8 | b=00000008 | f=0
#       outputs: y=00000008 | y_ex=00000800 | zero=0
# [         4]Success: inputs: a=00000000 | b=00000000 | f=0
#       outputs: y=00000000 | y_ex=00000000 | zero=1
# [         5]Error: inputs: a=00000007 | b=fffffff8 | f=0
#       outputs: y=00000000 | y_ex=00000008 | zero=0
# [         6]Error: inputs: a=00000008 | b=00000008 | f=0
#       outputs: y=00000008 | y_ex=00000000 | zero=0
# [         7]Error: inputs: a=00000800 | b=00000008 | f=0
#       outputs: y=00000000 | y_ex=000007f8 | zero=1
#          8 tests completed with          6 errors

As you can see, the f values, which are used to specify which operation the ALU will perform, are always wrong. The a and b values are read wrong as well. The reading seems to happen fine though. I tested that already.

Here's my ALU code

module alu(input logic [31:0] a, b,
            input logic [2:0] f,
            output logic [31:0] y,
            output logic zero
    );
    
    always @*
    begin
        if (f == 3'h0) //AND
            y = a & b;
        else if (f == 3'h1) //OR
            y = a | b;
        else if (f == 3'h2) //ADD
            y = a + b;      
        else if (f == 3'h4) //AND NOT
            y = a & ~b;
        else if (f == 3'h5) //OR NOT
            y = a | ~b;
        else if (f == 3'h6) //SUBTRACT
            y = a - b;
        else if (f == 3'h7) //SET LESS THEN
            y =(a<b)?32'h00000001:32'h00000000;
        begin   
            if (y == 32'h00000000)
                zero = 1;
            else 
                zero = 0;
        end
    end 
endmodule

Test Bench Code

module testbench();
    logic clk;
    logic [31:0] a, b;
    logic [2:0] f;
    logic [31:0] y;
    logic zero;
    logic [31:0] y_ex;
    logic [31:0] vectornum, errors;
    logic [103:0] testvectors[10000:0];
    
    alu dut(a, b, f, y, zero);
    
    always 
        begin
            clk = 1; #5; clk = 0; #5;
        end
        
    initial 
        begin 
            $readmemh("alu.tv", testvectors); //f,a,b, y_ex, zero
            vectornum = 0; errors = 0;
        end
        
    always @(posedge clk)
        begin
            #1; {f, a, b, y_ex, zero} = testvectors[vectornum];
        end
        
    always @(negedge clk) begin
            if (y == y_ex) begin 
                $display("[%d]Success: inputs: a=%h | b=%h | f=%h",vectornum, a, b, f);
                $display("      outputs: y=%h | y_ex=%h | zero=%b", y, y_ex, zero);
            end
            else if (y !== y_ex) begin
                $display("[%d]Error: inputs: a=%h | b=%h | f=%h", vectornum, a, b, f);
                $display("      outputs: y=%h | y_ex=%h | zero=%b", y, y_ex, zero);
                errors = errors + 1;
            end
            vectornum = vectornum + 1;
            if (testvectors[vectornum] === 104'bx) begin
                $display("%d tests completed with %d errors", vectornum, errors);
        $stop;
            end
end
    endmodule

Vector File

2_00000000_00000000_00000000_1
2_00000000_FFFFFFFF_FFFFFFFF_0
2_00000001_FFFFFFFF_00000000_1
2_000000FF_00000001_00000100_0
6_00000000_00000000_00000000_1
6_00000000_FFFFFFFF_00000001_0
6_00000001_00000001_00000000_1
6_00000100_00000001_000000FF_0

What am I doing wrong? Would greatly appreciate the help.


Solution

  • You can't rely on _ to separate each line into 5 numbers. This 2_00000000_FFFFFFFF_FFFFFFFF_0 is one 104-bit hexadecimal number.

    When executing {f, a, b, y_ex, zero} = testvectors[1];, it actually does:

    hex |  bin  |   hex   |  bin  |   hex   |  bin  |   hex   |  bin
     2  | 000 0 | 0000000 | 111 1 | FFFFFFF | 111 1 | FFFFFFF | 000 0
     |    --- ----------------- ----------------- ----------------- -
     |     f          a                  b               y_ex       zero
     |    3'h0      32'h7          32'hffff_ffff    32'hffff_fff8   0
     V
     not used
    

    You need to specify range when assigning:

    assign tmp = testvectors[vectornum];
    assign zero = tmp[...];
    assign y_ex = tmp[...];
    

    Or change the bit width declaration of zero/y_ex/..., like what @Serge mentioned in the comment.

    There's another issue. The zero net in testbench is driven by both alu's zero output, and always block in testbench.