对于学术运动,我实施了32位Karatsuba乘数,该乘数需要17个周期来进行16位平行乘法并相应地移动它们。
。我正在遇到一个问题,其中局部产品需要未签名,但是无论我提供的输入类型如何,Booth Multiplier正在为我生成签名的部分产品,因为我得到了不正确的部分产品。我该如何解决?
例如。我的两个签名输入是0xa000_000a和0x000a_a000。因此,A000A的第一个部分产品应为64000,但我得到0xFFFC4000(FFFF_A000 * 0000_000A)。我在此处分享了Booth Mult及其TestBench的代码。
module booth_multiplier
(
input logic clk,
input logic rst,
input logic valid,
input logic signed [15:0] Mul_X,
input logic signed [15:0] Mul_Y,
output logic signed [31:0] product,
output logic result_ready
);
logic unsigned Q_1;
bit [4:0] count;
logic signed [15:0] multiplier;
logic signed [15:0] multiplicand;
logic [15:0] A, temp_A;
logic signed [32:0] partial_product;
logic signed [32:0] partial_multiplier;
typedef enum {IDLE=0, OPERATE} fsm;
fsm state, next_state;
parameter ADD = 2'b01, SUB = 2'b10;
//assign product = multiplier[16:1];
always@(posedge clk or negedge rst)
begin
if(~rst)
begin
count <= 0;
state <= IDLE;
multiplier <= 0;
multiplicand <= 0;
end
else begin
count <= count+1;
state <= next_state;
end
end
always@(*)
begin
case(state)
IDLE : begin
Q_1 = 0;
A = 0;
count = 0;
product = 0;
temp_A = 0;
result_ready = 0;
if(valid) begin
multiplicand = Mul_X;
multiplier = Mul_Y;
partial_product = {A, multiplier, Q_1};
partial_multiplier = 0;
next_state = OPERATE;
end
end
OPERATE: begin
case(partial_product[1:0])
ADD: begin
temp_A = A + multiplicand;
multiplier = partial_product[16:1];
partial_multiplier = {temp_A, multiplier, Q_1};
partial_product = partial_multiplier >>> 1;
Q_1 = partial_product[0];
A = partial_product[32:17];
end
SUB: begin
temp_A = A - multiplicand;
multiplier = partial_product[16:1];
partial_multiplier = {temp_A, multiplier, Q_1};
partial_product = partial_multiplier >>> 1;
Q_1 = partial_product[0];
A = partial_product[32:17];
end
default: begin
temp_A = A;
multiplier = partial_product[16:1];
partial_multiplier = {temp_A, multiplier, Q_1};
partial_product = partial_multiplier >>> 1;
Q_1 = multiplier[0];
A = partial_product[32:17];
end
endcase
if(count == 16) begin
next_state = IDLE;
product = partial_product >> 1;
result_ready = 1;
end
else next_state = OPERATE;
end
endcase
end
endmodule
我用来在
中进行4个并行乘法module fast_multiplier
(
input logic clk,
input logic rst,
input valid,
input logic signed [31:0] multiplicand,
input logic signed [31:0] multiplier,
output logic signed [63:0] product,
output logic ready);
logic [15:0] X1;
logic [15:0] Y1;
logic [15:0] Xr;
logic [15:0] Yr;
logic [31:0] X1_Yr;
logic [31:0] Xr_Yr;
logic [31:0] X1_Y1;
logic [31:0] Xr_Y1;
logic ready1, ready2, ready3, ready4;
assign X1 = multiplicand[31:16];
assign Y1 = multiplier[31:16];
assign Xr = multiplicand[15:0];
assign Yr = multiplier[15:0];
booth_multiplier X1Y1
(
.clk(clk),
.rst(rst),
.valid(valid),
.Mul_X(X1),
.Mul_Y(Y1),
.product(X1_Y1),
.result_ready(ready1));
booth_multiplier X1Yr
(
.clk(clk),
.rst(rst),
.valid(valid),
.Mul_X(X1),
.Mul_Y(Yr),
.product(X1_Yr),
.result_ready(ready2));
booth_multiplier XrY1
(
.clk(clk),
.rst(rst),
.valid(valid),
.Mul_X(Xr),
.Mul_Y(Y1),
.product(Xr_Y1),
.result_ready(ready3));
booth_multiplier XrYr
(
.clk(clk),
.rst(rst),
.valid(valid),
.Mul_X(Xr),
.Mul_Y(Yr),
.product(Xr_Yr),
.result_ready(ready4));
always@(posedge clk or negedge rst)
begin
if(~rst)
begin
product <= 0;
ready <= 0;
X1_Yr <= 0;
X1_Y1 <= 0;
Xr_Yr <= 0;
Xr_Y1 <= 0;
end
else begin
product <= ({32'b0,X1_Y1} << 32) + (({32'b0,X1_Yr} + {32'b0,Xr_Y1}) << 16) + {32'b0,Xr_Yr};
ready <= ready1 & ready2 & ready3 & ready4;
end
end
endmodule
另外,共享测试台,
module top_booth_multiplier ();
logic clk;
logic rst;
logic valid;
logic signed [31:0] multiplicand;
logic signed [31:0] multiplier;
logic signed [63:0] product;
logic ready;
fast_multiplier booth (.*);
initial
begin
clk = 0;
forever #10 clk = ~clk;
end
initial
begin
rst = 0;
#7 rst = 1;
@(posedge clk) valid <= 1;
multiplier = 32'hA000000A;
multiplicand = 32'h000AA000;
@(posedge clk) valid <= 0;
while(ready == 0)
begin
@(posedge clk);
end
repeat (20) @(posedge clk);
$finish;
end
endmodule
您只需要在x1Y1实例中考虑展位乘数中的"签名"输入。所有其他实例必须使用"未签名"输入。此更改应该有所帮助!