Continuous Assignment

Assign statement, implicit continuous assignment.

Darshan N
Updated: 19 March 2026
12 min read

Continuous assignment is the primary mechanism for describing combinational logic in Verilog dataflow modeling. Unlike procedural assignments that execute inside always or initial blocks, continuous assignments are always active — they continuously drive the output net whenever any input changes. This makes them the natural hardware equivalent of connecting wires to combinational logic gates.

Verilog Continuous Assignment: Dataflow ModelingExplicit Continuous Assignmentwire out;assign out = a & b;Step 1: wire declared separatelyStep 2: assign drives the wireassign #5 out = a | b;With propagation delayDelay #5 is simulation-onlySynthesis tools ignore itassign {cout, sum} = a + b + cin;Concatenation on LHS allowedFull adder in one statementImplicit Continuous Assignmentwire out = a & b;Declaration and assignment combinedAutomatically creates continuousdriver on the wire at declarationwire #(3,5) out = a ^ b;rise delay=3, fall delay=5Both forms drive wire type onlyReg cannot be driven by assignContinuous: always activeRe-evaluates on ANY RHS change
Figure 1: Explicit assign statement versus implicit wire declaration assignment — both create permanently active combinational drivers

Core Concept: Continuous Assignment

The assign statement is used in Verilog dataflow modeling to continuously drive a net (wire) with the result of an expression. The key property is that a continuous assignment is always active throughout simulation. Whenever any signal on the right-hand side changes, the left-hand side is immediately re-evaluated and updated. This mirrors the behavior of real combinational logic gates, which continuously produce an output based on their current inputs.

A continuous assignment must drive a net type (such as wire or tri). It cannot drive a reg type, which is reserved for procedural assignments inside always and initial blocks. This is one of the most common source of compile errors for Verilog beginners. If a signal needs to be driven from both a continuous assignment and a procedural block, the design needs to be restructured.

Implicit Continuous Assignment

Verilog allows an implicit continuous assignment where the assignment is combined directly with the wire declaration. The syntax wire out = a & b; is completely equivalent to declaring wire out; followed by assign out = a & b; in two separate statements. The implicit form is more compact and is commonly used for simple combinational signals. Both forms create an identical continuous driver on the net.

Propagation Delay in Continuous Assignment

A propagation delay can be specified in the assign statement using the # operator, as in assign #5 out = a | b;. This means that whenever the right-hand side changes, the new value is assigned to out after 5 simulation time units. If the right-hand side changes again before the 5 units expire, the scheduled update is cancelled and a new update is scheduled for 5 units from the latest change. This models real gate propagation delay.

For more detailed delay modeling, Verilog supports separate rise and fall delays using the syntax assign #(rise, fall) out = expr; and three-value delays using assign #(rise, fall, turnoff) for handling high-impedance transitions. These detailed delay specifications are important for timing analysis simulations but are ignored by synthesis tools.

Mathematical Expression

A continuous assignment implements a purely combinational Boolean function. For a 1-bit assign statement, the output at any time T is given by OUT(T) = f(IN1(T), IN2(T), ..., INn(T)) where f is the Boolean expression on the right-hand side. With a delay D, the output becomes OUT(T+D) = f(IN1(T), IN2(T), ..., INn(T)), meaning the output reflects the input state at time T, but the update appears at time T+D. This is the standard inertial delay model used in Verilog.

Practical Understanding

Continuous assignments are the standard way to implement multiplexers, encoders, decoders, and arithmetic operations in synthesizable RTL. A 2-to-1 multiplexer is written as assign out = sel ? a : b; using the conditional operator. A 4-bit ripple carry adder output can be written with a single assign {cout, sum} = a + b + cin; statement, where the concatenation on the left-hand side captures both the carry-out and the sum bits in one expression.

In hierarchical designs, continuous assignments connect internal logic to module output ports. When a module output port is of type wire (the default for output ports in Verilog-2001 style), it must be driven by either an assign statement or by an instantiated submodule's output port — not by a procedural block unless the port is declared as output reg.

Numerical Example: Propagation Delay Calculation

Example
Given:
assign #8 f = (a & b) | c;
At T=10ns: a=1, b=1, c=0 (RHS becomes 1)
At T=15ns: a=0, b=0, c=0 (RHS becomes 0)
Timescale: 1ns/1ps

Why this formula applies:
Inertial delay model: update scheduled at T + delay.
If RHS changes again before delay expires, old update is cancelled.

Formula:
Output update time = Time of RHS change + Propagation delay

Substitution:
First change at T=10: f would update at T=10+8=18ns
Second change at T=15: cancels previous, f would update at T=15+8=23ns

Calculation:
f remains at old value (0) until T=23ns
At T=23ns, f = 0 (value from T=15 when RHS was 0)
The pulse that would have set f=1 is suppressed

Final Answer:
f never goes to 1. It stays 0 and gets 0 again at T=23ns. Pulse suppressed by inertial delay.
Exam Tip: The assign statement drives wire types only — driving a reg from assign is a compile error. For GATE, remember that continuous assignments execute in zero simulation time by default (delay is 0 unless specified). Also, the conditional operator in assign (assign out = sel ? a : b;) directly infers a multiplexer in synthesis.

Mechanism: How Continuous Assignment Updates Work

Continuous Assignment: Signal Update FlowRHS Signala, b, c changeExpression Re-evaluatedf(a, b, c) computedDelay Check#N specified?LHS Updatedwire = new valassign vs reg ruleassign drives: wire, trialways/initial drives: regoutput wire: use assignoutput reg: use alwaysCannot mix both on same signalwithout X-state conflictMultiple DriversTwo assign statementsdriving same wire:assign out = a & b;assign out = c | d;Results in X if values conflictAvoid in RTL designSynthesis Behaviorassign out = a & b;Maps to AND gateassign out = sel ? a : b;Maps to 2-to-1 MUXPropagation delay ignoredby synthesis tools
Figure 2: How continuous assignment propagates changes — RHS re-evaluation triggers LHS update through optional delay; synthesis maps expressions to combinational gates
  • Continuous assignment is always active. Any change on the right-hand side triggers immediate re-evaluation and update of the left-hand side wire.
  • Only wire and net types can be driven by assign. Reg types are driven only from always and initial procedural blocks.
  • Multiple assign statements driving the same wire result in contention and an X (unknown) value if the drivers conflict, since wire resolves by wired-logic.
  • Synthesis tools map assign expressions directly to combinational gate structures: AND, OR, XOR, MUX, adder, etc.

Quick Revision

  • assign drives wire only. procedural always drives reg only. Mixing both on same signal causes X.
  • Continuous assignment re-evaluates whenever any RHS signal changes. It is permanently active.
  • Implicit form: wire out = a & b; is equivalent to wire out; assign out = a & b;
  • Propagation delay: assign #N out = expr; delays LHS update by N time units. Inertial model cancels previous pending update if RHS changes before delay expires.
  • Rise and fall delays: assign #(rise, fall) out = expr; models asymmetric gate delays.
  • Synthesis mapping: conditional operator ? : infers MUX; & infers AND; | infers OR; arithmetic operators infer adder/subtractor.
  • Exam trap: propagation delay in assign is ignored during synthesis. It only affects simulation waveforms.

Continuous Assignment Modeling

Test your knowledge on this topic.

Question 1 of 3

Q1.Which data type must be the target of a continuous assign statement?