Verilog assign Statement Explained: Syntax, Examples, and Beginner’s Guide to Continuous Assignment

目次

1. What is the assign statement in Verilog? [Beginner’s Guide]

What is Verilog HDL?

Verilog HDL (Hardware Description Language) is a hardware description language used to model digital circuits. Unlike software programming languages, Verilog describes the structure and behavior of hardware (logic circuits), which can then be simulated or synthesized into real hardware such as FPGAs and ASICs.

Among the most frequently used constructs in Verilog is the assign statement. It is especially essential when describing combinational circuits.

What does the assign statement do?

The assign statement is used to perform a continuous assignment to a wire-type signal. “Continuous” means that whenever the input signal changes, the output is updated immediately to reflect that change.

For example, to perform a logical AND of two signals and send the result to an output, you can write:

assign out = in1 & in2;

This single line implements the functionality “always drive out with the AND of in1 and in2.” In this way, assign plays the role of explicitly defining hardware connections (wiring).

Using assign in combinational circuits

Digital circuits are broadly categorized into combinational circuits and sequential circuits:

  • Combinational circuits: outputs change immediately in response to inputs (e.g., adders, logic gates)
  • Sequential circuits: use clocks or storage elements to maintain states over time (e.g., flip-flops, counters)

The assign statement is used in the former, combinational circuits. Since outputs must always reflect the current input state, continuous assignment is the most appropriate approach.

Why is the assign statement important for beginners?

At the early stage of learning Verilog, understanding combinational circuits is crucial. The assign statement is the primary way to describe them. From simple logic gates to adders, comparators, and conditional expressions, many essential components can be expressed concisely with assign.

Additionally, using assign helps beginners clearly grasp the flow of signals as actual hardware. This intuition is critical later when working with more complex sequential circuits or testbenches.

Summary: Master the basics of the assign statement

The Verilog assign statement is the foundation for describing combinational circuits. Since it allows you to express wiring and logical operations concisely, it is one of the first constructs beginners should master when learning Verilog.

2. Basic Syntax and Usage of the assign Statement in Verilog

Basic Syntax of assign

The assign statement in Verilog has a very simple syntax. It is mainly used to assign logical or arithmetic expressions to wire-type signals. The basic form looks like this:

assign output_signal = expression;

The “expression” can include other signals, logical operators, or bitwise operations. Note that assign can only be used with wire-type signals and not with reg types.

Example 1: Simple Logic Operations

One of the most common uses of assign is to describe logic gates. Below is an example of AND, OR, and XOR gates written with assign:

assign and_out = a & b;   // AND gate
assign or_out  = a | b;   // OR gate
assign xor_out = a ^ b;   // XOR gate

Using operators, you can combine multiple signals and continuously assign the result to an output.

Example 2: Bit-Level Operations

The assign statement also supports bit-level operations, such as extracting or combining specific bits:

assign upper_4bits = data[7:4];              // Extract the upper 4 bits of an 8-bit signal
assign lower_4bits = data[3:0];              // Extract the lower 4 bits
assign combined = {data1[3:0], data2[3:0]};  // Concatenate two 4-bit signals into 8 bits

This makes assign very useful for restructuring or slicing data.

What Does “Continuous Assignment” Mean?

In Verilog, assignments made with assign are called continuous assignments. This means that the output updates immediately whenever the input changes.

Unlike software assignment statements, hardware assignments behave as if the signals are physically wired together. In other words, assign allows you to describe signal propagation that mimics real hardware.

Specifying Delays in assign

Verilog also allows you to specify a delay in an assign statement. While this is primarily for simulation (and often ignored during synthesis), it can be useful for verifying behavior:

assign #5 out = a & b;  // Delay the AND result by 5 time units before assigning to out

The “#5” represents a delay based on the defined time unit. It is helpful for complex simulations but should not be relied on for hardware synthesis.

Example: Using Conditional Expressions in assign

The assign statement can also use the conditional (ternary) operator to implement simple if-else style behavior:

assign out = sel ? data1 : data2;

This means: “if sel is 1, output data1; otherwise, output data2.” This is commonly used for multiplexers or conditional assignments.

Summary: Mastering the Syntax of assign

The Verilog assign statement is a simple yet powerful construct. It supports logical operations, bit manipulation, conditional branching, and even delayed assignments for simulation.

For beginners, mastering the basic usage of assign is the first step toward confidently designing combinational circuits in Verilog.

3. The Relationship Between assign and wire: From Declaration to Usage

Basic Relationship Between assign and wire

One of the most important rules when using the assign statement in Verilog is that assign can only be used with signals declared as wire. If you ignore this rule, you will quickly run into syntax errors.

Assignments made with assign are known as continuous assignments, and continuous assignments are only allowed on signals of type wire.

What is wire? — Think of It as a Physical Connection

As the name suggests, the wire type in Verilog models a physical wire connection in a circuit. It represents a signal line that always carries values driven by other outputs.

In other words, a wire does not store values by itself. Instead, it receives values from other drivers (such as assign statements or module outputs) and propagates them.

For example:

wire a, b, out;

assign out = a & b;  // out is always driven by the AND of a and b

Here, out must be declared as a wire. If it were declared as reg, the compiler would throw an error.

Why assign Cannot Be Used with reg

The reg type is used to store values in sequential logic. A reg variable is typically updated inside an always block, depending on conditions or clock events. It is not meant to be continuously driven by an assign.

For example, this code is invalid:

reg out;
assign out = a & b;  // ERROR! assign cannot drive a reg

Thus, the general rule is: use assign with wire, and use always with reg.

Declaring wire Types and Using Buses

wire types can represent not only single-bit signals but also multi-bit buses:

wire [3:0] a, b;
wire [3:0] out;

assign out = a & b;  // Bitwise AND for each bit

When handling multi-bit signals, you must explicitly declare the width of the wire. Other than that, the syntax is the same as for single-bit signals.

wire in Module Connections

In Verilog, wire is also commonly used to connect signals between modules. For example:

wire result;

module1 u1 (.a(a), .b(b), .out(result));
module2 u2 (.in(result), .y(y));

This shows that wire is not only necessary for assign, but also serves as a fundamental connection element across the entire Verilog design.

Summary: Understanding wire Is Key to Using assign Correctly

To use the assign statement correctly in Verilog, you must understand the wire type. A wire is a “connection” that continuously receives values from other signals, and assign defines that connection.

On the other hand, assign cannot be used with reg; reg must be driven inside always blocks instead. Understanding this distinction ensures accurate and efficient hardware descriptions.

4. What’s the Difference Between assign and always? [Beginner’s Common Confusion]

Why Do Beginners Get Confused Between “assign” and “always”?

One of the biggest sources of confusion for beginners learning Verilog is the difference between the assign statement and the always block. Both are ways to assign values to signals, but they are used in different contexts and with different data types.

In this section, we’ll carefully explain their fundamental differences and how to use each properly.

Characteristics and Use Cases of assign

First, let’s review the main features of the assign statement:

  • Purpose: Describing combinational logic
  • Data type: Can only be used with wire
  • Assignment timing: Continuous assignment (signal is always driven)
  • Keyword: assign

Example: 2-input AND Gate (assign)

wire a, b;
wire out;

assign out = a & b;

Here, when the inputs change, the output immediately updates. This is the typical behavior of combinational circuits.

Characteristics and Use Cases of always

The always block, on the other hand, provides more flexibility. It is commonly used for sequential circuits, conditional branching, or clock-synchronized logic.

  • Purpose: Describing sequential logic or more complex behavior
  • Data type: Used to assign values to reg
  • Assignment timing: Conditional assignment (executed when a trigger condition is met)
  • Keyword: always

Example: Clock-Synchronized Register (always)

reg out;

always @(posedge clk) begin
  out <= a & b;
end

Here, the result of a & b is stored in out at the rising edge of the clock. For logic involving time or state, the always block is required.

Comparing wire and reg

Featurewirereg
Where usedassign statementsinside always blocks
Stores data?No (just propagates values)Yes (holds values)
Initial value settingNot allowedAllowed (in simulation)
Assignment styleContinuous assignmentBlocking / Non-blocking assignment

Because assign and always are so closely tied to data types, it’s effective to learn them as a paired concept.

Which Should You Use?

Here’s a basic guideline for choosing between assign and always:

GoalUseData type
Logical operations (combinational)assignwire
Clock-synchronized storage (sequential)alwaysreg
Conditional branchingalwaysreg
Simple wiring / logic outputassignwire

Example: Use always for if-statements

reg y;
always @(a or b) begin
  if (a == 1) y = b;
  else        y = 0;
end

This kind of conditional branching cannot be expressed with assign. A good rule of thumb is: if you need conditions, flow control, or storage, use always.

Can You Use assign and always Together?

You cannot drive the same signal from both assign and always. Doing so causes conflicts and synthesis errors because the signal has multiple drivers.

Invalid example:

assign y = a & b;

always @(posedge clk)
  y <= a | b;  // ERROR: y is driven by both assign and always

Each signal must have a single, clear driver.

Summary: Distinguishing Between assign and always

When designing in Verilog, your choice of assign or always depends on when and how you want the signal updated:

  • Direct, always-updated logic → assign with wire
  • Logic involving time, conditions, or storage → always with reg

By following this rule, beginners can avoid one of the most common stumbling blocks in Verilog: confusion between assign and always.

5. Practical Examples of Combinational Circuits Using assign [With Diagrams]

What Are Combinational Circuits?

Let’s start with the basics. A combinational circuit is a circuit where the output depends only on the current input values. Since it does not have memory elements, the output is determined immediately without depending on past states.

In Verilog, the assign statement is the most suitable way to describe this kind of circuit.

Basic Logic Gates (AND, OR, XOR)

Here’s an example of how to implement multiple basic logic gates using assign:

module logic_gates(
  input  wire a,
  input  wire b,
  output wire and_out,
  output wire or_out,
  output wire xor_out
);

  assign and_out = a & b;
  assign or_out  = a | b;
  assign xor_out = a ^ b;

endmodule

This module takes a and b as inputs and produces the outputs of AND, OR, and XOR operations. Since no conditions or clocks are needed, everything is handled with assign.

Half Adder Implementation

A classic example of a combinational circuit is the Half Adder. It adds two single-bit binary inputs and produces a sum bit and a carry bit as outputs.

Logic Equations

  • Sum = A ⊕ B (XOR)
  • Carry = A · B (AND)

Verilog Implementation

module half_adder(
  input  wire a,
  input  wire b,
  output wire sum,
  output wire carry
);

  assign sum   = a ^ b;
  assign carry = a & b;

endmodule

This Half Adder can be described with just two assign statements. It’s a perfect beginner-level example for practicing assign.

Full Adder Implementation

Next, let’s look at the Full Adder. This circuit adds three one-bit inputs (A, B, and Cin) and produces a Sum and a Carry output.

Logic Equations

  • Sum = A ⊕ B ⊕ Cin
  • Carry = (A · B) + (Cin · (A ⊕ B))

Verilog Implementation

module full_adder(
  input  wire a,
  input  wire b,
  input  wire cin,
  output wire sum,
  output wire cout
);

  wire ab_xor;

  assign ab_xor = a ^ b;
  assign sum    = ab_xor ^ cin;
  assign cout   = (a & b) | (cin & ab_xor);

endmodule

Here, we introduced an intermediate signal ab_xor using assign. This demonstrates how even multi-step logic can be expressed cleanly with wire + assign.

Multiplexer (MUX) Implementation

Another common example is the 2-to-1 Multiplexer (MUX), which selects between two inputs based on a control signal:

module mux2to1(
  input  wire a,
  input  wire b,
  input  wire sel,
  output wire y
);

  assign y = sel ? b : a;

endmodule

If sel is 1, the output is b; if sel is 0, the output is a. The ternary (conditional) operator with assign makes this very concise.

Best Practices When Using assign

  • Declare signals as wire: assign cannot drive reg.
  • Write one assign per output: avoid overly complex one-liners; keep it readable.
  • Use intermediate wires: break down complex logic into steps for clarity.

Summary: Combinational Circuits Can Be Implemented Entirely with assign

As shown in this section, basic combinational circuits can all be written using assign statements. Logic gates, adders, and multiplexers can be expressed smoothly and clearly.

For beginners, practicing with these simple circuits is the best way to get comfortable with assign and naturally develop an understanding of signal flow and circuit structure.

6. Common Pitfalls and Mistakes When Using assign

Typical Traps for Beginners

The assign statement is one of the simplest constructs in Verilog, but that simplicity can lead to misuse. If not fully understood, it may cause errors or unexpected behavior. Here are the most common mistakes beginners (and even intermediate users) make with assign, along with solutions.

1. Trying to Use assign with reg

❌ Common Mistake:

reg out;
assign out = a & b;  // ERROR! Cannot assign to a reg

💡 Cause and Fix:

The assign statement is for wire only. A reg must be updated inside an always block.

Fix: Change out to a wire, or use an always block instead.

2. Driving the Same Signal with Multiple assign Statements

❌ Invalid Example:

assign y = a & b;
assign y = a | b;  // ERROR: Multiple drivers for y

💡 Cause and Fix:

In Verilog, a signal must have only one driver. Multiple assign statements for the same signal cause conflicts.

Fix: Use an always block with conditional logic, or introduce intermediate wires.

3. Misunderstanding assign as an “Initializer”

❌ Misleading Example:

assign a = 1'b0;  // Not an initializer — this means a is always 0

💡 Cause and Fix:

assign is continuous — it always drives the value, not just at initialization. For simulation initialization, use initial, and for synthesis, use reset logic.

4. Forgetting to Declare the Signal

❌ Example:

assign result = a & b;  // ERROR if result is undeclared

💡 Cause and Fix:

All signals must be explicitly declared in Verilog. Forgetting to declare can cause compile errors or hidden bugs.

Fix: Always declare signals as wire or reg.

5. Using Operations Not Suitable for Synthesis

Some operations (like division or modulo) may work in simulation but fail during synthesis:

assign out = a / 3;  // ⚠️ May fail in FPGA synthesis

Fix: Check synthesis compatibility. Rewrite with logic or use always for complex operations.

6. Overusing Nested Ternary Operators

assign out = sel1 ? a : (sel2 ? b : (sel3 ? c : d));  // Hard to read!

Fix: Use intermediate wire signals to simplify, or rewrite with always for readability.

Tips for Debugging assign Issues

  • Be explicit about signal types (wire vs reg)
  • Pay attention to warnings (simulators often flag potential issues)
  • Know tool limitations (check if operations are synthesis-friendly)

Summary: assign Is Simple but Requires Care

While assign is a convenient and straightforward construct in Verilog, its restrictions must be respected: only for wire, no multiple drivers, and no initialization. Following these rules prevents future bugs and makes your code more maintainable.

7. Frequently Asked Questions (FAQ)

Beginners and intermediate learners often have similar questions about the Verilog assign statement. This section covers the most commonly searched and asked questions in a clear Q&A format.

Q1: Which is easier for beginners, assign or always?

A: Start with the assign statement.

The assign statement is ideal for beginners because it concisely expresses combinational circuits. The always block is more complex, as it involves sequential logic and conditional branching.

  • Simple logic → assign
  • Time or state-dependent logic → always

Q2: Can I use assign with reg?

A: No. If you want to drive a reg, you must use an always block.

The assign statement works only with wire. reg variables must be updated in always.

// ✅ Correct (using always with reg)
reg out;
always @(a or b)
  out = a & b;

// ❌ Incorrect (assign cannot drive reg)
reg out;
assign out = a & b;

Q3: Can I assign the same signal in multiple assign statements?

A: No. This will cause conflicts or synthesis errors.

In Verilog, a signal must have exactly one driver. If multiple assign statements drive the same signal, it results in conflicts and undefined behavior.

For multiple conditions, use an always block or restructure with intermediate wires.

Q4: Does the delay (#) in assign have any real hardware effect?

A: Delays apply only in simulation, not in synthesis.

Example:

assign #5 out = a & b;

Here, #5 introduces a delay in simulation, but it is ignored in FPGA or ASIC synthesis.

  • Simulation → Valid
  • Synthesis → Ignored

Q5: How do I write conditional logic with assign?

A: Use the ternary (conditional) operator.

assign out = sel ? a : b;

This means “if sel is 1, output a; otherwise, output b.” For complex branching, use an always block.

Q6: Why isn’t the output changing in my assign test?

A: Check if the inputs are actually changing.

The output of assign depends entirely on its input signals. If the inputs do not change, the output will stay constant.

  • Are the inputs properly toggled in the testbench?
  • Are initial values assigned correctly?
  • Do the simulation waveforms show expected changes?

Q7: Can assign-based circuits be synthesized?

A: Yes, but it depends on the operations used.

Most logic described with assign (AND, OR, XOR, etc.) can be synthesized. However, certain operations (like division or floating-point arithmetic) may not be synthesizable on all FPGA/ASIC tools.

  • ✅ AND / OR / XOR → Synthesizable
  • ⚠️ Division / Real numbers / Floating-point → May not be synthesizable

8. Glossary: Essential Verilog Terms for Beginners

Here is a concise glossary of key Verilog terms that beginners should understand first. We focus on terms closely related to the assign statement and combinational logic.

wire

Meaning:
A signal type that models a physical “wire.” It receives values from other signals or module outputs rather than storing its own value.

Key Points:

  • Values can be assigned with assign
  • Cannot store data by itself
  • Mainly used for combinational circuits

Example:

wire a, b, out;
assign out = a & b;

reg

Meaning:
A signal type that can store values temporarily. Typically used in always blocks.

Key Points:

  • Cannot be assigned with assign
  • Used for sequential circuits with memory
  • Often updated on clock edges

Example:

reg out;
always @(posedge clk) out <= a;

assign

Meaning:
A construct for continuous assignment to wire-type signals.

Key Points:

  • Used in combinational logic
  • Output changes immediately when input changes
  • Right-hand side can include expressions, operators, constants

Example:

assign y = a & b;

always

Meaning:
A block that executes when specific events occur (e.g., clock edges or signal changes).

Key Points:

  • Works with reg variables
  • Used for sequential circuits or conditional logic
  • Supports if-statements and case-statements

Example:

always @(posedge clk) begin
  out <= a + b;
end

Combinational Circuit

Meaning:
A circuit where the output is determined only by the current inputs.

Key Points:

  • No memory elements
  • Examples: logic gates, adders, multiplexers
  • Described using assign or always @(*)

Sequential Circuit

Meaning:
A circuit where the output depends on both current inputs and past states.

Key Points:

  • Contains memory elements (registers, flip-flops)
  • Clock-driven operation
  • Described using always @(posedge clk)

Ternary Operator (Conditional Operator)

Meaning:
A compact conditional expression in the form condition ? true_value : false_value.

Key Points:

  • Commonly used with assign
  • More concise than if-statements

Example:

assign y = sel ? a : b;

module

Meaning:
The basic building block of a Verilog design.

Key Points:

  • Contains input and output ports
  • Can be instantiated hierarchically

Example:

module adder(input a, input b, output sum);
  assign sum = a + b;
endmodule

initial

Meaning:
A block executed only once at the beginning of a simulation.

Key Points:

  • Not synthesizable in hardware
  • Used in testbenches

Example:

initial begin
  a = 0;
  b = 1;
end

Non-blocking Assignment (<=)

Meaning:
An assignment operator used inside always blocks to update registers without blocking other assignments.

Key Points:

  • Common in clock-synchronized sequential circuits
  • Allows multiple assignments to execute in parallel

Example:

always @(posedge clk) begin
  out1 <= in1;
  out2 <= in2;
end

Summary: Understanding Terms Is the First Step to Mastering Verilog

These terms form the foundation of Verilog. By not just memorizing syntax but also understanding what each keyword means, beginners can debug errors faster and design circuits more effectively.

9. Conclusion: Mastering the assign Statement in Verilog

In this article, we covered the assign statement in Verilog HDL from the basics to advanced usage. As one of the first constructs beginners should learn, assign is simple but powerful, and it is essential for designing combinational circuits.

Key Takeaways About assign

✅ Role of assign

  • A construct for continuous assignment to wire-type signals
  • Output updates immediately in response to input changes
  • Best suited for combinational circuits

✅ Usage Rules

  • assign cannot be used with reg
  • One signal must not have multiple assign drivers
  • Not suitable for initialization — only for continuous driving

✅ Tips for Effective Use

  • Clearly distinguish between assign (for wire) and always (for reg)
  • Use the ternary operator for simple conditional logic
  • For complex logic, break it down into intermediate wire signals to improve readability

Next Steps to Level Up

Once you are comfortable with assign, try learning the following next:

  • always blocks for sequential circuits
  • Conditional logic with if and case
  • Writing testbenches and running simulations
  • Hierarchical design using multiple modules

Verilog design skills grow through hands-on practice. Start with small circuits, get used to describing them with assign, and gradually tackle more complex designs.

Final Words

By fully understanding and mastering the assign statement, you will have already overcome one of the biggest hurdles in Verilog design. From simple gates to larger combinational circuits, assign provides the foundation for everything.

We hope this guide serves as your go-to “assign cheat sheet” that you can revisit anytime as you progress in your Verilog learning journey.