4.2 Verilog Procedural Assignment
Category Verilog Tutorial
Keywords: Blocking Assignment, Non-blocking Assignment, Parallel
Procedural assignment occurs within the initial or always statement blocks, and the objects of assignment are registers, integers, real numbers, etc.
Once these variables are assigned a value, they will retain that value until they are reassigned a new value.
Continuous assignment is always active, and any change in the operands will affect the result of the expression; procedural assignment only takes effect when the statement is executed. This is the difference between continuous and procedural assignment.
Verilog procedural assignments include two types of statements: blocking assignments and non-blocking assignments.
Blocking Assignment
Blocking assignments are executed sequentially, meaning that the current statement will definitely be completed before the next statement is executed.
The blocking assignment statement uses the equal sign =
as the assignment operator.
In previous simulations, the assignment statements inside the initial block were all blocking assignments.
Non-blocking Assignment
Non-blocking assignments are parallel execution statements, meaning that the execution of the next statement and the current statement are carried out simultaneously, and it will not block the execution of statements later in the same block.
The non-blocking assignment statement uses the less than or equal sign <=
as the assignment operator.
The following code is used to simulate blocking and non-blocking assignments to illustrate the differences between the two types of procedural assignments.
Example
`timescale 1ns/1ns
module test;
reg [3:0] ai, bi;
reg [3:0] ai2, bi2;
reg [3:0] value_blk;
reg [3:0] value_non;
reg [3:0] value_non2;
initial begin
ai = 4'd1; //(1)
bi = 4'd2; //(2)
ai2 = 4'd7; //(3)
bi2 = 4'd8; //(4)
#20; //(5)
//non-blocking assignment with blocking assignment
ai = 4'd3; //(6)
bi = 4'd4; //(7)
value_blk = ai + bi; //(8)
value_non <= ai + bi; //(9)
//non-blocking assignment itself
ai2 <= 4'd5; //(10)
bi2 <= 4'd6; //(11)
value_non2 <= ai2 + bi2; //(12)
end
//stop the simulation
always begin
#10;
if ($time >= 1000) $finish;
end
endmodule
Simulation results are as follows:
Statements (1) - (8) are all blocking assignments and are executed in sequence.
Before 20ns, the values of signals ai and bi change. Due to the characteristics of procedural assignment, value_blk = ai + bi has not been executed, so the value of value_blk before 20ns is X (undetermined state).
After 20ns, the values of signals ai and bi change again. When it is executed to value_blk = ai + bi, the signal value_blk is calculated using the new values of signals ai and bi, resulting in 7.
Statements (9) - (12) are all non-blocking assignments and are executed in parallel.
Firstly, although (9) - (12) are all executed concurrently, the execution order is also after (8), so the calculation of signal value_non = ai + bi will also use the new values of signals ai and bi, resulting in 7.
Secondly, (10) - (12) are executed concurrently, so when calculating value_non2 = ai2 + bi2, it does not care about the latest non-blocking assignment results of signals ai2 and bi2. That is, when calculating value_non2, the old values of signals ai2 and bi2 are used, resulting in 4'hF.
Use Non-blocking Assignment to Avoid Race Hazards
The above simulation code is only to help readers better understand the difference between blocking assignments and non-blocking assignments. In actual Verilog code design, remember not to mix blocking assignments and non-blocking assignments in a procedural structure. Mixing the two assignment methods makes it difficult to control timing and can easily lead to unexpected results.
More often, in circuit design, non-blocking assignments are used more in always sequential logic blocks, and blocking assignments are used more in always combination logic blocks; in simulating circuits, blocking assignments are generally used more in initial blocks.
As shown below, to achieve the function of exchanging the values of two registers on the rising edge of the clock, blocking assignments are used in two always blocks.
Because the statements