Computer Organization & Embedded System — Hardware Description Language and IC Technology, NEC licence examination syllabus (Nepal Engineering Council).
Combinational Logic in VHDL: no memory, just wires and gates
If it doesn't need a clock, it's combinational — and dataflow style is usually the cleanest way to write it.
Half Adder (dataflow style)
architecture DATAFLOW of HALF_ADDER is
begin
S <= A xor B;
C <= A and B;
end DATAFLOW;
2-to-1 Multiplexer (with-select style)
architecture DATAFLOW of MUX2 is
begin
with SEL select
Y <= A when '0',
B when '1',
'0' when others;
end DATAFLOW;
4-to-1 Multiplexer (when-else style)
Y <= I0 when SEL="00" else
I1 when SEL="01" else
I2 when SEL="10" else
I3;
2-to-4 Decoder
architecture DATAFLOW of DECODER is
begin
Y(0) <= not A(1) and not A(0);
Y(1) <= not A(1) and A(0);
Y(2) <= A(1) and not A(0);
Y(3) <= A(1) and A(0);
end DATAFLOW;
Notice the pattern: every dataflow-style output is a concurrent signal assignment (<=) built directly from a Boolean equation — exactly the same equations you'd get from a truth table or K-map.
💡 Practice writing VHDL for: full adder, 4-bit comparator, and a 3-to-8 decoder using the same dataflow pattern shown above — these are the most commonly asked combinational-circuit codes.
The rule behind every example above
All these architectures use signal assignment (<=), and the reason is worth stating because it is what makes them describe hardware rather than a program.
⚡ Signals versus variables
Signal (<=)Models a wire. Assignment is scheduled, not immediate — inside a process the new value appears only after the process suspends.
Variable (:=)Models local storage inside a process. Updates immediately, like an ordinary programming assignment.
Concurrent statements outside a process — which is all of the dataflow examples above — execute simultaneously and continuously, not in the order written. Swapping two lines of a dataflow architecture changes nothing, because they describe wires that all exist at once. That is the fundamental difference between an HDL and a programming language, and the misunderstanding that produces most first-year VHDL bugs.
💡 A useful test: if reordering your statements changes the behaviour, you have written sequential code where hardware was wanted. In genuinely combinational dataflow VHDL, order is irrelevant.
The others clause is not optional
Notice '0' when others in the multiplexer. It looks like defensive padding for a signal that can only be '0' or '1'. It is not.
VHDL's std_logic has nine values, not two — including 'X' (unknown), 'Z' (high impedance), 'U' (uninitialised) and '-' (don't care). A with-select must cover every one, so when others is required for the code to compile at all.
💡 The same rule causes the commonest synthesis warning students meet: an incomplete if-else or case in a process implies "hold the previous value", which infers a latch — unintended memory in what was supposed to be combinational logic. Assigning a default value at the top of the process, or always including an else, prevents it.
Three styles, one circuit
✍️ How the same hardware gets written
DataflowBoolean expressions and with-select/when-else. Closest to the logic equations, best for small combinational blocks — the style used above.
BehaviouralProcesses with sequential statements. Best for state machines and anything clocked.
StructuralComponent instantiation and wiring. Best for assembling verified blocks into a larger design — a netlist in text form.
💡 The styles can be mixed in one architecture, and a real design usually does: structural at the top to connect modules, behavioural inside each for the clocked logic, dataflow for the small combinational pieces. A question asking which style is "best" is asking which suits the block, not which is superior.