Modified Booth (Radix-4) Multiplier in Verilog with Code
The modified Booth multiplier (also called the radix-4 Booth multiplier) is a signed-multiplication circuit that recodes the multiplier three bits at a time so it generates only half as many partial products as a naive array multiplier. This page gives you clean, synthesizable modified booth multiplier Verilog code with runnable, self-checking testbenches, plus the radix-4 recoding table and the sign-extension rules you need to get a correct signed product.
Unlike the plain (radix-2) Booth algorithm, which scans overlapping pairs of bits and still produces N partial products for an N-bit multiplier, the radix-4 scheme scans overlapping triples and collapses them into N/2 partial products chosen from the set {-2, -1, 0, +1, +2} times the multiplicand. Fewer partial products means a shorter, faster adder tree.
A signed 4×4 modified Booth multiplier with the two partial products written out explicitly. The recode function maps each overlapping 3-bit group to its {-2,-1,0,+1,+2} multiple of the multiplicand, and the testbench checks all 256 signed input combinations against $signed(a)*$signed(b).
// Radix-4 Modified Booth multiplier: signed 4x4, explicit two partial products
module booth_radix4_4x4(
input signed [3:0] a, // multiplicand
input signed [3:0] b, // multiplier
output signed [7:0] p // signed product
);
wire [2:0] g0, g1;
assign g0 = {b[1], b[0], 1'b0}; // {y1, y0, y(-1)=0} weight 2^0
assign g1 = {b[3], b[2], b[1]}; // {y3, y2, y1} weight 2^2
// Booth recode: returns (coeff * multiplicand), coeff in {-2,-1,0,+1,+2}
function signed [5:0] recode;
input [2:0] g;
input signed [3:0] m;
reg signed [5:0] mm; // sign-extended multiplicand (prevents 2*m overflow)
begin
mm = m;
case (g)
3'b001, 3'b010: recode = mm; // +1
3'b011: recode = mm <<< 1; // +2
3'b100: recode = -(mm <<< 1); // -2
3'b101, 3'b110: recode = -mm; // -1
default: recode = 6'sd0; // 000 / 111 -> 0
endcase
end
endfunction
reg signed [7:0] pp0, pp1;
always @(*) begin
pp0 = recode(g0, a);
pp1 = recode(g1, a);
end
assign p = pp0 + (pp1 <<< 2); // sum sign-extended partial products
endmodule
module tb;
reg signed [3:0] a, b;
wire signed [7:0] p;
integer i, j, fails;
reg signed [7:0] exp;
booth_radix4_4x4 dut(.a(a), .b(b), .p(p));
initial begin
fails = 0;
for (i = -8; i <= 7; i = i + 1) begin
for (j = -8; j <= 7; j = j + 1) begin
a = i[3:0];
b = j[3:0];
#1;
exp = $signed(a) * $signed(b); // golden model
if (p !== exp) begin
$display("FAIL a=%0d b=%0d got=%0d exp=%0d", $signed(a), $signed(b), $signed(p), exp);
fails = fails + 1;
end
end
end
// Spot PASS lines for representative corner cases
a = -8; b = -8; #1; $display("PASS (-8)*(-8) = %0d", $signed(p));
a = -8; b = 7; #1; $display("PASS (-8)*( 7) = %0d", $signed(p));
a = 7; b = 7; #1; $display("PASS ( 7)*( 7) = %0d", $signed(p));
a = 0; b = -5; #1; $display("PASS ( 0)*(-5) = %0d", $signed(p));
if (fails == 0)
$display("ALL TESTS PASSED (256/256 signed 4x4 combinations)");
else
$display("TOTAL FAILS = %0d", fails);
$finish;
end
endmodule
PASS (-8)*(-8) = 64 PASS (-8)*( 7) = -56 PASS ( 7)*( 7) = 49 PASS ( 0)*(-5) = 0 ALL TESTS PASSED (256/256 signed 4x4 combinations)The log shows an exhaustive sweep of every signed 4-bit multiplicand against every signed 4-bit multiplier. Each product is compared against a golden
$signed(a)*$signed(b)reference, and the corner cases (-8)x(-8)=64, (-8)x(7)=-56 and (7)x(7)=49 are printed explicitly, proving the recoding and sign extension are correct across the full input space.A width-parameterized version (default N=8) that exposes the radix-4 recoding as a reusable
recodefunction and loops over all N/2 overlapping groups, accumulating sign-extended partial products. The testbench exhaustively sweeps all 65,536 signed 8x8 pairs, including negative-by-negative and zero cases.// Parameterized radix-4 Modified Booth multiplier (signed, even N) // Recodes N/2 overlapping groups and accumulates sign-extended partial products. module booth_radix4 #(parameter N = 8) ( input signed [N-1:0] a, // multiplicand input signed [N-1:0] b, // multiplier output signed [2*N-1:0] p ); integer i; reg signed [2*N-1:0] acc; reg signed [N+1:0] pp; reg [N:0] be; // {b, 1'b0}: be[0] is the implicit y(-1)=0 reg [2:0] g; // Expose the radix-4 recoding as a function: coeff(-2..+2) * multiplicand function signed [N+1:0] recode; input [2:0] grp; input signed [N-1:0] m; reg signed [N+1:0] mm; // widened so +2*|m| (most-negative m) cannot overflow begin mm = m; case (grp) 3'b001, 3'b010: recode = mm; 3'b011: recode = mm <<< 1; 3'b100: recode = -(mm <<< 1); 3'b101, 3'b110: recode = -mm; default: recode = {(N+2){1'b0}}; // 000 / 111 -> 0 endcase end endfunction always @(*) begin be = {b, 1'b0}; acc = {(2*N){1'b0}}; for (i = 0; i < N/2; i = i + 1) begin g = {be[2*i+2], be[2*i+1], be[2*i]}; pp = recode(g, a); acc = acc + ($signed(pp) <<< (2*i)); end end assign p = acc; endmodule module tb; localparam N = 8; reg signed [N-1:0] a, b; wire signed [2*N-1:0] p; integer i, j, fails; reg signed [2*N-1:0] exp; booth_radix4 #(.N(N)) dut(.a(a), .b(b), .p(p)); initial begin fails = 0; // exhaustive signed 8x8 sweep (65536 combinations) for (i = -128; i <= 127; i = i + 1) begin for (j = -128; j <= 127; j = j + 1) begin a = i[N-1:0]; b = j[N-1:0]; #1; exp = $signed(a) * $signed(b); if (p !== exp) begin $display("FAIL a=%0d b=%0d got=%0d exp=%0d", $signed(a), $signed(b), $signed(p), exp); fails = fails + 1; end end end a = -128; b = -128; #1; $display("PASS neg*neg (-128)*(-128) = %0d", $signed(p)); a = -128; b = 127; #1; $display("PASS neg*pos (-128)*( 127) = %0d", $signed(p)); a = 0; b = -99; #1; $display("PASS zero ( 0)*( -99) = %0d", $signed(p)); a = 45; b = -45; #1; $display("PASS mixed ( 45)*( -45) = %0d", $signed(p)); if (fails == 0) $display("ALL TESTS PASSED (65536/65536 signed 8x8 combinations)"); else $display("TOTAL FAILS = %0d", fails); $finish; end endmodulePASS neg*neg (-128)*(-128) = 16384
PASS neg*pos (-128)*( 127) = -16256
PASS zero ( 0)*( -99) = 0
PASS mixed ( 45)*( -45) = -2025
ALL TESTS PASSED (65536/65536 signed 8x8 combinations)The log confirms all 65,536 signed 8x8 combinations match the golden reference, including the hardest case (-128)x(-128)=16384, which forces a +2x(multiplicand) partial product on the most-negative operand. That is exactly the case that overflows if the recoded value is not widened by one extra bit before shifting.
Radix-4 Booth recoding table
The modified Booth algorithm appends an implicit 0 below the LSB of the multiplier and then scans overlapping 3-bit windows. Each window {y2i+1, y2i, y2i-1} selects one multiple of the multiplicand. The recoded value is simply
-2·y2i+1 + y2i + y2i-1:
y2i+1 y2i y2i-1 Operation 0 0 0 +0 0 0 1 +1 × M 0 1 0 +1 × M 0 1 1 +2 × M 1 0 0 -2 × M 1 0 1 -1 × M 1 1 0 -1 × M 1 1 1 +0 Here M is the multiplicand. The ±1 multiples are the multiplicand itself (or its two's-complement negation); the ±2 multiples are a single left shift of those. Because every multiple is a shift and/or negate, no actual multiplier is needed to build the partial products.
Why it halves the partial products
A straightforward signed array multiplier for an N-bit multiplier produces N partial products, one per multiplier bit. The radix-4 scheme consumes two new multiplier bits per step (the windows overlap by one bit), so an N-bit multiplier yields only ⌈N/2⌉ partial products. For an 8-bit multiplier that is 4 partial products instead of 8; for 32 bits it is 16 instead of 32.
Fewer partial products shorten the final summation. Whether you use a ripple of adders or a Wallace/Dadda tree, halving the operand count removes roughly one level of the reduction tree, cutting both delay and adder area. This is the classic reason modified Booth encoding is the default front end in most high-performance signed multipliers.
Radix-4 vs. radix-2 Booth
Plain radix-2 Booth encoding scans overlapping pairs and only ever adds, subtracts, or does nothing (multiples {-1, 0, +1}); it still emits N partial products, so it does not reduce the adder tree the way radix-4 does. The radix-4 version adds the {±2} multiples, which is what lets it consume two bits per step. The cost is generating the 2× multiple (one shift) and slightly more complex select logic per partial product — a good trade.
Sign-extension handling
Signed correctness hinges on three details that the code above handles explicitly:
- Each partial product is itself signed. A −1 or −2 multiple is a negative number, so each partial product must be sign-extended to the full product width before it is added into the accumulator. In the code this happens automatically because the recode result is a
signedvalue assigned into a widersignedaccumulator.- The 2× multiple must be widened before shifting. For the most-negative multiplicand,
-2 × Mequals+2k, which needs one more bit than the multiplicand to represent as a positive number. The parameterized example uses an[N+1:0]recode result precisely so that(-2)×(-128) = +256does not wrap. Omitting that extra bit is the single most common bug in modified Booth Verilog, and the exhaustive testbench catches it immediately at a = −128.- Arithmetic shifts, not logical. Partial products are placed at their weights with the arithmetic shift operator
<<<on signed operands so the sign bit is preserved while the value is scaled by 22i.Synthesis notes
The code is written in strict Verilog-2005 (reg/wire,
always @(*), functions, integer loop variables) so it maps cleanly in any synthesis flow. A few practical points:
- The
recodefunction is pure combinational select-and-shift logic — it synthesizes to muxes and a negate, not to an arithmetic multiplier.- The loop in the parameterized module is statically bounded by
N/2, so it fully unrolls during elaboration into N/2 partial-product generators plus an adder chain.- For timing-critical designs, replace the linear accumulation with a Wallace or Dadda tree of carry-save adders over the N/2 partial products; the recoding front end stays identical. The behavioral
+chain here lets the synthesizer pick an adder structure and keeps the reference readable.- N must be even for the simple group indexing shown; for odd widths, sign-extend the multiplier by one bit first.
FAQ
Is the modified Booth multiplier the same as the Booth multiplier?
"Booth multiplier" usually means the radix-2 algorithm. "Modified Booth" (radix-4) is the enhancement that recodes three bits at a time to halve the partial-product count. Both handle signed numbers in two's complement; the radix-4 version is the one used in practical high-speed multipliers.
Does this code handle unsigned multiplication?
As written it computes a signed (two's-complement) product. To multiply unsigned values, zero-extend both operands by one bit so the sign bit is forced to 0, then use the signed multiplier and take the low 2N bits of the result.
Why append a zero below the LSB?
The first window has no bit to its right, so the algorithm defines y-1 = 0. In the code this is the
1'b0appended when forming the first group (or the LSB of{b, 1'b0}in the parameterized version).How do I verify my own version?
Compare against
$signed(a)*$signed(b)in a testbench and sweep exhaustively for small widths (4- and 8-bit sweeps run in milliseconds under Icarus Verilog). Always include a = the most-negative value, since that is where sign-extension and the 2× multiple break if the widths are wrong.Have questions about this topic?
Share your question in comments or talk to our mentor team for batch guidance.▶ Try it in the ChipXpert LabRun it in the LabOpen this design in the free in-browser simulator — edit, compile and see the waveform/log instantly.
Learn Verilog with mentors, labs and placement support
This free series is maintained by the ChipXpert training team in Hyderabad & Bengaluru. Go deeper with instructor-led courses on real EDA tools.
Explore VLSI Courses Hi! Ask me about courses, fees, batches or discounts. ×ChipXpert AssistantAsk about courses, fees, batches and centres