I have been having a really hard time understanding the difference between blocking and non-blocking assignments in Verilog. I mean, I understand the conceptual difference between the two, but I am really lost when it comes to implementation.
I referred to a number of sources, including this question, but all the explanations seem to explain the difference in terms of code (what happens to the sequence of execution of lines when using blocking vs non-blocking). My question is a little different.
While writing verilog code (since I am writing it to be synthesized on an FPGA), I always try to visualize what the synthesized circuit is going to look like, and that is where the problem begins :
1) I am not able to understand how the changing from blocking to non-blocking assignments would alter my synthesized circuit. For example :
always @* begin
number_of_incoming_data_bytes_next <= number_of_incoming_data_bytes_reg;
generate_input_fifo_push_pulse_next <= generate_input_fifo_push_pulse;
if(state_reg == idle) begin
// mealey outputs
count_next = 8'b0;
if((rx_done_tick) && (rx_data_out == START_BYTE)) begin
state_next = read_incoming_data_length;
end else begin
state_next = idle;
end
end else if(state_reg == read_incoming_data_length) begin
// mealey outputs
count_next = 8'b0;
if(rx_done_tick) begin
number_of_incoming_data_bytes_reg <= rx_data_out;
state_next = reading;
end else begin
state_next = read_incoming_data_length;
end
end else if(state_reg == reading) begin
if(count_reg == number_of_incoming_data_bytes_reg) begin
state_next = idle;
// do something to indicate that all the reading is done
// and to send all the data in the fifo
end else begin
if(rx_done_tick) begin
generate_input_fifo_push_pulse_next = ~ generate_input_fifo_push_pulse;
count_next = count_reg + 1;
end else begin
count_next = count_reg;
end
end
end else begin
count_next = 8'b0;
state_next = idle;
end
end
In the above code, how would the synthesized circuit change if I replaced all the blocking assignments by non-blocking
2) Understanding the difference between blocking and non-blocking statements when written sequentially is a bit simpler (and most answers to this question focus on this part), but how do blocking assignments affect behaviours when they are declared in separate conditional behaviours. For example :
Would it make a difference if I wrote this:
if(rx_done_tick) begin
a = 10;
end else begin
a = 8;
end
or if I wrote this :
if(rx_done_tick) begin
a <= 10;
end else begin
a <= 8;
end
I know that conditional statements synthesize to become multiplexers or priority structures, and so I feel that using either blocking or non-blocking statements should not make a difference, but I am not sure.
3) When writing testbenches, I the result of the simulation is very different when using blocking v/s non-blocking statements. The behaviour is very different if I write :
initial begin
#31 rx_data_out = 255;
rx_done_tick = 1;
#2 rx_done_tick = 0;
#30 rx_data_out = 3;
rx_done_tick = 1;
#2 rx_done_tick = 0;
#30 rx_data_out = 10;
rx_done_tick = 1;
#2 rx_done_tick = 0;
end
versus when I write this :
initial begin
#31 rx_data_out <= 255;
rx_done_tick <= 1;
#2 rx_done_tick <= 0;
#30 rx_data_out <= 3;
rx_done_tick <= 1;
#2 rx_done_tick <= 0;
#30 rx_data_out <= 10;
rx_done_tick <= 1;
#2 rx_done_tick <= 0;
end
This is very confusing. In my practice, the rx_done_tick signal is going to be generated by a Flip Flop. So, I think that non-blocking statements should be used to represent this behaviour. Am I right ?
4) Finally, when to use blocking assignments and when not to use non-blocking statements ? I.e is it true that blocking statements should be used only in combinational behaviours , and non-blocking statements in sequential behaviours only? If yes or No, why ?