Skip to content

VHDL · Chapter 4.1 · Concurrent Statements

The Concurrent Execution Model

Software runs one line after another. Hardware does not, because every gate is always active, all at once, and VHDL models exactly that. An architecture body is a set of concurrent statements that execute simultaneously, so their textual order is irrelevant: swapping two lines changes nothing, because they were never running in sequence. Each statement, whether a concurrent assignment, a process, a component instance, or a generate, is an event-driven block that re-evaluates only when one of its inputs changes, and the delta-cycle engine you met earlier coordinates them into a deterministic result. Internalizing this, thinking parallel rather than sequential, is the dividing line between writing software-shaped VHDL that mis-synthesizes and writing real hardware.

Foundation14 min readVHDLConcurrencyConcurrent StatementsEvent-DrivenRTLDataflow

1. Engineering intuition — hardware is always on

Picture a board of gates: every gate continuously watches its inputs and drives its output. None of them "waits its turn." A VHDL architecture describes precisely that — a collection of always-active blocks running in parallel. There is no program counter stepping through the statements; they all exist and react at the same time. The moment you accept that the architecture is a netlist of concurrent blocks, not a sequence of instructions, VHDL stops surprising you.

2. Formal explanation — concurrent statements and order independence

Everything written directly in an architecture body (between begin and end) is a concurrent statement. The major kinds are: concurrent signal assignments (lesson 4.2), processes, component/entity instantiations, and generate statements. They all execute concurrently, and crucially their order is immaterial:

order_does_not_matter.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
architecture rtl of logic is
begin
  y <= a and b;     -- these three are concurrent;
  z <= y or c;      -- writing them in ANY order
  w <= a xor c;     -- produces the identical hardware and behaviour
end architecture;
-- Reordering the lines changes nothing: each is an always-active block,
-- re-evaluated when its own inputs change — not when the line "executes".

Each statement behaves as if it has an implicit sensitivity to the signals it reads: when any of those change, it re-evaluates. A process makes this explicit with its sensitivity list; a concurrent assignment has it implicitly.

3. Production-quality RTL — parallel blocks sharing nets

A real architecture is several concurrent blocks wired together by shared signals — a small netlist:

parallel_blocks.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
architecture rtl of unit is
  signal sum : unsigned(7 downto 0);
begin
  -- concurrent assignment: combinational adder (always live)
  sum <= unsigned(a) + unsigned(b);
 
  -- process: a register (event-driven on clk)
  reg : process (clk) begin
    if rising_edge(clk) then q <= std_logic_vector(sum); end if;
  end process;
 
  -- component instance: a sub-block, also running concurrently
  u_chk : entity work.range_check port map (clk => clk, v => sum, bad => overflow);
end architecture;

What hardware does this become? Three pieces of always-active hardware — an adder, a register, and a checker sub-block — coexisting and communicating through sum. They are not steps; they are parts, all live simultaneously.

4. Hardware interpretation — concurrency is the parallelism of silicon

architecture as parallel concurrent blocks communicating through shared signalssuminputs a, b, clkshared netsconcurrent assignadder → sum (always live)processregister (on clk)componentchecker sub-blockoutputs q, overflowdriven concurrently12
An architecture as a set of concurrent blocks. Each concurrent statement — a concurrent assignment, a process, a component instance — is always-active hardware that watches its input signals and drives its outputs. They communicate only through shared signals (nets), and they all run in parallel. There is no execution order between them; the design is a netlist, not a sequence. This is the direct model of real hardware, where every element is continuously active.

5. Simulation interpretation — event-driven scheduling

A simulator cannot literally run everything at the same instant, so it emulates concurrency with the event-driven engine from lesson 3.4: a signal change is an event that wakes every concurrent statement sensitive to that signal; each evaluates and schedules its own outputs one delta later; the deltas settle; then real time advances. The result is identical for any statement order, which is what makes concurrency deterministic.

event-driven scheduling waking concurrent statements and settling over deltasnew eventsSignal eventan input changesWake all sensitivestatementsevery block reading thatsignalEach evaluates inparallelschedules its outputs atT+ΔDelta cycle appliesupdatesmay raise new eventsStable → advance timesame result for any order12
How the engine emulates concurrency. A signal change is an event placed on the queue; every concurrent statement sensitive to that signal is resumed; each evaluates and schedules its outputs one delta ahead; the delta cycle applies them, which may raise further events, until the design is stable and time advances. Order independence falls out: regardless of the textual order of statements, the same events wake the same blocks and reach the same fixed point.

Two concurrent statements react independently and simultaneously to their own inputs

8 cycles
Two concurrent statements react independently and simultaneously to their own inputs'a' changes → y=(a and b) re-evaluates; w=(a xor c) re-evaluates too'a' changes → y=(a and…independent blocks update whenever THEIR inputs changeindependent blocks upd…a01110001b00011100c11000111y00010000w10110110t0t1t2t3t4t5t6t7
y = a and b and w = a xor c are two concurrent statements. Each tracks only its own inputs and updates one delta after they change — simultaneously and independently, with no ordering between them. This is concurrency: many always-active blocks, each reacting to its own signals, exactly as separate gates would.

6. Debugging example — the sequential-thinking bug

Expected: a beginner writes three concurrent assignments expecting them to "run in order" and share a temporary. Observed: the result is not what sequential reading predicts — values look "off by a delta" or a temporary never carries the intended intermediate. Root cause: the statements are concurrent, not sequential; the "temporary" signal updates one delta later and is read by the others using its old value, and reordering would not help because order is irrelevant. Fix: if step-by-step computation with immediate intermediate values is needed, do it inside a single process using variables (lesson 3.1); keep concurrent statements for genuinely parallel logic. Engineering takeaway: when concurrent results defy a top-to-bottom reading, the bug is the sequential mental model — move ordered computation into a process, or accept the delta-true parallel behaviour.

sequential expectation vs concurrent reality
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- WRONG expectation: 'tmp' is computed then immediately reused, as if sequential.
tmp <= a + b;              -- concurrent: tmp updates one delta later
y   <= tmp * 2;            -- reads the OLD tmp → not "this line's" value
-- FIX: for ordered, immediate intermediates, use a process + variable:
process (a, b)
  variable t : unsigned(7 downto 0);
begin
  t := unsigned(a) + unsigned(b);     -- immediate
  y <= std_logic_vector(t * 2);       -- uses the new t
end process;

7. Common mistakes & what to watch for

  • Assuming statement order matters. Concurrent statements are order-independent; reordering them changes nothing.
  • Expecting sequential, immediate computation between concurrent statements. A signal updates one delta later; chained concurrent assignments are not step-by-step. Use a process+variables for that.
  • Treating an architecture like a function body. It is a netlist of parallel blocks, not a sequence of instructions.
  • Forgetting each block is event-driven. A concurrent statement re-evaluates only when its inputs change — define those inputs (implicitly via the expression, or a complete sensitivity list in a process).
  • Hiding ordered logic in many concurrent lines. If the algorithm is inherently sequential, express it in one process, not a fan of concurrent assignments.

8. Engineering insight

Concurrency is not a VHDL feature bolted onto a programming language — it is the language admitting what hardware is: massively parallel, always-active, communicating through nets. The payoff of embracing it is that your code's structure mirrors the silicon's structure, so it synthesises predictably and reads like a schematic. The event-driven engine guarantees this parallel model is deterministic, so you never reason about statement order — only about which signals feed which blocks. Every later construct (processes, combinational and sequential logic, FSMs, structural hierarchy) is a kind of concurrent statement; this model is the frame they all sit in.

9. Summary

A VHDL architecture is a set of concurrent statements that execute simultaneously, so their textual order is irrelevant. Each — concurrent assignment, process, component, generate — is an event-driven block re-evaluated when its inputs change, coordinated deterministically by the delta-cycle engine. This is the direct model of always-active hardware, and thinking sequentially about it is the classic source of RTL bugs.

10. Learning continuity

Now that you see the architecture as parallel, event-driven blocks, the next step is the simplest such block. Concurrent Signal Assignment examines target <= expression; on its own — a continuously-live driver equivalent to a process sensitive to everything it reads, and the purest form of combinational logic — before the module adds structure with conditional (when/else) and selected (with/select) assignments, instantiation, and generate.