Verilog中使用Karatsuba算法的有符号数乘法



尝试实现两个二进制数相乘的Karatsuba乘数,下面的逻辑适用于无符号数,但当我将其中一个输入更改为负数时,得到不正确的答案。在下面的例子中,a=1010011111000000(等于-88.25),b= 0001010001000000(等于20.25)。答案应该是11111001000001001111000000000000(等于:-1787.0625),但我最终得到了不正确的答案。采用定点逻辑,输入16位,分数8位,输出32位,分数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

输入图片描述

输入图片描述

关于post中的带符号乘法有两个问题:

  1. 向量变量的切片(甚至有符号向量的切片)在Verilog中被视为无符号。这是因为当获取切片时,无法识别原始符号位,因此必须将其视为无符号

    。解决方案是将片强制转换为signed,以便Verilog将它们视为signed。这样的:

    分配ac =签署(一个[3:2])*签署的(b [3:2]);

  2. 使定义变量ac,bd的行使用signed关键字(默认为unsigned)被视为有符号的。

您需要将这些更改传播到发布代码中存在相同问题的其他地方。

以下是文章的简化版本,使用小数字来说明转换和关键字的使用:

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

示例在运行时显示以下消息:

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

最新更新