Why we need non-blocking assignments in Verilog?
Lets simplify things by assuming a and b have initial values 1'b1 and 1'b0 respectively. 


One always block with blocking assignment:

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

a and b will be 1'b0 after any clock event
Two always blocks with blocking assignment:

always @(posedge clk)
  a = b;
always @(posedge clk)
  b = a;

The simulator can choose which always block to evaluate first per the non-determinism specifically allowed by the IEEE1364 (Verilog) and IEEE1800 (SystemVerilog). a and b will both be 1'b0 or both be 1'b1 and will stay that value for any future clock event.
One always block with non-blocking assignment:

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

After the first clock, a will be 1'b0 and b will be 1'b1. After the second clock, a and b will be assign back to their initial values; 1'b1 and 1'b0 respectively. They will continue to flop every clock. This is the desired behavior and will match hardware.
Two always blocks with non-blocking assignment:

always @(posedge clk)
  a &lt;= b;
always @(posedge clk)
  b &lt;= a;

The simulator can choose which always block to evaluate first per the non-determinism specifically allowed by the IEEE1364 (Verilog) and IEEE1800 (SystemVerilog). Regardless, after the first clock, a will be 1'b0 and b will be 1'b1. After the second clock, a and b will be assign back to their initial values; 1'b1 and 1'b0 respectively. They will continue to flop every clock. This is the desired behavior and will match hardware.




Blocking assignments (=) means evaluate and update immediately. This is ideal for combinational logic (assigned in always @*).
Non-blocking assignments (&lt;=) means evaluate immediately and postpone the updates until all other planed evaluations in the same time step has been completed. Sequential logic (assigned in always @(posedge clk)) should use non-blocking assignments.