the issue is with:
always @ (posedge clk) x = y;
always @ (posedge clk) y = z;
always @ (posedge clk) z = x ^ (~y);
this is a simple example. but what if these statements were in different modules at different levels of hierchy? For synthesis, it probably won't matter, but for sim it can become an issue. (and even if they are in the same module)
If "posedge clk" is encountered, then the sim will do one of 6 different orderings of these statements. each ordering will result in different values for x,y,z. I'm not sure if synthesis allows this case, as its not clear what the user actually wants.
The ordering may not be bottom to top, or top to bottom, or even be consistant. Even if there were some rules, the fact that they could be in seperate levels of hierchy would make the rules very hard to use.
now if non-blocking statements are used, none of these values changes until after all of the always blocks are evaluated. This makes the order of evaluation unimportant.
Thus, the output of a clocked process should use the non-blocking assignment.
For combinatorial processes, it can be beneficial to use blocking assigns. eg:
always @ (a, b, c) begin a <= b; d <=c | a; end
in this case, if b changes, then:
evaluate, find a = b. d is unchanged
notice "a" has changed.
evaluate, find a unchanged, d is updated.
For combinatorial logic, the evaluation/re-evaluation process can continue, but will eventually finish -- unless there are combinatorial loops.
with blocking assigns, the "a" input is no longer needed, and a change to b will result in a change to d within the first evaluation of the block.
Now, for clocked processes, "=" has another downside. if x = y is inside a clocked process, then x cannot be used blindly in any other clocked process -- as before, the simulator can evaluate the assigning "always" either before or after x is used.
For the case where you ONLY use the intermediate results within the clocked process AND you correctly use the blocking assigns, it will work and sim correctly. This is the same as the use of "variables" in VHDL -- where "variables" can only use blocking assigns and can only be used in a single process.