module booth_datapath
(
input wire clk,
input wire rst,
input wire load,
input wire shift_en,
input wire add_sub_en,
input wire signed [7:0] M, // multiplicand
input wire signed [7:0] Q, // multiplier
output wire signed [15:0] product,
output reg [3:0] count // countdown from 8 → 0
);
reg signed [8:0] A; // A = n+1
reg signed [7:0] Q_reg;
reg Q_1;
assign product = {A, Q_reg};
always @(posedge clk or posedge rst)
begin
if (rst)
begin
A <= 9'sd0;
Q_reg <= 8'sd0;
Q_1 <= 1'b0;
count <= 4'd8; // eight Booth iterations
end
else
if (load)
begin
A <= 9'sd0;
Q_reg <= Q;
Q_1 <= 1'b0;
count <= 4'd8;
end
else
if (add_sub_en)
begin
case ({Q_reg[0], Q_1})
2'b01: A <= A + M;
2'b10: A <= A - M;
default: ;
endcase
end
else
if (shift_en)
begin
{A, Q_reg, Q_1} <= $signed({A, Q_reg, Q_1}) >>> 1;
count <= count - 1;
end
end
endmodule
// Controller (FSM)
module booth_controller
(
input wire clk,
input wire rst,
input wire start,
input wire [3:0] count,
output reg load,
output reg add_sub_en,
output reg shift_en,
output reg done
);
// ---------- State encoding ----------
localparam IDLE = 2'b00,
ADD = 2'b01,
SHIFT = 2'b10,
DONE = 2'b11;
reg [1:0] state, next_state;
// ---------- State register ----------
always @(posedge clk or posedge rst)
if (rst)
state <= IDLE;
else
state <= next_state;
// ---------- Combinational logic ----------
always @(*) begin
// Defaults
load = 1'b0;
add_sub_en = 1'b0;
shift_en = 1'b0;
done = 1'b0;
next_state = state;
case (state)
IDLE:
begin
if (start)
begin
load = 1'b1;
next_state = ADD;
end
end
ADD:
begin
add_sub_en = 1'b1;
next_state = SHIFT;
end
SHIFT:
begin
shift_en = 1'b1;
// Trước khi SHIFT, nếu count==1 thì đây là lần dịch cuối
if (count == 4'd1)
next_state = DONE;
else
next_state = ADD;
end
DONE:
begin
done = 1'b1; // giữ DONE cho tới khi reset bên ngoài
next_state = DONE;
end
default: next_state = IDLE;
endcase
end
endmodule
module booth_top
(
input wire clk,
input wire rst,
input wire start,
input wire signed [7:0] M,
input wire signed [7:0] Q,
output wire signed [15:0] product,
output wire done
);
wire load, add_sub_en, shift_en;
wire [3:0] count;
booth_controller ctrl (
.clk(clk), .rst(rst), .start(start),
.count(count), .load(load),
.add_sub_en(add_sub_en), .shift_en(shift_en),
.done(done)
);
booth_datapath dp (
.clk(clk), .rst(rst),
.load(load), .shift_en(shift_en), .add_sub_en(add_sub_en),
.M(M), .Q(Q),
.product(product), .count(count)
);
endmodule