We know that the difference between blocking statements and non-blocking statements is: blocking statements executes sequentially (execution of next statement is blocked until present one completes) and are used to perform in combinational circuits.
Example:
always@(*) begin
c = A & B;
D = C/A;
end
Here all the statements executes sequentially (blocking statement)
Whereas non-blocking statements execute parallelly (execution of next statement is not blocked) and are used to perform in sequential circuits.
Example: Take an example of shift register
always@posedge(clk) begin
A<=B;
B<=C;
C<=D;
end
Here all the statements executes parallely because it is non-blocking and we have used posedge clk
Now if you see the difference between begin end and fork join, the difference is: in begin end, statements are executed in the order they are listed (i.e. sequentially), whereas in fork join, statements are executed parallelly.
My question here is, in the above example of non-blocking statement, we have used begin end but the statements are been executed parallelly not sequentially, but if you see in the difference between begin end and fork join it says begin end executes the statements one after another.
Could someone explain with a clear answer to this?
That is not true. In the above example of non-blocking statement, we have used
begin-endand the statements are executed sequentially. However, in spite of that, the order of execution doesn't matter. A subtle but important distinction.When a line of code containing a non-blocking assignment is executed, it is executed immediately, but the left-hand-side of the assignment (the target) does not get its new value immediately. So, any other statements in the same
begin-endblock that read a variable assigned to using a non-blocking assignment will use the old value of that variable. As a consequence, the order of statements using non-blocking assignments insidebegin-endblocks often does not matter. That is the case with your example.So, when does the left-hand-side of a non-blocking assignment get updated?
System-Verilog has 9 so-called scheduler regions:
and Verilog has 4:
Think of this like a flow chart that gets executed at every timestep. (A timestep is a particular simulation time - 12345ns or whatever.) The lines of code in your
begin-endblock get executed in the ACTIVE region (ie early), however, the left-hand-side of your non-blocking assignments doen't get updated until the NBA region, ie later.