Statements inside a process are sequential?! (Or am I wrong?)
Not really. At compile time, the synthesis tool parses each line in sequence, and it's certainly true that the order of the sequence can affect the meaning of your code. But when it comes to actually "executing" your code on the target device, for want of a better expression, there is no sequence unless you explicitly code for it.
It's very counter-intuitive if you're used to writing code for a microprocessor. For example:
a = b;
b = a;
... is a classic example of how not to swap the contents of two variables. But in VHDL:
IF clk'event AND clk = '1' THEN
a <= b;
b <= a;
END IF;
... actually does swap the contents of registers a and b on each rising edge of the clock. It doesn't matter which way round the two assignment statements are written, because they both happen simultaneously on each clock edge.
Think of "a <= b" as meaning "a takes the value that b had
immediately prior to the clock edge".
The sequence is sometimes important, though. For example:
IF clk'event AND clk = '1' THEN
a <= '0';
IF b = c THEN
a <= '1';
END IF;
END IF;
... will set the value of a to 0 on each rising clock edge, unless b and c are equal, in which case a is set to 1. But:
IF clk'event AND clk = '1' THEN
IF b = c THEN
a <= '1';
END IF;
a <= '0';
END IF;
... will always set a to 0. Moreover, the synthesis tool will spot that it doesn't require b or c, so if is this the only place in the code they're used, then they (and all the logic that might be required to generate them) will be optimised away. Also, since a is never assigned anything other than zero, any code which depends on the value of a will also be simplified.
Be aware of this if you're ever fixing bugs in a device which is running low on spare capacity. It's quite possible to fix a bug, and find the code suddenly gets a lot bigger because half of it can no longer be thrown away!