was fairly sure that nonblocking assignments were sequential while blocking assignments were parallel.
Blocking assignment executes "in series" because a blocking assignment blocks execution of the next statement until it completes. Therefore the results of the next statement may depend on the first one being completed.
Non-blocking assignment executes in parallel because it describes assignments that all occur at the same time. The result of a statement on the 2nd line will not depend on the results of the statement on the 1st line. Instead, the 2nd line will execute as if the 1st line had not happened yet.
1) I am not able to understand how the changing from blocking to non-blocking
The example code posted was for a combinatorial block, changing all blocking (=
) to non-blocking (<=
) may affect simulation but will not affect synthesis. This results in a RTL to gate level mismatch. It is an incorrect place to use the non-blocking assignment, do not use it in a combinatorial section.
To summarise for the other question non-blocking simulates that data changing just after an event such as the posedge of a clock. This allows correct simulation of a flip-flop.
this implies for testbenches:
initial begin
#31 rx_data_out = 255;
At time 31 the assignment happens.
initial begin
#31 rx_data_out <= 255;
Just after time 31 the assignment happens. Try both in parallel with a
initial begin
#31 $display(rx_data_out);
end
For the first example you actually have a race condition both happen at the same time, you should get 255 printed out. For the second example you will always have x
printed because the assignment happens just after the time 31 event, not on it.
non blocking can be useful for testbenches were you want to mimic data being driven by flip-flops, i.e. it changes just after the event. for example releasing a power on reset.
initial begin
@(posedge clk);
@(posedge clk);
rst_n <= 1'b0;
end
Imagine we had a series of flip-flops (a,b,c) creating a delay line, they each have d input and q output.
if the assignments were chained with :
c = b = a
Data would rush through from a to c instantly. but if we have
c <= b <= a
we have a pipeline, and each flip-flop can hold its value.
Actual code:
always @(posedge clk) begin
c = b;
b = a;
a = in;
end
versus:
always @(posedge clk) begin
c <= b;
b <= a;
a <= in;
end
This is why for question 2 with only one assignment it does not matter. but if there are multiple assignments that rely on each other it really does matter because you're controlling if it is driven from a flip-flop (<=
) or a block of combinatorial logic (=
).
My rules of thumb:
Use blocking (=
) for combinatorial logic and non-blocking (<=
) for sequential (flip-flops)
Best Answer
What makes VHDL and verilog somewhat confusing is that they were originaly designed to describe hardware for simulation and later re-used to describe hardware for synthisis.
Careful.
Remember the initial state of registers is undefined. As a result unless you have specified the initial state of the registers* it is very likely your synthisizer will optimise this to all your signals having a constant value of 1.
Lets for now pretend that you did set the initial state of the registers to zero and you just haven't included that in your example. In that case as you say there will be three registers set one after another on the first three clock edges.
As photon says that code is equivilent to.
But none of that really answers your real question which boils down to.
How a blocking statement in a sequential always block behaves and hence how it is synthisized depends on where you read it. There are three cases.
In the first case, there is no need for a register (though one may be generated initially and then removed for having zero fanout). The signal just feeds through combinatorially.
In the second case the value needs to be stored from one clock cycle to the next, hence a register is needed.
Note that in some cases flow control may mean that a read is sometimes after a write and sometimes not, in that case the synthisis tool will need to generate a mux to either read from the register or directly from the logic as appropriate, just as it needs to generate muxes when a value is written on multiple different paths.
In the third case the behaviour is not well-defined. In simulation the results will depend on what order the always blocks are evaluated in. In synthisis the tool will probablly spit out a warning and do something, but what it does may not be what you wanted.
Hence you should avoid the third case, if you use blocking assignments in sequential always blocks you should only read the results of those assignments from within the same always block. Signals passing between different always blocks (or going out to the outside world) should always use nonblocking assignments.
* Unfortunately the ability to specify the initial state of registers is something that varies between tools (and versions of tools), some allow use of "initial" blocks for this purpose, some require tool-specific techniques, some don't support it at all.