josuah.net | panoramix-labs.fr

git | cv | links | quotes | ascii | tgtimes | gopher | mail

Address decoding and multiplexer

When dealing with hardware there is often the need to convert input number to a binary flag output like so:

sel     en
 0 => 0b1110
 1 => 0b1101
 2 => 0b1011
...

For instance, if there are modules plugged like so:

                         ┌─────┐
                         │ t0  │
                 ┌───────en0   │
                 │   ┌───data  │
 ┌───────────┐   │   │   └─────┘
 │ decoder   │   │   │   ┌─────┐
 │         en0───┘   │   │ t1  │
─sel       en1───────────en1   │
─data      en2───┐   ├───data  │
 │           │   │   │   └─────┘
 │        data───│───┤   ┌─────┐
 └───────────┘   │   │   │ t2  │
                 └───────en2   │
                     └───data  │
                         └─────┘
      

Above, there are two inputs: sel and data. The sel signal would be turning only one of the enX signal on at a time:

Frequent on PCB design

It is frequent to have an "enable" signal, (SPI, memories...). This construct is ubiquitous, as you would have noticed there is only one data signal shared with every other chip.

Then the selection signal sel permits to choose which of the 3 targets (t0, t1, t2) to communicate with with the shared data bus. by telling each target:

Which of high or low means listen or ignore is a matter of convention.

I/O are scarce resources on a chip, and this is a very frequently encountered problem. There are actually a lot of small ASICs doing exactly this:

https://octopart.com/search?category_id=4287 ASICs on octopart, going as low as 10 cents for 8 outputs

Frequent on HDL design

It is also encountered while in hardware description languages (HDL) designs every time there is a bus with an address field: multiple targets (t0, t1, t2) would read an address port (like sel above).

Addresses are written at the same time as data and if the address matches, then the data is used, otherwise, it is ignored.

It looks like each target instance is monitoring the sel address port itself, but when pulling all this monitoring logic and putting it in common, the same construct as above is reproduced: just a matter of point of view.

Here is what happen if we let each device decode its own address:

             ┌─────┐
             │ t0  │
      ┌──────addr  │
      │  ┌───data  │
      │  │   └─────┘
      │  │   ┌─────┐
      │  │   │ t1  │
      ├──────addr  │
      │  ├───data  │
      │  │   └─────┘
data──│──┤   ┌─────┐
addr──┤  │   │ t2  │
      └──────addr  │
         └───data  │
             └─────┘

Implementation

The principle behind this is a demultiplexer, and has a reverse operation: a multiplexer.

Depending on a two-bits address (1 and 2), a multiplexer would select which of A, B, C or D transmit to the output Z:

    12
    ||
   │`.
 A─┤  │
 B─┤  │_Z
 C─┤  │
 D─┤  │
   │,'

I would like to implement the opposite: based on the address, I want to select the output.

There might be much to read about this on the Internet, I will see what solution I come-up with for my various use-cases. If you want me to write about it, ping me at me@josuah.net, I might have tried a few things by then.

Update

https://www.eevblog.com/forum/fpga/address-decoder/

In verilog, using a generate macro is an easy way to implement it, looping 3 times (in this example) over a variable such as i, and have addr == i for matching the slave device to use.

An alternate way is to use the shift operator, that is peforming the decoder function on its own. FPGA work with gates, not assembly statements, so the compiler (such as yosys) will be the one to pick a mesh of gates that solves it.