I'm just starting to write verilog, and I try to implement a MAC which include a 8-bits unsigned modified Booth multiplier, but I encountered some errors when my input is -128. How can I solve this issue?
Below is my code
module MAC(
input [7:0] ifmap, // Input feature map
input [7:0] filter, // Filter
input [23:0] psum, // Partial sum
output reg [23:0] updated_psum // Updated partial sum
);
reg [15:0] p, ans;
reg [7:0] neg_ifmap;
reg [23:0] prod;
integer i, lookup_tbl, operate;
initial begin
p = 16'b0;
ans = 16'b0;
// Two's complement of a negative number
assign neg_ifmap = (~ifmap) + 1;
end
always @(*) begin
p = 16'b0;
for (i = 1; i <= 7; i = i + 2) begin
if (i == 1)
lookup_tbl = 0;
else
lookup_tbl = filter[i-2];
lookup_tbl = lookup_tbl + 4*filter[i] + 2*filter[i-1];
if (lookup_tbl == 0 || lookup_tbl == 7)
operate = 0;
else if (lookup_tbl == 3 || lookup_tbl == 4)
operate = 2;
else
operate = 1;
if (filter[i] == 1)
operate = -1*operate;
case (operate)
1: begin
ans = {{8{ifmap[7]}}, ifmap};
ans = ans << (i-1);
p = p + ans;
end
2: begin
ans = {{8{ifmap[7]}}, ifmap} << 1;
ans = ans << (i-1);
p = p + ans;
end
-1: begin
ans = {{8{neg_ifmap[7]}}, neg_ifmap};
ans = ans << (i-1);
p = p + ans;
end
-2: begin
ans = {{8{neg_ifmap[7]}}, neg_ifmap} << 1; // negative a
ans = ans << (i - 1);
p = p + ans;
end
endcase
end
prod = {{8{p[15]}}, p};
updated_psum <= prod + psum;
end
endmodule
Below is my testbench
`include "MAC.v"
module MAC_tb;
reg signed [7:0] a;
reg signed [7:0] b;
reg signed [23:0] c;
wire [23:0] result;
MAC MAC0(
.ifmap(a),
.filter(b),
.psum(c),
.updated_psum(result)
);
reg signed [23:0] answer;
reg signed [23:0] test_c[4:0];
integer i, j, k;
integer err;
initial begin
`ifdef FSDB
$fsdbDumpfile("MAC.fsdb");
$fsdbDumpvars("+struct", "+mda", MAC0);
`endif
test_c[0] = {24{1'b1}};
test_c[1] = 24'b0;
test_c[2] = 24'b0101_0101_0101_0101_0101_0101;
test_c[3] = 24'b1010_1010_1010_1010_1010_1010;
test_c[4] = 24'b0011_0011_0011_0011_0011_0011;
err = 0;
for (i = 8'b0; i <= 8'b1111_1111; i = i+1) begin
for (j = 8'b0; j <= 8'b1111_1111; j = j+1) begin
for (k = 8'd0; k <= 8'd4; k = k+1) begin
a = i;
b = j;
c = test_c[k];
answer = a * b + c;
#100
if(answer != result) begin
$display("Error :%d*%d+%d=%d", a, b, c, answer);
$display("Your result:%d*%d+%d=%d", a, b, c, $signed(result));
err = err + 1;
end else begin
err = err;
end
end
end
end
$display("Error times:%d", err);
end
endmodule
I personal think it may due to -128 causes an error during binary two's complement operation. I also have problems trying to calculate directly.
I found that the error came from directly fetching ifmap[7] as the sign extension.However, when multiplying -128 with other numbers, it will be converted to a positive value. If directly fetching ifmap[7] as the sign extension, errors will occur.
I modify the code below.
-1: begin
if (ifmap==(8'b10000000))
ans = {{8{1'b0}}, neg_ifmap};
else
ans = {{8{neg_ifmap[7]}}, neg_ifmap};
// ans = {{8{neg_ifmap[7]}}, neg_ifmap};
ans = ans << (i-1);
p = p + ans;
end
-2: begin
if (ifmap==(8'b10000000))
ans = {{8{1'b0}}, neg_ifmap} << 1;
else
ans = {{8{neg_ifmap[7]}}, neg_ifmap} << 1;
// ans = {{8{neg_ifmap[7]}}, neg_ifmap} << 1; // negative a
ans = ans << (i - 1);
p = p + ans;
end