Introduction#
It’s time to move to the next level of components. In this post, we’ll be building more complex but manageable components: multiplexers (MUX) and adders.
Multiplexer (MUX)#
A multiplexer (MUX) is an essential component that takes two inputs and, depending on a third input called sel (selector), outputs the value of either in1 or in2. If sel
is 0, in1 is outputted; if sel is 1, in2 is outputted.
Here’s a diagram of the MUX:

Let’s break it down further: when sel is 1, the output is true if both sel and in2 are true, which is achieved using an AND gate.

For in1, as sel is false, it must be inverted via a NOT gate. The outputs of the two AND gates are then fed into an OR gate.

The MHRD code for wiring the MUX looks like this:
Inputs: in1, in2, sel;
Outputs: out;
Parts:
n NOT,
a1 AND,
a2 AND,
o OR;
Wires:
in1 -> a1.in1,
in2 -> a2.in1,
sel -> n.in,
sel -> a2.in2,
n.out -> a1.in2,
a1.out -> o.in1,
a2.out -> o.in2,
o.out -> out;
Demultiplexer (DEMUX)#
A demultiplexer (DEMUX) performs the opposite function of a MUX: it takes one input and routes it to one of two outputs, based on the value of the selector input.

Here’s a logical arrangement of the DEMUX:

The truth table shows that each output is activated by different selector conditions. Two AND gates and a NOT gate are used to route the input based on the selector value.

The wiring for the DEMUX is as follows:
Inputs: in, sel;
Outputs: out1, out2;
Parts:
n NOT,
a1 AND,
a2 AND;
Wires:
in -> a1.in1,
in -> a2.in1,
sel -> n.in,
n.out -> a1.in2,
sel -> a2.in2,
a1.out -> out1,
a2.out -> out2;
MUX4B#
The MUX4B is an extension of the standard MUX to handle a 4-bit bus. It takes two 4-bit inputs and a single selector.

The wiring for the MUX4B looks like this:
Inputs: in1[4], in2[4], sel;
Outputs: out[4];
Parts:
m1 MUX,
m2 MUX,
m3 MUX,
m4 MUX;
Wires:
in1[1] -> m1.in1,
in1[2] -> m2.in1,
in1[3] -> m3.in1,
in1[4] -> m4.in1,
in2[1] -> m1.in2,
in2[2] -> m2.in2,
in2[3] -> m3.in2,
in2[4] -> m4.in2,
sel -> m1.sel,
sel -> m2.sel,
sel -> m3.sel,
sel -> m4.sel,
m1.out -> out[1],
m2.out -> out[2],
m3.out -> out[3],
m4.out -> out[4];
DEMUX4W#
As the name suggests, DEMUX4W is a demultiplexer with four outputs. This requires a 2-bit selector since four outputs cannot be selected with only one bit.

The first bit in the selector decides whether the output is routed to out1/out3 or out2/out4. The second bit further narrows it down to one of the four outputs.
The wiring is:
Inputs: in, sel[2];
Outputs: out1, out2, out3, out4;
Parts:
d1 DEMUX,
d2 DEMUX,
d3 DEMUX;
Wires:
in -> d1.in,
sel[2] -> d1.sel,
d1.out1 -> d2.in,
d1.out2 -> d3.in,
d2.out1 -> out1,
d2.out2 -> out2,
d3.out1 -> out3,
d3.out2 -> out4,
sel[1] -> d2.sel,
sel[1] -> d3.sel;
Completing this will unlock further components such as MUX4W16B, MUX16B, and DFF, which we will discuss later.
Half Adder#
A half adder is the foundational component of a CPU that enables basic addition. It takes two inputs and adds them. If both are 0, the output is 0. If one is 1, the output
is 1. If both are 1, the output is 0 but the carry output is set to 1.

The half adder uses an XOR gate for the output and an AND gate for the carry.

Here’s the wiring:
Inputs: in1, in2;
Outputs: out, carry;
Parts:
x XOR,
a AND;
Wires:
in1 -> x.in1,
in2 -> x.in2,
in1 -> a.in1,
in2 -> a.in2,
x.out -> out,
a.out -> carry;
Full Adder#
A full adder extends the half adder by adding an additional input called carryIn, which is used to add bits from previous additions. This is crucial for adding larger numbers.

Here’s the truth table for the full adder:

The wiring for the full adder looks like this:
Inputs: carryIn, in1, in2;
Outputs: out, carryOut;
Parts:
x XOR,
a AND,
o OR,
n NOT,
m1 MUX,
m2 MUX;
Wires:
in1 -> x.in1,
in1 -> o.in1,
in1 -> a.in1,
in2 -> x.in2,
in2 -> o.in2,
in2 -> a.in2,
x.out -> n.in,
x.out -> m1.in1,
n.out -> m1.in2,
carryIn -> m1.sel,
m1.out -> out,
a.out -> m2.in1,
o.out -> m2.in2,
carryIn -> m2.sel,
m2.out -> carryOut;
Adder4B#
Finally, we can chain multiple full adders to add two 4-bit numbers together.

The wiring for the 4-bit adder is:
Inputs: in1[4], in2[4], carryIn;
Outputs: out[4], carryOut;
Parts:
f1 FULLADDER,
f2 FULLADDER,
f3 FULLADDER,
f4 FULLADDER;
Wires:
in1[1] -> f1.in1,
in2[1] -> f1.in2,
in1[2] -> f2.in1,
in2[2] -> f2.in2,
in1[3] -> f3.in1,
in2[3] -> f3.in2,
in1[4] -> f4.in1,
in2[4] -> f4.in2,
f1.out -> out[1],
f2.out -> out[2],
f3.out -> out[3],
f4.out -> out[4],
carryIn -> f1.carryIn,
f1.carryOut -> f2.carryIn,
f2.carryOut -> f3.carryIn,
f3.carryOut -> f4.carryIn,
f4.carryOut -> carryOut;
Conclusion#
We have now built multiplexers, demultiplexers, half adders, and full adders. These components allow us to perform logical operations and arithmetic on multiple bits, a crucial step in constructing more complex systems, such as an Arithmetic Logic Unit (ALU).
