Foundations — Combinational logic in HDL
Before you can read the parent note Combinational logic in HDL, you must own every little symbol it throws at you. This page builds them one at a time, from nothing, each with a picture. Nothing here assumes you have seen Verilog, gates, or Boolean algebra before.
0. What is a "signal"? (the atom of everything)
Picture a wire as a water pipe. The pipe is either pressurised (call that 1) or empty (call that 0). Nothing in between matters — we round every voltage to one of these two buckets.

y drawn twice — empty pipe (top, state 0) and full amber pipe (bottom, state 1). Observe that a signal is one named wire whose single value is always exactly one of these two buckets.
Why the topic needs it: every input (a, b, c, sel, enable) and every output (y, s, cout) in the parent note is a signal. When the note says "output depends on inputs," it means the value on the output wire is decided by the values on the input wires.
1. The two symbols 0 and 1 — and what "depends on" means
Every digital value is 0 or 1. That is the whole alphabet.
When we say output depends on inputs, we mean: for each choice of input values, there is one fixed output value. Change an input, the output may change. That "for each input → one output" idea is the definition of a function, which is our next symbol.
2. f(inputs) — the function arrow
Picture a vending machine: you press a combination of buttons (inputs), and one snack drops (output). The same button-press always gives the same snack. It does not care what you bought yesterday.

a, b, sel (cyan arrows) enter the box f, and one output wire y (amber arrow) leaves. Observe that each set of input values produces exactly one output value, and nothing about yesterday's inputs enters the box.
Why the topic needs it: the parent's central line is combinational logic. "No memory" is just another way of saying "the output is a pure function of the present inputs — yesterday's inputs are not part of ."
3. The truth table — a function written out in full
A function over 0/1 inputs has only finitely many input combinations, so we can just list them all. That list is a truth table.
The parent's 2-to-1 selector has three one-bit inputs — sel, a, and b — where a and b are themselves signals (each 0 or 1), not constants. The rule is: "when sel is 0, copy a to y; when sel is 1, copy b to y." Written out fully over all input rows:
| sel | a | b | y |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 1 |
| 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 0 |
| 1 | 1 | 1 | 1 |
Read the top half (sel=0): y copies whatever a is, ignoring b. Read the bottom half (sel=1): y copies whatever b is, ignoring a. The compact "sel | y" form with entries a and b is just shorthand for these eight rows.
The picture: a lookup sheet. Find the row matching your inputs, read off the output.
Why the topic needs it: the parent derives every circuit (MUX, full adder) from a truth table. Fully listing every row is also how you guarantee you covered every case — which is the whole latch-avoidance discipline in disguise.
Recall Why exactly
rows?
Each input independently is 0 or 1 (2 choices). With inputs the choices multiply: .
Question: How many rows for a 3-input truth table? ::: .
4. Boolean operators — the symbols &, |, ~, ^
These four symbols combine 0/1 signals into new 0/1 signals. Each one is a tiny truth table. We use these specific operators because every digital function can be built from them — they are the complete toolbox. (This is the world of Boolean algebra and Karnaugh maps.)

1 cells — AND lights only on the last row, OR on any row with a 1, XOR only when the two inputs differ, and NOT simply flips.
Notice the parent note writes AND/OR/NOT with maths notation, not the code symbols. Each deserves its own clear definition so you never confuse them or their precedence:
Putting the precedence rules together, the parent's
reads, in plain words: "y is 1 when (sel is 0 AND a is 1) OR (sel is 1 AND b is 1)." That matches the eight-row table from Section 3 exactly.
5. assign — a permanent equation
First, the physical thing an equation turns into:
Picture literal metal: the gates named by the equation are soldered to y forever. There is no "sometimes" — y is always driven.
Why the topic needs it: because y can never be left undriven, an assign is automatically combinational. That is why the parent calls it the safest idiom.
6. always @(*) — a described block, and its trap
Why @(*) and not a hand-written list? If you list only @(a) but the recipe also reads b, the simulation ignores b changes, while the real synthesized gates still use b. Simulation would then disagree with silicon. @(*) includes everything read, so they match. This is the "sim ≠ silicon" warning in the parent.
The trap: inside such a block, if some path forgets to give y a value, the tool must keep the old value — and keeping an old value requires memory: a latch (the one-bit storage element from Section 2). So the rule: assign every output on every path (a default up top, or an else/default).

enable=0 case, so the tool inserts a latch that keeps y's old value (amber warning). Right — a default y=0 written first, so every path assigns y and the logic stays pure combinational. Observe that the only difference is covering the missing case.
7. = vs <= — order of updates
Picture blocking = as dominoes in a line: each falls, then the next reacts — exactly how a signal ripples through chained gates in one instant. Picture non-blocking <= as a whole marching band stepping together on one drumbeat — like flip-flops all updating on the same clock edge.
Why the topic needs it: the parent's rule "combinational ⇒ blocking =" is because combinational logic behaves like rippling dominoes, not a synchronized band. Deeper treatment lives in Blocking vs Non-blocking assignments.
8. Putting it together — the prerequisite map
Read top to bottom: signals give us values, values give us functions and truth tables, those give us the Boolean toolbox (with its precedence rules), the toolbox becomes gates, and gates are expressed through the two HDL idioms — which feed the parent topic.
Equipment checklist
Test yourself — cover the right side and answer out loud.
What does HDL stand for, and what is it for?
What is a signal?
Why do digital circuits use only two values?
What does mean in words?
How many rows does a truth table with one-bit inputs have?
In the MUX table, are a and b constants or signals?
What does & do?
What does | do?
What does ~ do?
What does ^ (or ) do?
What does the overline mean?
~sel.What does a + mean inside a Boolean expression?
What do parentheses do in a Boolean expression?
Rank the precedence NOT, AND, OR, XOR tightest to loosest.
What is a 2-to-1 multiplexer?
sel.What is a gate?
Which signal type does an assign drive, and which does an always block assign?
assign drives a wire; always assigns a reg (still combinational in @(*)).Why is a continuous assign always combinational?
What does @(...) mean in Verilog?
What is a sensitivity list, and what does * do?
* auto-includes every signal the block reads.What is a simulation time-step?
What happens if a path leaves an output unassigned in always @(*)?
Blocking = behaves like what physical picture?
Non-blocking <= behaves like what physical picture?
Connections
- Combinational logic in HDL — the parent topic these foundations unlock.
- Boolean algebra and Karnaugh maps — where
& | ~ ^and truth tables come from. - Blocking vs Non-blocking assignments — the deep dive on
=vs<=. - Latch inference and how to avoid it — what goes wrong when a path is unassigned.
- Multiplexers, adders, decoders — the circuits you build once these symbols are yours.