Binary to Excess-3 Code Converter in Verilog with Code
A binary (BCD) to Excess-3 converter adds 3 to every decimal digit, so the valid digits 0 through 9 map to the codes 0011 through 1100. Excess-3 (also written XS-3) is a self-complementing code that was widely used in early decimal arithmetic hardware because taking the 9’s complement of a digit is as simple as inverting its bits. This page gives clean, simulator-verified binary to excess 3 verilog code for both the forward converter and the reverse decoder.
Both modules below are purely combinational and are driven by self-checking testbenches that compare every output against a golden reference computed in the bench, so a real bug would print a FAIL line instead of the PASS lines you see in the logs.
The clearest implementation: Excess-3 is simply the 4-bit BCD value plus 3, so a single assign expresses the whole converter. The testbench sweeps all ten valid digits (0-9), checks each output equals digit + 3, then prints the don’t-care outputs for the invalid inputs 10-15.
module bcd_to_excess3 (
input [3:0] bcd,
output [3:0] xs3
);
assign xs3 = bcd + 4'd3;
endmodule
module tb;
reg [3:0] bcd;
wire [3:0] xs3;
integer d;
integer errors;
bcd_to_excess3 dut (.bcd(bcd), .xs3(xs3));
initial begin
errors = 0;
for (d = 0; d <= 9; d = d + 1) begin
bcd = d[3:0];
#1;
if (xs3 !== (d[3:0] + 4'd3)) begin
$display("FAIL: digit=%0d xs3=%b expected=%b", d, xs3, d[3:0]+4'd3);
errors = errors + 1;
end else begin
$display("PASS: BCD %0d (%b) -> Excess-3 %b (decimal %0d)", d, bcd, xs3, xs3);
end
end
// Show don't-care region 10-15 (still just +3, wraps past 4 bits)
for (d = 10; d <= 15; d = d + 1) begin
bcd = d[3:0];
#1;
$display("NOTE: invalid BCD input %0d (%b) -> output %b (unused / don't-care)", d, bcd, xs3);
end
if (errors == 0)
$display("ALL TESTS PASSED");
else
$display("TESTS FAILED: %0d", errors);
$finish;
end
endmodulePASS: BCD 0 (0000) -> Excess-3 0011 (decimal 3) PASS: BCD 1 (0001) -> Excess-3 0100 (decimal 4) PASS: BCD 2 (0010) -> Excess-3 0101 (decimal 5) PASS: BCD 3 (0011) -> Excess-3 0110 (decimal 6) PASS: BCD 4 (0100) -> Excess-3 0111 (decimal 7) PASS: BCD 5 (0101) -> Excess-3 1000 (decimal 8) PASS: BCD 6 (0110) -> Excess-3 1001 (decimal 9) PASS: BCD 7 (0111) -> Excess-3 1010 (decimal 10) PASS: BCD 8 (1000) -> Excess-3 1011 (decimal 11) PASS: BCD 9 (1001) -> Excess-3 1100 (decimal 12) NOTE: invalid BCD input 10 (1010) -> output 1101 (unused / don't-care) NOTE: invalid BCD input 11 (1011) -> output 1110 (unused / don't-care) NOTE: invalid BCD input 12 (1100) -> output 1111 (unused / don't-care) NOTE: invalid BCD input 13 (1101) -> output 0000 (unused / don't-care) NOTE: invalid BCD input 14 (1110) -> output 0001 (unused / don't-care) NOTE: invalid BCD input 15 (1111) -> output 0010 (unused / don't-care) ALL TESTS PASSEDThe log shows all ten valid digits converting correctly (0→0011 up to 9→1100), each line a PASS because the output matched the golden
digit + 3computed in the bench. The six NOTE lines expose the don't-care behaviour for inputs 10-15, which a real decimal system never presents. The closingALL TESTS PASSEDconfirms zero mismatches.The reverse converter subtracts 3 to recover the BCD digit. This variant also demonstrates the defining property of Excess-3: it is self-complementing, meaning the bitwise complement of Excess-3(d) equals Excess-3(9−d). The bench checks both facts over all ten digits.
module excess3_to_bcd ( input [3:0] xs3, output [3:0] bcd ); assign bcd = xs3 - 4'd3; endmodule module tb; reg [3:0] xs3; wire [3:0] bcd; integer d; integer errors; reg [3:0] xs3_d; // Excess-3 of d reg [3:0] xs3_9md; // Excess-3 of (9-d) excess3_to_bcd dut (.xs3(xs3), .bcd(bcd)); initial begin errors = 0; // Reverse: valid Excess-3 codes are d+3 for d=0..9, i.e. 3..12 for (d = 0; d <= 9; d = d + 1) begin xs3 = d[3:0] + 4'd3; #1; if (bcd !== d[3:0]) begin $display("FAIL: xs3=%b decoded=%b expected=%b", xs3, bcd, d[3:0]); errors = errors + 1; end else begin $display("PASS: Excess-3 %b -> BCD %0d (%b)", xs3, bcd, bcd); end end // Self-complementing property: ~Excess3(d) == Excess3(9-d) for (d = 0; d <= 9; d = d + 1) begin xs3_d = d[3:0] + 4'd3; xs3_9md = (9 - d) + 4'd3; if ((~xs3_d) !== xs3_9md) begin $display("FAIL self-comp: d=%0d ~%b=%b but Excess3(9-d)=%b", d, xs3_d, ~xs3_d, xs3_9md); errors = errors + 1; end else begin $display("PASS self-comp: d=%0d ~Excess3(%0d)=%b = Excess3(%0d)=%b", d, d, ~xs3_d, 9-d, xs3_9md); end end if (errors == 0) $display("ALL TESTS PASSED"); else $display("TESTS FAILED: %0d", errors); $finish; end endmodulePASS: Excess-3 0011 -> BCD 0 (0000) PASS: Excess-3 0100 -> BCD 1 (0001) PASS: Excess-3 0101 -> BCD 2 (0010) PASS: Excess-3 0110 -> BCD 3 (0011) PASS: Excess-3 0111 -> BCD 4 (0100) PASS: Excess-3 1000 -> BCD 5 (0101) PASS: Excess-3 1001 -> BCD 6 (0110) PASS: Excess-3 1010 -> BCD 7 (0111) PASS: Excess-3 1011 -> BCD 8 (1000) PASS: Excess-3 1100 -> BCD 9 (1001) PASS self-comp: d=0 ~Excess3(0)=1100 = Excess3(9)=1100 PASS self-comp: d=1 ~Excess3(1)=1011 = Excess3(8)=1011 PASS self-comp: d=2 ~Excess3(2)=1010 = Excess3(7)=1010 PASS self-comp: d=3 ~Excess3(3)=1001 = Excess3(6)=1001 PASS self-comp: d=4 ~Excess3(4)=1000 = Excess3(5)=1000 PASS self-comp: d=5 ~Excess3(5)=0111 = Excess3(4)=0111 PASS self-comp: d=6 ~Excess3(6)=0110 = Excess3(3)=0110 PASS self-comp: d=7 ~Excess3(7)=0101 = Excess3(2)=0101 PASS self-comp: d=8 ~Excess3(8)=0100 = Excess3(1)=0100 PASS self-comp: d=9 ~Excess3(9)=0011 = Excess3(0)=0011 ALL TESTS PASSEDThe first ten PASS lines prove the decoder recovers the original digit for every valid Excess-3 code (0011 through 1100). The next ten lines verify the self-complementing identity: inverting the four bits of Excess-3(d) yields exactly Excess-3(9−d) — for example
~Excess3(0)=1100=Excess3(9). Both checks compare against values recomputed in the bench, andALL TESTS PASSEDmeans neither check ever failed.What Excess-3 is and why it is self-complementing
Excess-3 represents a decimal digit by its 4-bit binary value biased, or "excessed", by 3. Digit 0 becomes 0011, digit 5 becomes 1000, and digit 9 becomes 1100. Because the bias is 3, the ten valid code words occupy the middle of the 4-bit range (3 to 12) rather than the bottom (0 to 9) as in straight BCD.
The key property is that Excess-3 is self-complementing: the 1's complement (bitwise NOT) of the code for digit d is the code for digit 9−d, which is the 9's complement of d. This is extremely useful for decimal subtraction, because 9's-complement arithmetic lets you subtract by adding a complement, and here the complement is free — it is just an inverter on each bit. Codes like plain BCD and 8421 do not have this property.
The +3 derivation
Why exactly 3? For a 4-bit code to be self-complementing, the code words of d and 9−d must be bitwise complements, so each pair must sum to 1111 (decimal 15). If the code for d is
d + kfor some fixed offset k, then:code(d) + code(9-d) = (d + k) + ((9 - d) + k) = 9 + 2kSetting this equal to 15 gives
2k = 6, sok = 3. That is the unique offset that makes a 4-bit weighted-plus-bias code self-complementing, which is precisely why the code is called Excess-3.Truth table and K-map note
The converter maps each valid BCD input to its Excess-3 output:
- 0000 → 0011
- 0001 → 0100
- 0010 → 0101
- 0011 → 0110
- 0100 → 0111
- 0101 → 1000
- 0110 → 1001
- 0111 → 1010
- 1000 → 1011
- 1001 → 1100
In a classic digital-logic course you would derive four output equations, one per Excess-3 bit, and simplify each with a Karnaugh map, treating inputs 1010 through 1111 as don't-cares to get minimal gates. The RTL above lets the synthesis tool do that minimization for you: writing
bcd + 3yields the same optimized logic a hand K-map would produce, which is why a behavioural+3is the idiomatic way to express this in Verilog.Difference from straight BCD
Straight BCD (8421) encodes digit d as its plain binary value, so 0 is 0000 and 9 is 1001. Excess-3 shifts every code up by 3. The practical differences:
- No all-zero code: digit 0 is 0011, not 0000. This historically helped distinguish a genuine zero digit from an inactive or blank line.
- Self-complementing: Excess-3 supports easy 9's-complement decimal subtraction; 8421 BCD does not.
- Carry behaviour: adding two Excess-3 digits introduces a bias of 6 in the sum, so correction (adding or subtracting 3) is needed, which is a different fix-up rule than the add-6 correction used for BCD addition.
Synthesis notes and common mistakes
Both modules synthesize to a small block of combinational logic — a handful of XOR/AND gates per output bit — with no clock or storage. A few things to watch:
- Widths: keep operands 4 bits wide. The
+ 4'd3literal is sized deliberately so the result stays in 4 bits and naturally wraps for the don't-care inputs.- Don't-cares, not errors: inputs 1010-1111 are not valid BCD. The hardware still produces some output for them (shown in the Example 1 log), but a correct system must never drive those values. If your design can, add an explicit validity check.
- Reverse-converter range: the decoder assumes a valid Excess-3 word (0011-1100). Feeding it 0000-0010 or 1101-1111 produces out-of-range results, so gate the input upstream if needed.
- Blocking vs non-blocking: because this is combinational, a continuous
assign(oralways @(*)with blocking assignments) is correct; do not usealways @(posedge clk)unless you intend to register the result.FAQ
Is Excess-3 the same as Gray code? No. Gray code changes only one bit between adjacent values; Excess-3 is a biased weighted code and is self-complementing, which Gray code is not.
Can I build this structurally with gates? Yes — derive the four per-bit Boolean equations from the truth table and instantiate
xor/and/orprimitives. The behavioural+3here is equivalent after synthesis and far easier to read.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