VHDL · Chapter 6.5 · Combinational Logic Design
Multiplexers
The multiplexer is the workhorse of combinational logic. It selects one of several inputs and routes it to the output under the control of a select signal, and almost every datapath is built from muxes. VHDL gives you four natural ways to write one. The when-else and if forms build a priority mux, while the with-select and case forms build a balanced mux, and indexing an array by an integer gives a clean wide mux. This lesson maps each style to the hardware it builds, shows when priority versus balanced selection matters, and applies the default-then-override discipline so a mux never accidentally latches. Choosing the right width and selection shape is the only real design decision.
Foundation13 min readVHDLMultiplexerSelectionPriority MuxDatapathRTL
1. Engineering intuition — route one of many
A multiplexer is a switch: many inputs, one output, and a select that decides which input gets through. It is the basic act of choosing in hardware — feed a register from one of several sources, pick an ALU result, steer a bus. Because choosing is so common, VHDL offers several syntaxes for it, but they all describe the same primitive: a selection network from N inputs to one output. The only real design decisions are the width (N) and whether the selection is priority (ordered) or balanced (value-based).
2. Formal explanation — four ways, two shapes
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
-- PRIORITY mux (ordered conditions): when/else (concurrent) or if (process).
y1 <= a when s1 = '1' else b when s2 = '1' else c; -- first true wins
-- BALANCED mux (one selector value): with/select (concurrent) or case (process).
with sel select
y2 <= d0 when "00", d1 when "01", d2 when "10", d3 when others;
-- WIDE mux by ARRAY INDEX: index a vector-of-vectors with an integer (numeric_std).
y3 <= data_array(to_integer(unsigned(sel))); -- clean N:1 muxwhen/else and if build a priority mux (a chain of 2:1 muxes, order = precedence);
with/select and case build a balanced mux (a flat one-of-N decode). Indexing an array by an
integer is the most concise wide mux. All are combinational; keep them latch-free (a final else /
when others / complete index range, plus defaults in a process).
3. Production RTL — datapath source select
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
-- 4:1 datapath mux feeding a register input, written as a balanced case in a process.
src_mux : process (all)
begin
mux_out <= (others => '0'); -- default → latch-free
case src_sel is
when "00" => mux_out <= alu_result;
when "01" => mux_out <= mem_data;
when "10" => mux_out <= imm_value;
when others => mux_out <= reg_data;
end case;
end process;What hardware does this become? A 4:1 multiplexer selecting the register-input source — src_sel
drives the mux select, and the four data sources are its inputs. The default plus full case coverage
guarantees no latch. (Written as mux_out <= data_array(to_integer(unsigned(src_sel))) it is the same
mux, more concisely, when the sources are collected into an array.)
4. Hardware interpretation — N:1 selection
5. Simulation interpretation — output follows the select
A mux is combinational, so its output continuously equals the currently-selected input — change the select or the selected input and the output follows after a delta.
A 4:1 mux: the select value routes the matching source to the output
8 cycles6. Debugging example — priority where balanced was meant (and a latch)
Expected: a value-based 4:1 mux. Observed: either subtly wrong selection, or an inferred latch.
Root cause: writing a value decode as an if/elsif ladder makes it a priority mux — fine if
conditions are exclusive, but it adds depth and, if the final else is missing, leaves a path
unassigned → latch. Fix: use case/with/select for value-based selection (balanced, exhaustive),
or ensure the if ladder has a final else. Engineering takeaway: match the construct to the
selection — case/with/select for value decode, when/else/if for ranked conditions — and always
close it (default / else / others) so the mux cannot latch.
-- RISK: value decode as a priority ladder, missing final else → latch + extra depth.
-- y <= d0 when sel="00" else d1 when sel="01" else d2 when sel="10"; -- no else → latch
-- FIX: balanced, exhaustive selection.
with sel select
y <= d0 when "00", d1 when "01", d2 when "10", d3 when others; -- balanced, no latch7. Common mistakes & what to watch for
- Missing final
else/when others. Leaves a path unassigned → latch. Always close the mux. - Using a priority style for value-based selection.
case/with/selectis balanced and clearer; reserveif/when/elsefor ranked conditions. - Index out of range on an array mux.
data_array(to_integer(unsigned(sel)))must haveselcover exactly the array range; an out-of-range index is an error. - Forgetting defaults in a process-style mux. Default the output at the top to stay latch-free.
- Very wide priority muxes. A long
ifladder has deep logic; a balancedcase/array index is faster and smaller for wide selection.
8. Engineering insight & continuity
The multiplexer is selection distilled, and writing one well is mostly about two choices: balanced
versus priority, and keeping it latch-free. Use case/with/select (or an array index) for the common
value-based mux, reserve priority styles for genuinely ranked conditions, and always close the
selection so no path is unassigned. With muxes — the route-one-of-many primitive — in hand, the next
lesson covers the complementary primitives that expand and compress encodings: Decoders and
Encoders, where a binary value fans out to one-hot (decode) or a one-hot/priority input compresses to
binary (encode).
Standards & specifications
- Governing standard
- IEEE Std 1076 (VHDL)(opens IEEE in a new tab)
Defines the VHDL language — types, the simulation cycle, and the semantics a conforming analyser and simulator must implement. Synthesis restrictions and vendor coding rules are tool behaviour, not language rules.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the VHDL curriculum.
