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.
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
.