BCD Adder in Verilog: Single-Digit and Two-Digit Decimal Addition with Add-6 Correction
A bcd adder verilog code example adds two Binary Coded Decimal (BCD) digits and produces a valid BCD result plus a decimal carry. BCD stores each decimal digit 0–9 in a 4-bit nibble, so a plain binary adder is not enough: when the raw sum exceeds 9, the result must be corrected by adding 6 to skip the six unused codes (1010–1111).
This page builds a single-digit BCD adder with the classic add-6 correction, then chains two of them into a two-digit (8-bit) ripple adder. Both designs are pure Verilog-2005 and ship with self-checking testbenches you can run in Icarus Verilog.
Single-digit BCD adder with add-6 correction
The design sums a, b and cin into a 5-bit binary value. If that value is greater than 9, adding 6 produces the correct BCD digit in the low nibble and asserts the decimal carry-out.
// Single-digit BCD adder with add-6 correction
module bcd_adder(input [3:0] a, input [3:0] b, input cin,
output [3:0] sum, output cout);
wire [4:0] bin = a + b + cin; // raw binary sum, 0..19
wire need6 = (bin > 5'd9); // correction needed when > 9
wire [4:0] corr = need6 ? (bin + 5'd6) : bin;
assign sum = corr[3:0]; // low nibble = BCD digit
assign cout = need6; // carry to next decimal digit
endmodule
module tb;
reg [3:0] a, b; reg cin;
wire [3:0] sum; wire cout;
integer errors = 0;
bcd_adder dut(.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));
task check(input [3:0] ta, input [3:0] tb, input tcin,
input [3:0] esum, input ecout);
begin
a = ta; b = tb; cin = tcin; #1;
if (sum === esum && cout === ecout)
$display("PASS: %0d + %0d + %0d = digit %0d, carry %0d",
ta, tb, tcin, sum, cout);
else begin
$display("FAIL: %0d + %0d + %0d -> digit %0d carry %0d (exp %0d/%0d)",
ta, tb, tcin, sum, cout, esum, ecout);
errors = errors + 1;
end
end
endtask
initial begin
check(4'd7, 4'd5, 1'b0, 4'd2, 1'b1); // 12
check(4'd4, 4'd3, 1'b0, 4'd7, 1'b0); // 7
check(4'd9, 4'd9, 1'b1, 4'd9, 1'b1); // 19
check(4'd0, 4'd0, 1'b0, 4'd0, 1'b0); // 0
check(4'd5, 4'd5, 1'b0, 4'd0, 1'b1); // 10
check(4'd8, 4'd9, 1'b1, 4'd8, 1'b1); // 18
if (errors == 0) $display("ALL PASS");
else $display("%0d FAILURES", errors);
$finish;
end
endmodule
PASS: 7 + 5 + 0 = digit 2, carry 1 PASS: 4 + 3 + 0 = digit 7, carry 0 PASS: 9 + 9 + 1 = digit 9, carry 1 PASS: 0 + 0 + 0 = digit 0, carry 0 PASS: 5 + 5 + 0 = digit 0, carry 1 PASS: 8 + 9 + 1 = digit 8, carry 1 ALL PASSEvery case matches its expected digit and decimal carry: 7+5 gives digit 2 with carry 1 (i.e. 12), and 9+9+1 gives digit 9 with carry 1 (19).
Two-digit (8-bit) BCD ripple adder
Two single-digit stages are chained: the units stage feeds its decimal carry into the tens stage. Each operand is packed as
[7:4]= tens and[3:0]= units, so the result reads directly as two BCD digits.// Two-digit (8-bit BCD) ripple adder built from two bcd_adder stages module bcd_adder(input [3:0] a, input [3:0] b, input cin, output [3:0] sum, output cout); wire [4:0] bin = a + b + cin; wire need6 = (bin > 5'd9); wire [4:0] corr = need6 ? (bin + 5'd6) : bin; assign sum = corr[3:0]; assign cout = need6; endmodule // Each operand holds two BCD digits: [7:4]=tens, [3:0]=units module bcd_adder2(input [7:0] a, input [7:0] b, output [7:0] sum, output cout); wire c0; bcd_adder u0(.a(a[3:0]), .b(b[3:0]), .cin(1'b0), .sum(sum[3:0]), .cout(c0)); bcd_adder u1(.a(a[7:4]), .b(b[7:4]), .cin(c0), .sum(sum[7:4]), .cout(cout)); endmodule module tb; reg [7:0] a, b; wire [7:0] sum; wire cout; integer errors = 0; bcd_adder2 dut(.a(a), .b(b), .sum(sum), .cout(cout)); task check(input [7:0] ta, input [7:0] tb, input [7:0] esum, input ecout); begin a = ta; b = tb; #1; if (sum === esum && cout === ecout) $display("PASS: %0h + %0h = %0h, carry %0d", ta, tb, sum, cout); else begin $display("FAIL: %0h + %0h -> %0h carry %0d (exp %0h/%0d)", ta, tb, sum, cout, esum, ecout); errors = errors + 1; end end endtask initial begin check(8'h25, 8'h37, 8'h62, 1'b0); // 25+37=62 check(8'h49, 8'h49, 8'h98, 1'b0); // 49+49=98 check(8'h99, 8'h01, 8'h00, 1'b1); // 99+01=100 check(8'h58, 8'h67, 8'h25, 1'b1); // 58+67=125 if (errors == 0) $display("ALL PASS"); else $display("%0d FAILURES", errors); $finish; end endmodulePASS: 25 + 37 = 62, carry 0
PASS: 49 + 49 = 98, carry 0
PASS: 99 + 1 = 0, carry 1
PASS: 58 + 67 = 25, carry 1
ALL PASSHexadecimal display is handy here because a valid BCD result reads out as decimal:
8'h62is literally the digits 6 and 2. The 99+01 case shows the tens carry rolling out to 100 (result 00, carry 1).Why plain binary addition fails for BCD
A 4-bit nibble can represent 0–15, but BCD only uses 0–9. When two digits add to more than 9 — for example 7 + 5 = 12 — the raw binary result (
01100, decimal 12) is not a valid single BCD digit. The six codes 1010 through 1111 are illegal. Adding 6 (0110) pushes the sum past those six unused codes, which simultaneously wraps the low nibble to the correct decimal digit and generates a carry into the next decimal position. This is exactly how the classic 7483-plus-correction BCD adder works in hardware textbooks.How the add-6 correction works
The raw sum of two digits plus a carry ranges from 0 to 19, so five bits hold it safely. The condition
bin > 9captures both cases that need correction: a true binary overflow (sum 16–19, where bit 4 is set) and the mid-range illegal values 10–15. Becausebin + 6for any value 10–19 lands in the range 16–25, the low nibblecorr[3:0]always holds the right units digit and the correction flag itself becomes the decimal carry-out. A common exam mistake is testing only bit 4 (bin[4]) for the carry; that misses sums of 10–15 entirely, so always compare the full value against 9.Chaining digits into a ripple adder
Multi-digit BCD addition is a ripple of single-digit stages, just like a binary ripple-carry adder but with decimal carries. The units stage takes
cin = 0; itscoutfeeds the tens stage, and so on. The combinational delay grows linearly with the number of digits, which is acceptable for small displays and calculators but is the first thing to pipeline if you need throughput. Packing each digit into its own nibble ([7:4]tens,[3:0]units) keeps the result human-readable in simulation when printed with%h.Synthesis notes and interview angle
This code is fully synthesizable: the comparison, the conditional add, and the digit slices all map to a small block of adders and a multiplexer. Interviewers like BCD adders because they test whether you truly understand why the +6 trick works rather than memorizing it — be ready to explain the six skipped codes and to show the carry is driven by the correction condition, not by bit 4 alone. A good follow-up answer is that BCD arithmetic trades hardware efficiency for exact decimal representation, which is why it survives in financial and display logic where binary-to-decimal rounding errors are unacceptable.
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