Verilog Blocking and Non-blocking
Verilog supports blocking and non-blocking assignments statements within the always block with their different behaviors.
The blocking assignment is similar to software assignment statements found in most popular programming languages. The non-blocking assignment is the more natural assignment statement to describe many hardware systems, especially for synthesis.
The blocking assignments can only be used in a few situations, such as modeling combinational logic, defining functions, or implementing testbench algorithms. All IEEE P1364.1 compliant synthesis tools are required to support both blocking and non-blocking assignments in explicit-style code, with the restriction that each variable and each block may use only one or the other kind of assignment.
Blocking assignment statements are assigned using (=) operator and are executed one after the other in a procedural block. But, it will not prevent the execution of statements that run in a parallel block.
There are two initial blocks which are executed in parallel. Statements are executed sequentially in each block and both blocks finish at time 0ns.
To be more specific, variable is assigned first, that followed by the display statement which is then followed by all other statements.
This is visible in the output where variable b and c are 8'hxx in the first display statement. This is because variable b and c assignments have not been executed yet when the first $display is called.
In the below example, we'll add a few delays into the same set of statements to see how it reacts and behaves.
After execution, it gives the following data.
Non-blocking assignment statements are allowed to be scheduled without blocking the execution of the following statements and is specified by a (<=) symbol.
The same symbol is used as a relational operator in expressions, and as an assignment operator in the context of a non-blocking assignment.
Take the same example as above, replace all (=) symbols with a non-blocking assignment operator (<=), we'll get the difference in the output.
Now, all the $display statements printed 'h'x. The reason for this behavior is the execution of the non-blocking assignment statements.
The RHS of every non-blocking statement of a particular time-step is captured and moves onto the next statement.
The captured RHS value is assigned to the LHS variable only at the end of the time-step.