Skip to content

VHDL · Chapter 5.3 · Sequential Statements & Processes

How a Process Executes

This is the anchor for the whole module. Every sequential construct that follows, if, case, loops, variables, wait, and sequential signal assignment, is just statements inside a process, and to use any of them correctly you need one precise mental model of how a process actually executes. A process stays suspended until a trigger fires, then runs its body top to bottom in zero simulated time, updating variables immediately and scheduling signals one delta later. It suspends, and the scheduled updates take effect, waking whatever reads them. Get this model exact and the rest of the module becomes obvious, including the bugs, like stale signals and accidental latches, that all trace back to it.

Foundation22 min readVHDLProcessExecution ModelDelta CycleSchedulerVariablesSignals

1. Engineering intuition — a triggered, run-to-completion engine

A process is a small engine with three states: asleep, running, asleep again. It sleeps until a trigger (a sensitivity-list signal changing, or a wait condition) fires; it then runs its body from top to bottom all at once, in zero simulated time; then it goes back to sleep. Nothing in the body "takes time" by itself — time only passes between wake-ups. The two things that make this subtle are: (1) variables change the instant you assign them, but signals do not — they are scheduled and only update after the process suspends; and (2) the ordered, top-to-bottom reading is a description, not a sequence of clock ticks. Hold those two ideas and every sequential statement in this module behaves predictably.

2. Historical context — VHDL is an event-driven simulator

VHDL began (in the 1980s, for the US DoD) as a language to document and simulate digital systems, not primarily to synthesise them. That heritage is why the execution model is an event-driven discrete-event simulation: time advances from event to event, signals carry values that change at scheduled times, and processes react to those changes. Synthesis came later and layered a "this subset describes hardware" interpretation on top. So when a process's behaviour seems surprising, remember it is first a simulator obeying event-driven rules — and the synthesisable subset is the part of those rules that maps cleanly to gates and flip-flops.

3. The execution model, formally — the suspend/resume cycle

A process repeats one cycle for its entire life:

process suspend-resume lifecycle with zero-time body and delta-delayed signal updatesback to sleepSuspendedwaiting for a triggerTrigger firessensitivity signal changes/ wait satisfiedRun body top→bottomZERO simulated timeVariables updateimmediatelysignals only SCHEDULEDReach end process /waitprocess suspendsDelta: applyscheduled signalsmay wake this/otherprocesses12
The process execution lifecycle. A process is suspended until a trigger fires (a sensitivity-list signal changes, or a wait condition becomes true). It resumes and runs its sequential body top to bottom in ZERO simulated time: variable assignments take effect immediately; signal assignments are scheduled (not yet applied). On reaching end process (or the next wait) it suspends. One delta cycle later the scheduled signal updates are applied, which may wake this or other processes — and the cycle repeats. Time advances only between wake-ups, never inside the body.

4. The simulator interpretation — the scheduler and delta cycles

Zoom out from one process to the whole simulation. The simulator runs a loop: at the current time it updates the signals scheduled for now, resumes every process sensitive to those changes, lets each run to suspension (scheduling new signal updates one delta ahead), and repeats. When a pass produces no further signal changes at this time, time advances to the next event. The infinitesimal, ordered steps within one instant are delta cycles (lesson 3.4).

event-driven scheduler: update signals, resume processes, run to suspend, delta or advance timeyes (T unchanged)noApply signal updatesdue at Tdrivers project new valuesResume sensitiveprocessesall that read a changedsignalEach runs to suspendschedules its signals atT+deltaMore updates due atT?yes → another delta cycleStable → advance timeto the next scheduled event12
The simulator scheduler that drives every process. At time T the engine applies signal updates due now, then resumes all processes sensitive to those signals; each process runs to suspension and schedules its own signal updates at T+delta. If more updates are due at T, the engine runs another DELTA cycle (same real time); when stable, real time advances. Many processes are coordinated by this one loop, which is why their relative order never matters — only the data dependencies through signals do.

5. Variables vs signals during execution — the crux

The single most important consequence of the model: inside a process, a variable assignment (:=) takes effect immediately, so a later line sees the new value; a signal assignment (<=) is scheduled, so a later line in the same wake-up still reads the old value, and the update appears only after the process suspends.

variable immediate update versus signal scheduled update inside a processimmediatescheduled (delta)v := exprwrite in placelater line reads vsees NEW value (immediate)s <= exprschedule onto driverlater line reads ssees OLD value (untildelta)12
Variable vs signal timing within one process run. A variable assignment updates the variable in place immediately, so subsequent statements in the same wake-up read the new value. A signal assignment schedules a transaction on the signal's driver; the signal keeps its old value for the rest of this run and only updates one delta after the process suspends. This is why intermediate computation uses variables, and why a signal read right after writing it returns the previous value.

Same computation, variable vs signal: the variable result is one cycle earlier

8 cycles
Same computation, variable vs signal: the variable result is one cycle earlierclocked process: v := a; y_var <= v*2 → uses THIS cycle's aclocked process: v := …tmp_sig <= a; y_sig <= tmp_sig*2 → tmp_sig is a cycle behindtmp_sig <= a; y_sig <=…clka22553377y_var04410106614y_sig0044101066t0t1t2t3t4t5t6t7
In a clocked process, computing through a VARIABLE (v := a; y_var <= v*2) uses this cycle's value, so y_var = 2*a one clock later. Computing through an intermediate SIGNAL (tmp_sig <= a; y_sig <= tmp_sig*2) reads the OLD tmp_sig, inserting an extra cycle so y_sig lags by two. Same arithmetic, different timing — entirely explained by immediate vs scheduled updates.

6. Hardware interpretation — settling vs capture

The same execution model produces two kinds of hardware depending on how the body is written:

combinational settling versus registered capture from the same execution modelcomb styleclocked styleprocess executessuspend / run / suspendno clock guardoutputs settle →combinational logicrising_edge(clk)guardvalues captured → registers12
How the execution model maps to hardware. A combinational process (complete sensitivity list, no clock guard) re-runs whenever any input changes and its outputs settle to a function of the inputs — combinational logic. A clocked process (sensitive to clk, guarded by rising_edge) runs only at the edge and captures values into registers. The body's execution is the same suspend/run/suspend cycle; the presence or absence of a clock-edge guard is what makes the result settle (logic) or capture (flip-flops).

7. Synthesizer interpretation — order is description, not time

Synthesis reads the process body as a specification of logic, not a sequence of timed steps. The top-to-bottom order and last-assignment-wins semantics (lesson 5.9) define what the final value of each signal is as a function of the inputs; the synthesiser then builds combinational logic (or, at a clock edge, registers) that computes those values in parallel. So "sequential" in synthesis means "evaluate the body's data flow to a result," collapsed into a single combinational cone or a register update — no stepping exists in the gates.

order_is_specification.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- The ordered body specifies the FINAL value of y; synthesis builds it as parallel logic.
process (sel, a, b)
begin
  y <= a;                 -- default
  if sel = '1' then
    y <= b;               -- override (last assignment wins)
  end if;
end process;
-- Synthesises to: y = (sel = '1') ? b : a  — a single 2:1 mux, evaluated in parallel.

8. Production RTL — the canonical process patterns

canonical_processes.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
 
-- (A) Combinational process: complete sensitivity, default-then-override, no latch.
comb : process (all)                       -- VHDL-2008: every read signal
begin
  y <= (others => '0');                     -- default assignment covers all paths
  if  sel = "01" then y <= a;
  elsif sel = "10" then y <= b;
  end if;                                    -- no else needed: default already drives y
end process;
 
-- (B) Clocked process with synchronous reset: registers.
sync : process (clk)
begin
  if rising_edge(clk) then
    if rst = '1' then count <= (others => '0');
    else              count <= count + 1;    -- numeric_std arithmetic on unsigned
    end if;
  end if;
end process;
 
-- (C) Local computation with a variable, registered result (immediate intermediate).
acc : process (clk)
  variable sum_v : unsigned(7 downto 0);
begin
  if rising_edge(clk) then
    sum_v := unsigned(a) + unsigned(b);      -- immediate
    result <= std_logic_vector(sum_v + 1);   -- uses THIS cycle's sum_v
  end if;
end process;

What hardware does this become? (A) a multiplexer feeding y with a guaranteed default (latch- free); (B) an 8-bit counter register with synchronous reset; (C) an adder whose result is registered, with sum_v realised as combinational logic feeding the final register — the variable is intermediate wiring, not a separate storage element.

9. Debugging examples — every classic bug traces to this model

(i) The stale-signal "extra cycle." Expected: a two-step computation completes in one cycle. Observed: the result is a cycle late. Root cause: an intermediate signal was read right after being assigned, returning its old value (Section 5). Fix: use a variable for the intermediate. Takeaway: signals update after suspend; variables update immediately.

(ii) The accidental latch. Expected: combinational logic. Observed: synthesis infers a latch. Root cause: a path through the process leaves an output unassigned, so it must "hold" — memory (lesson 6.3). Fix: a default assignment at the top so every path drives the output. Takeaway: the model holds the old value when you do not assign; defaults prevent that.

(iii) The hung simulation. Expected: the process runs. Observed: the simulator never advances. Root cause: no sensitivity list and no wait — the process never suspends, looping in zero time (lesson 5.1). Fix: add a trigger. Takeaway: a process must be able to suspend.

stale_signal_fix.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- BUG: intermediate SIGNAL read after write → old value → extra cycle.
process (clk) begin
  if rising_edge(clk) then
    tmp_s <= unsigned(a) + unsigned(b);     -- scheduled
    y     <= std_logic_vector(tmp_s + 1);   -- reads OLD tmp_s
  end if;
end process;
-- FIX: VARIABLE intermediate → immediate, same-cycle result.
process (clk)
  variable tmp_v : unsigned(7 downto 0);
begin
  if rising_edge(clk) then
    tmp_v := unsigned(a) + unsigned(b);     -- immediate
    y     <= std_logic_vector(tmp_v + 1);   -- uses NEW tmp_v
  end if;
end process;

10. Engineering tradeoffs

  • Variables vs signals for intermediates. Variables give immediate, same-cycle computation and fewer registers; signals are visible across processes and to waveforms but cost a delta of latency per stage. Use variables for local math, signals for inter-process communication and observable state.
  • One big process vs several small ones. A large process can express complex ordered behaviour but is harder to read and review; several focused processes (one per register bank or function) are clearer and compose through signals. Prefer small, single-purpose processes.
  • Combinational process vs concurrent assignment. A process scales to multi-step logic and case decode; a concurrent when/else/with/select is terser for simple selection. Choose by complexity.
  • Sensitivity list discipline. process(all) removes the incomplete-list bug class for combinational logic at the cost of requiring VHDL-2008; explicit lists are portable but error-prone.

11. Interview framing

Interviewers probe this model because it separates engineers who understand VHDL from those who pattern-match syntax. Expect to explain: why a signal read after assignment gives the old value; why a variable does not; what a delta cycle is; why statement order in a process does not mean clock steps; and how the same process becomes combinational or registered. A crisp answer references the suspend/run/suspend cycle and immediate-vs-scheduled updates — exactly this page.

Q&A

  • Q: Inside a process, you assign s <= x; then read s on the next line. What do you get? A: The old value of s. Signal assignments are scheduled; s updates one delta after the process suspends, so the same wake-up still sees the previous value.
  • Q: How would you get the new value immediately? A: Use a variable (v := x;), which updates in place, then read v.
  • Q: Does statement order in a process imply timing? A: No. The body runs in zero simulated time; order defines the final value of each signal (last-assignment-wins), which synthesis builds as parallel logic. Time passes only between wake-ups.
  • Q: What is a delta cycle and why does it exist? A: An infinitesimal, ordered step within one simulation time so zero-delay logic settles deterministically; scheduled signal updates are applied on the next delta.
  • Q: Why does an unassigned output in a combinational process infer a latch? A: The model holds a signal's value when no driver updates it; an unassigned path means "keep the old value" — memory. A default assignment fixes it.

12. Practice exercises

  1. Trace it. For a clocked process with tmp_s <= a; y <= tmp_s; versus tmp_v := a; y <= tmp_v;, draw the waveforms of y for a changing a and state the cycle difference.
  2. Latch hunt. Write a combinational case process that assigns y in only three of four branches; identify the inferred latch and fix it two ways (default assignment; full coverage).
  3. Delta count. Given b <= a; c <= b; as two concurrent assignments, how many delta cycles for a change on a to reach c? Now put both in one process with variables — what changes?
  4. Reset styles. Convert the counter in Section 8(B) to an asynchronous reset and adjust the sensitivity list correctly.
  5. Refactor. Take a 40-line single process mixing combinational and clocked logic and split it into a combinational process and a clocked process communicating by signal; verify identical behaviour.

13. Key takeaways

  • A process is a suspend → run-to-completion (zero time) → suspend engine, coordinated by an event-driven scheduler using delta cycles.
  • Variables update immediately; signals are scheduled and update one delta after the process suspends — the source of stale-signal bugs and the reason variables are used for intermediates.
  • Order in the body is description, not time: it defines each signal's final value (last-assignment-wins), which synthesis builds as parallel logic — combinational settling without a clock guard, registered capture with one.
  • The classic bugs — extra-cycle latency, inferred latches, hung simulations — are all direct consequences of this model, and each fix follows from it.
  • This is the reference model for the rest of Module 5: if, case, loops, variables, wait, and sequential signal assignment are all just statements executing inside this cycle.

14. Summary & next step

You now have the complete execution model: how a process wakes, runs its body in zero time with variables immediate and signals scheduled, suspends, and lets the scheduler apply updates over delta cycles — and how that single model yields combinational or registered hardware. With this anchor in place, the remaining sequential statements are straightforward applications of it. The module continues with the body's decision constructs — the if statement and the case statement — then loops, variables in processes, the wait statement, and sequential signal assignment with last-assignment-wins, each building on the model established here.