VHDL · Chapter 6.1 · Combinational Logic Design
Modeling Combinational Logic
Combinational logic is any circuit whose outputs are a pure function of its current inputs. There is no clock and no stored state, so the outputs simply settle to a value whenever the inputs change. VHDL gives you two ways to describe it: concurrent assignments and the combinational process, and both must obey the same short set of golden rules. Assign every output for every input so no latch is inferred, react to every input so simulation matches synthesis, and never let a signal feed back on itself. This opener sets up the mental model and those rules, and the rest of the module applies them to multiplexers, decoders, and arithmetic.
Foundation15 min readVHDLCombinational LogicModelingLatch AvoidanceRTLDesign
1. Engineering intuition — a function, not a memory
Combinational logic is a mathematical function made of gates: present the inputs, and after the gates settle the outputs are a fixed function of those inputs — change an input and the output follows; there is nothing remembered from before. No clock, no state, no history. An adder, a multiplexer, a decoder, a comparator — all combinational. The entire discipline of modeling it well comes down to making sure your VHDL describes a pure function: every output defined for every input, reacting to every input, with no value feeding back on itself.
2. Formal explanation — two modeling styles
VHDL gives you two equivalent ways to describe combinational logic:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
-- STYLE 1 — concurrent assignments (Module 4): terse, great for simple functions.
y1 <= a when sel = '1' else b; -- 2:1 mux
sum <= std_logic_vector(unsigned(a) + unsigned(b)); -- adder
-- STYLE 2 — combinational process (Module 5): scales to multi-step / case decode.
proc : process (all)
begin
y2 <= b; -- default
if sel = '1' then y2 <= a; end if; -- override
end process;Both describe combinational hardware. Concurrent assignments (when/else, with/select,
expressions) are concise and ideal for single functions. The combinational process is better when
you have several outputs, a case decode, shared intermediate computation, or multi-step logic. They
are not different circuits — choose by clarity.
3. The three golden rules
Every correct combinational description obeys three rules; every classic bug breaks one of them.
4. Hardware interpretation — a settling logic cone
5. Simulation interpretation — outputs follow inputs
In simulation a correct combinational description re-evaluates whenever any input changes (concurrent
assignment: implicit full sensitivity; process: process(all)), and the output settles to the new
function value after a delta. There is no clock and no held state, so the waveform shows outputs that
track their inputs continuously.
Combinational output settles as a pure function of its inputs
8 cycles6. Synthesizer interpretation — gates, or an accidental latch
Synthesis turns a correct combinational description into a logic cone of gates. But if the description breaks rule 1 (an output unassigned on some path), synthesis cannot build a pure function — it must remember the old value, so it infers a latch, a tiny memory you did not ask for. If it breaks rule 3 (feedback), it builds a combinational loop with no defined steady state. The golden rules are precisely the conditions under which synthesis produces clean combinational gates and nothing else.
7. Production RTL — a clean multi-output combinational block
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
-- Multi-output combinational block, latch-free by default-then-override, full sensitivity.
alu : process (all)
begin
result <= (others => '0'); -- rule 1: default every output
zero <= '0';
case op is
when "00" => result <= std_logic_vector(unsigned(a) + unsigned(b));
when "01" => result <= std_logic_vector(unsigned(a) - unsigned(b));
when "10" => result <= a and b;
when others => result <= a or b; -- rule 1: every selector covered
end case;
if result = x"00" then zero <= '1'; end if; -- second output, also defaulted
end process;What hardware does this become? A combinational ALU cone: a result multiplexer over the four
operations and a zero-detect comparator. Every output is defaulted then conditionally driven (no
latch), the process is process(all) (full sensitivity), and nothing feeds back — all three rules
satisfied, so synthesis yields pure gates.
8. Debugging examples — one per golden rule
- Latch (rule 1). An output assigned in only some branches → synthesis infers a latch and the output holds stale values. Fix: default-assign every output at the top (lesson 6.3/6.4).
- Sim/synth mismatch (rule 2). A combinational process omits an input from its sensitivity list →
RTL simulation ignores that input's changes while the gate reacts. Fix:
process(all)(lesson 5.2). - Combinational loop (rule 3). A signal depends combinationally on itself → no stable value, or a delta-iteration-limit hang. Fix: break the loop with a register (lesson 6.8).
9. Common mistakes & what to watch for
- Partial output assignment. Any path that leaves an output unassigned infers a latch — default every output.
- Incomplete sensitivity in a process. Use
process(all)for combinational logic to avoid the RTL/synthesis mismatch. - Accidental feedback. A signal in its own combinational expression is a loop; register the feedback.
- Over-using processes for trivial logic. A one-line
when/elseis clearer than a process for a simple mux; pick the style by readability. - Mixing clocked and combinational logic in one process. Keep combinational and clocked behaviour in separate processes for clarity and correct inference.
10. Engineering insight & continuity
Combinational design is the art of describing a pure function and nothing more — and the three golden
rules are the entire safety net: complete assignment (no latch), complete sensitivity (no mismatch), no
feedback (no loop). Internalise them and every combinational block you write — mux, decoder, ALU,
priority encoder — comes out clean and synthesizable. The module now applies this foundation in detail:
the next lesson, Combinational Processes, develops the process(all) + default-then-override
pattern for multi-output logic, then Unintended Latches and Default Assignments dig into rule 1,
before Multiplexers, Decoders and Encoders, Arithmetic Circuits, and Combinational Loops
build out the standard combinational toolkit.