cancel
Showing results for
Show  only  | Search instead for
Did you mean:
Visitor
602 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 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?

7 Replies
Voyager
596 Views
Registered: ‎06-28-2018

Visitor
578 Views
Registered: ‎02-12-2020

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.

Voyager
572 Views
Registered: ‎06-28-2018

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.

Voyager
554 Views
Registered: ‎06-28-2018

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.

Visitor
534 Views
Registered: ‎02-12-2020

@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!

Voyager
523 Views
Registered: ‎06-28-2018

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

Voyager
511 Views
Registered: ‎06-28-2018

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.