The concept of Blocking vs. Nonblocking signal assignments is a unique one to hardware description languages. The main reason to use either Blocking or Nonblocking assignments is to generate either combinational or sequential logic.
In programming language like c, one assignment blocks the next from executing until it is done. In Verilog there is logic that can execute concurrently or at the same time as opposed to one-line-at-a-time and there needs to be a way to tell which logic is which.
Generally, we use blocking assignment to describe combinational logic and nonblocking assignment to describe sequential logic in order to get the same result before and after simulation.
<= // nonblocking assignment
= // blocking assignment