Search code examples
verilogsystem-verilogtest-bench

How to create an array to store integers in a testbench?


I'm going through all my Verilog modules and creating good testbenches for them. I already finished the larger project, but I want to get better at writing testbenches as well as upload the testbenches to the project repository.

I have the following code for a testbench that tests a module I have. This module takes a 16-bit input, trims it down to 10 bits (data input from an accelerometer, only 10 bits are used but the input is 16 bits for consistency), then converts the 10 bit signed number into decimal by outputting the number of ones, tens, hundreds, and thousands.

This is the code I have for the testbench (Note: Decimal_Data represents the "usable" 10 bits of data):

module Binary_to_Decimal_TB();

reg [15:0] Accel_Data = 16'd0;

wire [3:0] ones;
wire [3:0] tens;
wire [3:0] hundreds;
wire [3:0] thousands;
wire negative;

wire [9:0] Decimal_Data;

integer i;

integer j = 0;

Binary_to_Decimal BtD (
    .Accel_Data(Accel_Data), .Decimal_Data(Decimal_Data),
    .ones(ones), .tens(tens), .hundreds(hundreds), .thousands(thousands), 
    .negative(negative)
); 

initial
begin
    for (i = 0; i < 2047; i = i + 1)
    begin
        Accel_Data = i;
        #2;
        if (Decimal_Data < 512)
        begin
            if (((ones * 1) + (tens * 10) + (hundreds * 100) + (thousands * 1000)) != 4 * Decimal_Data)
                j = j + 1;
        end
        else if (Decimal_Data == 512)
        begin
            if (((ones * 1) + (tens * 10) + (hundreds * 100) + (thousands * 1000)) != 0)
                j = j + 1;
        end
        else
        begin
            if (((ones * 1) + (tens * 10) + (hundreds * 100) + (thousands * 1000)) != 2048 - (4 * (Decimal_Data - 512)))
                j = j + 1;   
        end
    end
    $display("Conversion mismatches:", j);
    $finish;
end
endmodule

It works as it should, and I get zero mismatches between the numbers represented by the converted data, and the original 2's complement 10-bit number.

However, I want to write it so that if there were an error, it would save the binary number where there is a mismatch between the input and output. In C++, I'd create an array, and dynamically allocate it with the binary numbers where a mismatch is detected (since we don't know how many mismatches there would be if the design were faulty).

More clearly, right now I can see how many mismatch errors occur. I want to implement a way to see where the errors occur

I know I'd write to the array in the conditional where I increment j, but I don't know how to create an array that's used for this purpose in Verilog.

Also, I've heard SystemVerilog is better for verification, so maybe there's something in SystemVerilog that I could use to accomplish this? I haven't really looked into SystemVerilog, but I do want to learn it.


Solution

  • In SystemVerilog you can create a queue, which is dynamic, to store the mismatched results.

    logic [15:0] mismatches [$];
    ...
            if (Decimal_Data < 512)
            begin
                if (((ones * 1) + (tens * 10) + (hundreds * 100) + (thousands * 1000)) !== 4 * Decimal_Data) begin
                    j = j + 1;
                    mismatches.push_back(Accel_Data);
                end
            end
    ...
        $display("Conversion mismatches:", j);
        foreach (mismatches[i]) $display(mismatches[i]);
        $finish;
    

    Refer to IEEE Std 1800-2017, section 7.10 Queues.


    Since you are comparing 4-state values, you should use the case inequality operator (!==), as I have shown above. Furthermore, since you are comparing your DUT outputs to each other, you should also check if there are x or z values using $isunknown.

    Also, there is common code in your testbench which can be combined. This is especially important as you add more checking code. For example:

    logic [15:0] mismatches [$];
    integer expect_data;
    
    initial
    begin
        for (i = 0; i < 2047; i = i + 1)
        begin
            Accel_Data = i;
            #2;
    
            if (Decimal_Data < 512)
            begin
                expect_data = 4 * Decimal_Data;
            end
            else if (Decimal_Data == 512)
            begin
                expect_data = 0;
            end
            else
            begin
                expect_data = 2048 - (4 * (Decimal_Data - 512));
            end
    
            if (((ones * 1) + (tens * 10) + (hundreds * 100) + (thousands * 1000)) !== expect_data) begin
                j = j + 1;
                mismatches.push_back(Accel_Data);
            end
        end
        $display("Conversion mismatches:", j);
        foreach (mismatches[i]) $display(mismatches[i]);
        $finish;
    end
    endmodule