Skip to content

VHDL · Chapter 4.2 · Concurrent Statements

Concurrent Signal Assignment

This is the atom of concurrent VHDL: a target signal assigned an expression, written directly in an architecture body. It is a continuously-live driver, so whenever any signal in the expression changes, the target is recomputed and updated one delta later. In other words it is combinational logic, exactly equivalent to a process with a sensitivity list containing every signal the expression reads. This lesson shows how a concurrent assignment maps straight to gates, why its implicit full sensitivity makes it safe by construction, why each assignment contributes exactly one driver so that two assignments to one target is a multiple-driver bug, and how a self-referential right-hand side turns into a combinational loop.

Foundation14 min readVHDLConcurrent AssignmentCombinational LogicDriversnumeric_stdRTL

1. Engineering intuition — a gate written as one line

A combinational gate continuously computes its output from its inputs. A concurrent signal assignment is that gate in text: y <= a and b; means "y is always the AND of a and b." There is no clock, no storage, no sequence — just a live function from inputs to output. Whenever an input changes, the output follows (after the model's delta). If you can describe a piece of logic as "output equals some expression of inputs," a concurrent assignment is its most direct form.

2. Formal explanation — equivalent to a process on all RHS signals

A simple concurrent signal assignment has the form target <= expression; placed in the architecture body. Its defining property: it is equivalent to a process sensitive to every signal read in the expression.

concurrent_equals_process.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- these two describe the SAME hardware and behaviour:
y <= (a and b) or c;                 -- concurrent signal assignment
 
process (a, b, c)                    -- the equivalent process: sensitive to ALL RHS signals
begin
  y <= (a and b) or c;
end process;

That implicit, automatically-complete sensitivity is why concurrent assignments cannot suffer the missing-sensitivity bug a hand-written combinational process can (lesson 3.5): the expression's inputs are the sensitivity, by definition. Each concurrent assignment is also exactly one driver for its target (lesson 3.5).

3. Production-quality RTL — gates, muxes, and arithmetic

Concurrent assignments express any combinational function directly:

combinational_with_concurrent_assigns.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
-- logic gate:
y      <= a and b;
-- a 2:1 mux (a conditional expression — the long form is lesson 4.3):
m      <= d0 when sel = '0' else d1;
-- arithmetic (numeric_std): an adder driving an 8-bit bus
sum    <= std_logic_vector(unsigned(x) + unsigned(y));
-- bit manipulation: concatenation and slicing are pure combinational nets
packed <= hi(3 downto 0) & lo(3 downto 0);

What hardware does this become? Each line is a combinational block driving its target net: an AND gate, a 2:1 multiplexer, an 8-bit adder, and wiring (concatenation is free routing). None hold state; all recompute continuously.

4. Hardware interpretation — one driver, combinational logic

concurrent assignment as a combinational block with implicit full sensitivity driving a netalwayswatcheddrivesRHS signalsa, b, c (implicitsensitivity)combinational logicevaluates the expressionone driversources the target nettarget signalrecomputed on any inputchange12
A concurrent signal assignment is a combinational logic block with an implicit sensitivity to every signal in its expression. The block continuously computes the expression and drives the target net — exactly one driver for that net. Because the inputs of the expression ARE the sensitivity, the logic is complete by construction. Two concurrent assignments to the same target would be two drivers on one net, i.e. the multiple-driver/resolution case from lesson 3.6, almost always an error for ordinary logic.

5. Simulation interpretation — re-evaluate on any input event

In simulation the assignment behaves as its equivalent process: any event on a signal it reads wakes it, it re-evaluates the expression, and it schedules the target one delta later (lesson 3.4). So the target tracks its inputs with a one-delta lag — the signature of combinational logic in the event-driven model.

event flow: RHS change re-evaluates expression and updates target one delta laterAny RHS signalchangesimplicit sensitivity firesEvaluate expressioncompute new target valueSchedule targetonto its single driverDelta cycletarget updatesFanout wakesdownstream logicre-evaluates12
The event flow of a concurrent assignment. An event on any right-hand-side signal wakes the (implicit) process; it evaluates the expression; it schedules the target onto its driver; one delta later the target updates and its fanout wakes. Because the sensitivity is exactly the expression's inputs, every relevant change triggers a re-evaluation — combinational behaviour with no missing-input gaps.

y <= (a and b) or c — the target tracks its inputs one delta after each change

8 cycles
y <= (a and b) or c — the target tracks its inputs one delta after each changea=1,b=1 → (a and b)=1 → y follows one delta latera=1,b=1 → (a and b)=1 …c=1 keeps y=1 even as a/b change — pure combinational trackingc=1 keeps y=1 even as …a01111000b00111110c00001100y00011110t0t1t2t3t4t5t6t7
y continuously equals (a and b) or c, updating one delta after any of a, b, c changes. There is no storage: every input change re-evaluates the expression. This is combinational logic expressed as a single concurrent statement, behaving exactly like the equivalent always-sensitive process.

6. Debugging example — the accidental combinational loop

Expected: a concurrent assignment computes a value. Observed: the simulator stalls with a delta iteration-limit error, or the target is 'X'/oscillating. Root cause: the target appears in its own expression with no register in between — y <= y xor a; — so it is sensitive to itself and re-triggers every delta, a zero-delay combinational loop (lesson 3.4). (The sibling failure is assigning the same target from two concurrent statements, creating two drivers and resolution, lesson 3.6.) Fix: break the self-reference by registering the feedback in a clocked process, or remove the unintended loop. Engineering takeaway: a concurrent assignment whose target feeds its own expression is a comb loop; cross it with a register so each value lasts a clock.

comb_loop_and_fix.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- WRONG: y depends on itself with no register → delta-cycle oscillation.
y <= y xor a;                 -- combinational loop, no fixed point
-- RIGHT: register the feedback so it advances once per clock.
process (clk) begin
  if rising_edge(clk) then
    y <= y xor a;             -- a clocked toggle/accumulator, settles each cycle
  end if;
end process;

7. Common mistakes & what to watch for

  • Self-referential expressions. t <= f(t) with no register is a combinational loop; register the feedback.
  • Two concurrent assignments to one target. That is two drivers (resolution, lesson 3.6) — for ordinary logic, use one assignment, or a conditional/selected form (lessons 4.3/4.4).
  • Expecting it to store a value. A concurrent assignment is combinational; it recomputes continuously and holds nothing across time on its own.
  • Thinking it runs "in order" with neighbours. It is concurrent and order-independent (lesson 4.1); chained assignments are not sequential steps.
  • Reaching for a process when one line suffices. Simple combinational functions read best as a concurrent assignment; reserve processes for clocked logic or genuinely sequential descriptions.

8. Engineering insight

The concurrent signal assignment is the cleanest expression of "hardware is always computing": one line, one driver, one combinational function, with a sensitivity that is automatically exactly its inputs. That automatic completeness is a real safety advantage over hand-written combinational processes, which can drop an input from the sensitivity list and mis-simulate. Use concurrent assignments as your default for combinational logic — they are concise, loop-and-latch resistant, and map transparently to gates — and step up to conditional/selected forms or processes only when the logic needs the extra structure they provide.

9. Summary

A concurrent signal assignment, target <= expression;, is the basic concurrent statement: a continuously-live driver equivalent to a process sensitive to every signal it reads. It is combinational logic, updates the target one delta after any input changes, and is exactly one driver — so two assignments to one target is the multiple-driver case, and a self-referential expression is a combinational loop.

10. Learning continuity

You now have the plain assignment. Real combinational logic usually needs to choose between values, and the next lessons add that structure on top of this base: Conditional Signal Assignment (when/else) expresses priority-style selection (a mux/priority network), and after it Selected Signal Assignment (with/select) expresses a clean case-style decode — both still concurrent, still single-driver, still combinational, just more expressive than a bare expression.