Multiplexers, encoders, decoders and comparators

Learning objectives
  • Explain and size multiplexers, demultiplexers, encoders, priority encoders, decoders, and comparators
  • Compose larger selection logic
  • Identify invalid inputs, default behavior, and combinational design defects
1 Objective→ 2 Learn→ 3 Example→ 4 Practice→ 5 Verify→ 6 Continue
How to study this lessonUnderstand the idea first. Use the example to see the behaviour, practise where provided, then make sure you can explain the result before continuing.
D0D1D2D3
→
4:1 MUX
select
→
Y
Concept diagram: Multiplexers, encoders, decoders and comparators

Explanation

Combinational logic has no stored history

A combinational output is determined by current inputs after propagation delay. It has no intended memory. Every output must have a defined result for every legal input combination, including invalid or idle conditions specified by the interface.

Multiplexers select data

A multiplexer, or mux, chooses one of several inputs. A 2-to-1 mux has data inputs d0 and d1, select s, and output y:

y = (!s && d0) || (s && d1)

An M-input mux needs at least ceil(log2(M)) select bits. A 4-to-1 mux needs two. If the number of inputs is not a power of two, some select codes are unused and require defined behavior.

Muxes appear in datapaths, register writeback, bus selection, and configurable test paths. A wide mux applies the same selection to each bit of a bus.

Demultiplexers and decoders direct control

A demultiplexer sends one data input to one selected output. A decoder converts a binary code into one active output. A 2-to-4 active-high decoder produces:

a1 a0 d3 d2 d1 d0
00 0001
01 0010
10 0100
11 1000

With an enable input, every output is inactive when disabled. Decoders are used for register addresses, operation selection, and one-hot controls.

Pay attention to polarity. A bubble or _n name commonly indicates active-low behavior. reset_n=0 means reset is asserted. Never infer polarity from a signal's purpose alone; read its definition.

Encoders report which input is active

An encoder performs the reverse mapping: one active input becomes a binary code. A plain encoder assumes exactly one input is active. If multiple inputs can be asserted, the output is ambiguous.

A priority encoder defines which request wins, such as the highest numbered input. It should also produce a valid output because output code zero can mean either “input zero won” or “no input is active.” Fixed priority is simple but can starve low-priority requesters that continuously compete with high-priority traffic.

Comparators

An equality comparator checks every corresponding bit and combines the matches. Magnitude comparison starts at the most significant unequal bit.

Signed and unsigned comparison can differ for the same bits:

a = 4'b1110
b = 4'b0011

unsigned: a=14, b=3, therefore a>b
signed:   a=-2, b=3, therefore a<b

The interface must define signedness. Extending both operands correctly before comparison avoids accidental width rules.

Composition and timing

Larger muxes and decoders can be composed from smaller blocks. Functional composition is straightforward, but every added logic level contributes delay. A long priority chain may become a critical path. Balanced structures may be faster at the cost of area or complexity.

Total output definition

In a combinational RTL process, assign a default before conditional overrides or cover every branch. Missing an assignment means the output must retain its previous value, which implies a latch. A combinational loop occurs when a signal depends on itself through only combinational logic. Such loops are generally unstable, difficult to time, and rejected unless deliberately implemented with a specialized flow.

Review questions

  • Are unused select or address codes defined?
  • Is active polarity clear?
  • Can multiple encoder inputs be asserted?
  • Is “none selected” distinguishable from selecting index zero?
  • Are comparisons signed or unsigned?
  • Does every output receive a value on every path?
  • Can priority cause starvation?

Worked example

Design a read mux for four 8-bit status registers.

Inputs are status0 through status3 and a 3-bit address. Valid addresses 0 through 3 select a register. Addresses 4 through 7 must return zero and assert read_error.

Address read_data read_error
0 status0 0
1 status1 0
2 status2 0
3 status3 0
4–7 8'h00 1

A good combinational description starts with safe defaults:

always_comb begin
    read_data  = 8'h00;
    read_error = 1'b0;
    case (address)
        3'd0: read_data = status0;
        3'd1: read_data = status1;
        3'd2: read_data = status2;
        3'd3: read_data = status3;
        default: read_error = 1'b1;
    endcase
end

The default values define invalid addresses and prevent unintended storage. Verification should exercise every address, not only the four useful cases.

Check yourself

Why does a priority encoder need a valid output? What behavior should a mux define for unused select codes?