Nona Blog

Visualising MUX and DEMUX logic in JavaScript

In the previous article –

We looked at how to write some basic boolean logic gates as JavaScript functions.

While this gives us a pretty good understanding of how to visualise the output of a circuit based off a set of conditions, it lacks is the ability to make decisions from this.

Enter the Multiplexer

For our purposes – the MUX or Multiplexer is a function (chip) that returns a specific value based off a selection e.g:

A = {either 1 or 0}
B = {either 1 or 0}
IF SEL EQUALS = 0
THEN OUTPUT A
ELSE OUTPUT B

This seems pretty straight forward, however, if we are going to build this using only NAND gates this becomes a little more tricky. For the sake of visualisation though, I am going to take advantage of some gates that we have already built (using the NAND gate) to represent our new MUX function.

The MUX function

This can be defined in JavaScript as:

const mux = (sel, a, b) => or(and(a, not(sel)), and(sel, b))

I would suggest taking a bit of time to understand what is actually happening here before moving on.

Let’s go ahead and create some example implementations for this:

let sel = 0
let a = 0
let b = 0
console.log(mux(sel, a, b)) // logs 0 (a)

let sel = 0
let a = 1
let b = 0
console.log(mux(sel, a, b)) // logs 1 (a)

let sel = 0
let a = 0
let b = 1
console.log(mux(sel, a, b)) // logs 0 (a)

If sel = 1 in any of the above examples the output would just be whatever the value of b was.

The DEMUX function

The DEMUX or Demultiplexer, while not entirely the inverse of the MUX operator is probably the best way to describe it given what we currently know about logic gates. I say this because a DEMUX function is one that takes in a single input and returns multiple outputs.

INPUT = {either 1 or 0}
IF SEL EQUALS 0
OUTPUT A = INPUT AND B = 0
ELSE
OUTPUT A = 0 AND B = INPUT

Something to note here is that we need a way to label our outputs (a and b), which we have never done before. When building a physical chip we could obviously label this in some meaningful way using an actual label or by ordering it in a specific way within the circuit. By taking this into account we can make use of JavaScript objects to label the returned output (note we aren’t actually adding anything new from a physical chip perspective, just wiring up our circuit slightly differently to have two outputs instead of one).

The demux function in JavaScript can be defined as follows:

const demux = (sel, input) => (
  {
    a: and(input, not(sel)),
    b: and(input, sel)
  }
)

Let’s create some examples:

let sel = 0
let input = 0
console.log(demux(sel, input)) // logs { a:0 b:0 }

let sel = 1
let input = 0
console.log(demux(sel, input)) //logs { a:0 b:0 }

let sel = 0
let input = 1
console.log(demux(sel, input)) //logs { a:1 b:0 }

let sel = 1
let input = 1
console.log(demux(sel, input)) //logs { a:0 b:1 }

Conclusion

If you look at the above two functions in any type of detail you will notice that we are adding a whole new dynamic to what is possible using existing NAND functionality, this will become much more apparent when we move onto some more advanced concepts. The last piece really of the basic logic gate puzzle is that of array input and output (which we have essentially done with the output of our demux).

From there we will start looking at how we can go about creating arithmetic processing logic and eventually a way to persist state with a register using only the logic gates that we have already built. Please let me know if you have any thoughts or comments.

Nona helps funded businesses accelerate their software projects. If you’d like to soundboard your tech project or your development team, book a consultation with Ed and we can chat through it! 

Richard Miles

Richard Miles

Fullstack Developer - Nona

Add comment