Signed Number Multiplication using Karatsuba Algorithm in Verilog

452 Views Asked by At

Tried implementing Karatsuba multiplier for multiplying two binary numbers, the logic below works well for unsigned numbers, but getting incorrect answer when I change one of the inputs to a negative. In the example below a=1010011111000000(equals -88.25) and b= 0001010001000000(equals 20.25). The answer should be 11111001000001001111000000000000(equals:-1787.0625)but I end up getting the incorect answer. Have used fixed point logic, with inputs 16 bits and fraction point 8 bits, output being 32 bits with fraction bits 16.

module karatsuba( input signed [15:0] a,
    input signed [15:0] b,
    output signed [31:0] out
    );
    
    reg  [15:0] ac,bd;
    reg  [31:0] t1;
    reg [31:0]t2;
    reg [24:0] psum;
    initial begin
 assign ac = a[15:8]*b[15:8];
 assign bd = a[7:0]*b[7:0];
  assign t2= bd;
  assign t1={ac,16'b0000000000000000};
  assign psum = {(a[15:8]+a[7:0])*(b[15:8]+b[7:0])-ac-bd,8'b00000000};
  end
  assign out= t1+psum+t2;

endmodule

module karatsuba_tb();
reg signed [15:0]a,b;
    wire signed [31:0]out;
    karatsuba uut(.a(a),.b(b),.out(out));
    initial begin
     a=16'b0101100001000000; 
        b=16'b0001010001000000;
       
end
endmodule

enter image description here

enter image description here

1

There are 1 best solutions below

0
On

There are two issues pertaining to the signed multiply in the post:

  1. Slices of vector variables (even slices of signed vectors) are treated as unsigned in Verilog. This is because when a slice is taken there is no way to identify the original sign bit, therefore it must be treated as unsigned

    The solution is to cast the slices to signed so that Verilog treats them as signed. Like this:

    assign ac = signed'(a[3:2]) * signed'(b[3:2]);

  2. Make the line that defines the variable ac,bd to be treated as signed using the signed keyword (default is unsigned).

You will need to propagate these changes to other places in the posted code which have the same issues.

Here is a simplified version of the post using small numbers to illustrate the cast and keyword use:

module karatsuba( 
    input signed [3:0] a,
    input signed [3:0] b
    );
    
    reg  signed [3:0] ac;
    assign ac = signed'(a[3:2]) * signed'(b[3:2]);
  
endmodule

module karatsuba_tb();
    reg signed [3:0]a,b;
  
    karatsuba uut(.a(a),.b(b));
  
    initial begin
      a = 4'b1110; 
      b = 4'b1111;
      #1;
      //
      $display("---------------");
      $display("uut.a[3:2] = %b",uut.a[3:2]);           
      $display("uut.b[3:2] = %b",uut.b[3:2]);           
      $display("uut.ac     = %b",uut.ac);
      $display("---------------");
      //
      $display("uut.a[3:2] = %d",signed'(uut.a[3:2]));           
      $display("uut.b[3:2] = %d",signed'(uut.b[3:2]));           
      $display("uut.ac     = %d",uut.ac);
      $display("---------------");
    end
  
endmodule

The example displays this message at runtime:

---------------
uut.a[3:2] = 11
uut.b[3:2] = 11
uut.ac     = 0001
---------------
uut.a[3:2] = -1
uut.b[3:2] = -1
uut.ac     =   1
---------------