I'm implementing a simple serializer in Verilog, but I do not understand the nuances of when blocking assigns can cause problems. I'm specifically having trouble understanding part of this answer. "However, you should never use blocking assignments for synchronous communication, as this is nondeterministic."
I'm building a block that takes, as an input:
- A bit clock
- A 5-bit parallel data input (the value to be serialized)
- A "Data valid" signal that indicates valid 5-bit data is present
As an output, I have:
- Serial data out
- A "Complete" signal that indicates it's time for a new 5-bit value
- A "Transmitting" signal that's high whenever there's valid serial data going out on the bus
Whenever data valid goes high, the block starts outputting the 5-bit value, one bit a time, starting at the next rising edge of the bit clock. When the last bit is out on the wire, the block signals "complete" so a new 5-bit value can be made available.
Omitting some of the reset logic, the code to do this looks like this:
Now, I can write the block with all non-blocking assigns, but I feel that it hurts readability. That would look something like this:
Both appear to do what I want in simulation, and I favor the 1st one because it's easier for me to read but since I don't understand why using blocking assignments for synchronous communication is nondeterministic, I'm worried that I've coded up a ticking time bomb
The Question: Am I doing something wrong in the 1st code that's going to blow up when I try to synthesize this? Is the 2nd code preferable despite being a bit harder (for me anyway) to read? Is there some 3rd thing I should be doing?
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 :
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:
or if I wrote this :
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 :
versus when I write this :
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 ?