In Verilog, assigning values to variables and nets is a fundamental concept that helps define the behavior of circuits. Assignments in Verilog can be broken down into three main categories:

  1. Procedural Assignment
  2. Continuous Assignment
  3. Procedural Continuous Assignment

Each type of assignment plays a unique role in how signals and variables are handled in Verilog, allowing you to design more efficient digital systems. Let’s dive deeper into each type and their usage.


Legal LHS (Left-Hand Side) Values for Verilog Assignments

An assignment in Verilog consists of two parts: the Right-Hand Side (RHS) and the Left-Hand Side (LHS). The RHS is the expression that evaluates to a value, while the LHS is the variable or net that will receive the value from the RHS.

Here is a table summarizing valid LHS values for each assignment type:

Assignment TypeLegal LHS Values
Procedural– Variables (scalar or vector)
– Bit-select or part-select of a vector
– Memory word
– Concatenation of variables
Continuous– Net (scalar or vector)
– Bit-select or part-select of a vector net
– Concatenation of bit-selects and part-selects
Procedural Continuous– Net or variable (scalar or vector)
– Bit-select or part-select of a vector net

Verilog Assignment Examples

Let’s look at some practical Verilog examples to understand how assignments work.

module tb;
    reg clk;
    wire a, b, c, d, e, f;
    reg z, y;

    // Procedural Assignment: Toggling the clock signal
    always #10 clk = ~clk;

    // Continuous Assignment: Assign constant value to y
    assign y = 1;

    // Continuous Assignment: Logic expression for f
    assign f = (a | b) ^ (d & e);

    // Procedural Assignment: Adding values during positive clock edge
    always @ (posedge clk) begin
        z <= a + b + c + d;
    end

    // Initializing variables at the start of the simulation
    initial begin
        a <= 0; b <= 0; c <= 0; d <= 0; e <= 0;
        clk <= 0;
    end
endmodule

Procedural Assignment

Procedural assignments occur within procedural blocks such as always, initial, tasks, and functions. These assignments place values onto variables and maintain those values until a new assignment occurs.

Key Points:

  • The variable holds the assigned value until another assignment happens.
  • Procedural assignments are triggered during simulation, and you can control the flow using control statements like if-else, case, and loops.

Example:

reg [7:0] data;
integer count;
real period;

initial begin
    data = 8'h3e;  // Initial assignment
    period = 4.23;
    count = 0;
end

always @ (posedge clk) begin
    count++;  // Increment count on every positive clock edge
end

Variable Declaration Assignment

You can assign a value to a variable at the time of declaration. This assignment works similarly to procedural assignments but has no duration — the value holds until the next assignment.

Note: Arrays cannot be initialized directly during declaration.

Example:

module my_block;
    reg [31:0] data = 32'hdead_cafe;  // Initial assignment at declaration

    initial begin
        #20 data = 32'h1234_5678;  // At time 20, 'data' changes to 1234_5678
    end
endmodule

If the variable is initialized during the declaration, the order of evaluation may not be predictable. It can have either of the two initial values.

module my_block;
    reg [7:0] addr = 8'h05;

    initial begin
        addr = 8'hee;  // This will update addr to 8'hee
    end
endmodule

Continuous Assignment

Continuous assignments assign values to nets and occur whenever there is a change in the RHS expression. This is often used to model combinational logic without specifying the underlying gates. The value on the LHS will continuously update based on the evaluation of the RHS.

Example:

// Example of an AND gate using continuous assignment
wire a, b, c;

assign a = b & c;  // 'a' will always be the result of b AND c

Whenever the values of b or c change, the expression on the RHS is re-evaluated, and a gets updated.

Net Declaration Assignment

In Verilog, nets (e.g., wire) can also be initialized at the time of declaration. However, nets can only have one continuous assignment.

Example:

wire penable = 1;  // Assigning value 1 to the 'penable' wire during declaration

Procedural Continuous Assignment

These assignments are used within procedural blocks but allow continuous updates to nets or variables. There are two types of procedural continuous assignments:

  1. assign … deassign
  2. force … release

1. assign ... deassign

The assign statement assigns a value to a variable, and deassign removes this value, leaving the variable unchanged until a new value is assigned procedurally.

Example:

reg q;

initial begin
    assign q = 0;  // Assign 0 to q
    #10 deassign q;  // Remove the assignment after 10 time units
end

2. force ... release

The force statement allows you to override all other assignments to a variable or net, and release removes the force.

Example:

reg o, a, b;

initial begin
    force o = a & b;  // Force o to be the result of a AND b
    // Other code
    release o;  // Release the force on o
end

This can be applied to both nets and variables. However, the LHS cannot be a bit-select, part-select of an array, or a variable array reference.


Conclusion

Verilog assignments are crucial for defining the behavior of digital circuits. Understanding the different types of assignments—procedural, continuous, and procedural continuous—helps you build efficient and reliable designs. By carefully choosing the correct assignment type, you can ensure that your circuits behave as expected, whether you are working with variables or nets.

Always keep in mind that the LHS of an assignment must be appropriate for the assignment type, and procedural assignments will hold their values until a new assignment occurs. Continuous assignments are ideal for combinational logic, while procedural continuous assignments allow you to override or release values as needed.

Scroll to Top