a = 1'b0;
b = 1'b1;
The initial block is a mechanism for describing how you want your signals to behave initially. When synthesised, the tools use these values as the initial vales for each register. The registers are not assigned these values sequentially, they have these values from the start.
In the case of simulation, the CPU processes the instructions given, one after the other
assign a = b;
As I mentioned in my comment, assigns are a synthesizable construct that essentially mean "connect this wire to this reg/wire". In reality, that assignment is going to end up optimised by the tools.
With all asynchronous assignments, the timing implications are going to depend on how long the wire is between 'a' and 'b'. If a mux is used, or any other processing performed (say,
assign a = b + c), that will also have an inherent propagation delay. How long are these in reality? Probably much shorter than a clock cycle. However you must be careful when going mad with assign statements. For example, this may get you into trouble with your timing constraints.
assign OutputQLLParity = QLLDout[23:21]^
Heading on to always blocks.
always @(posedge clk) begin
a <= y;
b <= a;
clk in the sensitivity list. This means that this process is going to only be executed (for lack of a better word) on the positive edge of a clock.
Say, for example, that
y changes after the clock rising edge. Even though
y has changed, a is only going to be updated on the next rising edge.
A is not updated directly on the rising edge, it's updated a tiny bit after that (this is called delta time). So b will only change on the clock cycle after that, a clock cycle after a.
Here, a handy timing diagram for you:
_____ _____ _____ _____
clk ____/ \____/ \____/ \____/ \____
So what does this look like in hardware?
They're not technically d-types in actuality, but it gives a good idea. A clocked register is used that propagates the input to the output on the rising clock edge.
simulate this circuit – Schematic created using CircuitLab
See the difference in assignments.
= is a blocking assignment,
<= is non-blocking.
It is possible to mix and match these in some cases, but if you're starting out with this, and just generally for your own sanity in the beginning, a good rule of thumb is
= is for assigns, initial blocks and processes without sensitivity lists*.
<= for processes with sensitivity lists.
* bit hazy about this. I don't use combinatorial processes in verilog very often.