First of all, throw out this concept of 'instructions'. They do not exist in Verilog. Nothing is executed. Verilog, VHDL, SystemVerilog, etc. are what are called hardware description languages. They are not executed. They are not interpreted. They define hardware components (logic gates, flip flops, registers, etc.) and their interconnections. (Not entirely accurate I suppose; but the only verilog that you can put on an FPGA - synthesizable verilog - will not be executed or interpreted. Testbenches are a different animal.)
Clocks are used to drive flip flops and registers. Data can be shifted into flip flops and registers on the edges of the clock. So inside of an always @(posedge clk) block, all of the statements will be 'executed' simultaneously and the results will be latched into the registers on the clock edge, according to the rules of how the HDL statements are interpreted. Be very careful where you are using = and <=, though. The meaning of these two assignment operations is very different inside of an always block. The basic idea is that all of the = operations are dealt with first in order of appearance. This happens at the propagation speed of the gates. Then all of the <= are dealt with at the same time, storing the argument into a register. The only thing the clock affects in this case is precisely when the registers are updated. If you are running a simulation, it won't matter how many operations need to occur between registers, but on an FPGA the clock will have to be slow enough to ensure that any changes have been able to propagate through the logic.
Faster clocks can be generated using a device called a phased lock loop (PLL). PLLs are not synthesizeable in verilog, but generally there is a way to instantiate a dedicated PLL component on the FPGA you are using. Actually, I take that back, you can certainly make a digital PLL in verilog, but you can only use it to generate signals lower than the clock frequency. A PLL contains a voltage controlled oscillator, one or more frequency dividers, a phase comparator, and some control circuitry. The output of the VCO is divided down and phase compared with the input frequency. The VCO control voltage is adjusted until the divided down VCO output precisely matches the frequency and phase of the reference signal. If you set the divider to 5 and use 50 MHz for the reference frequency, the PLL will generate a 250 MHz signal that is precisely phase locked to the 50 MHz reference. There are several reasons for doing this. Using a PLL allows generation of multiple clocks so different logic can be run at different speeds e.g. for specific peripheral interfaces or for slow, complex combinatorial logic. It also can allow the device to control its own clock frequency to save power.
Blocking statements inside of always blocks will generate combinatorial logic. Again, this logic will generally always be 'executed' regarless of the clock because it defines actual logic gates. It can be beneficial to use a few temporary variables, but care must be taken to ensure that there isn't so much extra logic that the timing requirements are not met.
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
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.