cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor
Visitor
352 Views
Registered: ‎02-12-2020

Behavioral Simulation Incorrect Value Checking Results During ALU Testing

Currently trying to test and verify correct behavior with an ALU design that performs 6 possible operations. 

module alu_8 (input [7:0] A,
               input [7:0] B,
               input [3:0] ALUCtl,
               output Zero,
               output reg [7:0] Result,
               output reg Overflow,
               output reg CarryOut);
    
    wire aSign, bSign;
    assign aSign = A[7];
    assign bSign = B[7];
    assign Zero = (Result == 8'd0);
    always @(ALUCtl, A, B) begin
        Overflow = 0;
        case(ALUCtl)
        4'b0000: Result <= A & B;
        4'b0001: Result <= A | B;
        4'b0010: begin
            {CarryOut, Result} <= A + B;
        end
        4'b0110: begin
            {CarryOut, Result} <= A + (~B + 1);
            CarryOut <= (A < B);
        end
        4'b0111: Result <= A < B ? 8'd1 : 8'd0;
        4'b1100: Result <= ~(A | B);
        default: Result <= 0; 
        
        endcase
    end
endmodule

I took out logic pertaining to overflow because it is not relevant to what I am testing at the moment. I created a testbench for this module with a clock that inverts it's value every 2 time units. I created the A and B operands and set the ALU control manually; the control changes after time delays to go through every ALU operation. At the posedge of the clock, one or both of the operands will change and the ALU will perform it's operation on A and B and store the result in a register. Also on the posedge, the testbench will check the result from the ALU to check if it is the correct output. This is where the behavior becomes unexpected. 

always @ (posedge clock) begin
        case(ALUCtl)                    // ALU control
... 4'b0001: begin // check if the result wire passed to the ALU has the correct // value from the operation if (Result != (A | B)) begin testFail <= 1'd1; // set the test fail indicator to 1 end end
...

An example of this not performing correctly is when A = 0xa8 and B = 0x61, Result holds the value 0xe9 because the ALU perform 0xa8 OR 0x61 (which is correct). But the logical statement Result != A | B returns true and the test fail is set. 

TestFail Set When Result Has Correct ValueTestFail Set When Result Has Correct Value

 

This is the complete testbench:

`timescale 1ns/1ns
module alu_8_testbench();
    reg clock;
    initial clock = 0;
    always #(2) clock <= ~clock;
    
    wire[3:0] ALUCtl;
    reg[3:0] ALUCtlReg = 4'b0000;
    assign ALUCtl = ALUCtlReg;
        
    wire [7:0] A, B, Result;
    reg [15:0] operands = 16'd0;
    assign A = operands[7:0];        // A gets lower bits
    assign B = operands[15:8];       // B gets upper bits
    wire Zero, Overflow, CarryOut;
    reg testFail = 1'd0;
    reg testZero = 1'd0;
    
    alu_8 alu(
        .A(A),
        .B(B),
        .ALUCtl(ALUCtl),
        .Zero(Zero),
        .Result(Result),
        .Overflow(Overflow),
        .CarryOut(CarryOut)
        );
        
    always @ (posedge clock) begin
        operands <= operands + 1'd1;
    end

    always @ (posedge clock) begin
        case(ALUCtl)
        4'b0000: begin
            if (Result != (A & B)) begin
                testFail <= 1'd1;
            end
        end
        4'b0001:  begin
            if (Result != (A | B)) begin
                testFail <= 1'd1;
            end
        end
        4'b0010: begin
            if ({CarryOut, Result} != A + B )
            begin
                testFail <= 1'd1;
            end
        end
        4'b0110: begin
            if ({CarryOut, Result} != A + (~B + 1) )
             begin
                testFail <= 1'd1;
            end
        end
        4'b0111: begin
            if (Result != A < B ? 8'd1 : 8'd0) begin
                testFail <= 1'd1;
            end
        end
        4'b1100: begin
            if (Result != ~(A | B)) begin
                testFail <= 1'd1;
            end
        end
        endcase
        testZero <= ((Result == 8'd0) && !Zero) || ((Result != 8'd0) && Zero);
    end
    initial begin
        #100_000;
        testFail = 1'd0;
        ALUCtlReg = 4'b0001;
        #100_000;
        testFail = 1'd0;
        ALUCtlReg = 4'b0010;
        #100_000;
        testFail = 1'd0;
        ALUCtlReg = 4'b0110;
        #100_000;
        testFail = 1'd0;
        ALUCtlReg = 4'b0111;
        #100_000;
        testFail = 1'd0;
        ALUCtlReg = 4'b1100;
        #100_000;
        $finish();
    end
endmodule

What could be causing this behavior? 

0 Kudos
7 Replies
Highlighted
Voyager
Voyager
346 Views
Registered: ‎06-28-2018

Re: Behavioral Simulation Incorrect Value Checking Results During ALU Testing

Hi @marascax 

The answer is here.

0 Kudos
Highlighted
Visitor
Visitor
328 Views
Registered: ‎02-12-2020

Re: Behavioral Simulation Incorrect Value Checking Results During ALU Testing

Hello @baltintop ,

 

I do not quite get what you mean. I am using the bitwise OR operator | on A and B (A | B), and using that to check if Result has that value as well. If Result != (A | B) returns true, then result does not have the correct value. In the example I listed, Result does have the correct value, but the error check is still passing true.

0 Kudos
Highlighted
Voyager
Voyager
322 Views
Registered: ‎06-28-2018

Re: Behavioral Simulation Incorrect Value Checking Results During ALU Testing

Hi @marascax 

Sorry, I was misled by your sentence


But the logical statement Result != A | B returns true and the test fail is set.

I thought this was the case in your code.

0 Kudos
Highlighted
Voyager
Voyager
304 Views
Registered: ‎06-28-2018

Re: Behavioral Simulation Incorrect Value Checking Results During ALU Testing

@marascax 

In the testbench, testFail is driven on the positive edge but on the waveform its value changes on the negative edge. This indicates an error in the testbench.

Your mistake is that you're driving testFail inside both the initial and always block. Those blocks are executed in parallel. You should only initialize it inside the initial block (at time #0) if you're gonna use it inside an always block.

0 Kudos
Highlighted
Visitor
Visitor
284 Views
Registered: ‎02-12-2020

Re: Behavioral Simulation Incorrect Value Checking Results During ALU Testing

@baltintop

Oh shoot, I forgot to reset a change I made to the testbench while trying to fix this. I tried running the result check on the negedge but the same problem kept happening. I took the screenshot while running it on the negedge check. Here's it on the posedge check. This is when it is adding A and B, the sum is 0x181 so Result gets 0x81 and the carry-out bit set, but it is still failing.

 

My apologies!

 

behavior2.PNG

0 Kudos
Highlighted
Voyager
Voyager
273 Views
Registered: ‎06-28-2018

Re: Behavioral Simulation Incorrect Value Checking Results During ALU Testing

Hi @marascax 

Can you post a waveform where I can see the clock transitions for at least a few clock cycles?

0 Kudos
Highlighted
Voyager
Voyager
261 Views
Registered: ‎06-28-2018

Re: Behavioral Simulation Incorrect Value Checking Results During ALU Testing

@marascax 

Either drive ALU Result inside an always @(*) block and use blocking assignments or do the comparison at the right time in your testbench. I think you're off by one clock cycle.

0 Kudos