Hi
Against all guidelines, I have always preferred using non-blocking assignments in always() blocks! The reason is that when using blocking assignments, you have to be careful about the order of statements, otherwise you will get a simulation/synthesis mismatch. An example of this is shown here. I believe that if this code is synthesized, it’s behavior will be as if the assignments in @() block were non-blocking.
I should say that although I use non-blocking assignments for combinational logic, I always observe the following rules:
1- All clocks and asynchronous resets should be driven by blocking assignments.
2- All sequential logic is described using non blocking assignments.
3- No mixture of blocking/non-blocking should ever happen, either in combinational or sequential blocks.
I wonder, considering the face that I always observe the above guidelines, is there anything bad which may happen due to my preference for non-blocking assignments when describing combinational logic? I understand that it may reduce simulation speed, but I guess that it’s worth it. Because getting a simulation/synthesis mismatch is much worse than getting slower simulations. Can we say that its a matter of personal preference? Or am I doing something which is seriously wrong and unprofessional?
Thanks
In reply to Farhad:
You have asked the same question before. If a clock goes through combinational logic with an NBA, you lose the determinism that the NBA was supposed to provide.
Also according to the LRM, variables that you make assignments to are not put into the senstivity list to re-trigger if you also plan on reading them in the same block. Some tools bend the rules, but you should not rely on that behavior.
In reply to dave_59:
Thank you, Dave. I am sorry, I didn’t remember that I had asked this question before. I guess the subject still has obscurities for me.
Also according to the LRM, variables that you make assignments to are not put into the senstivity list to re-trigger if you also plan on reading them in the same block.
Would you please elaborate this with an example so that I can understand it better? Or maybe refer me to the part of the LRM that explains this?
In reply to Farhad:
bit A,B,C,D
always @* begin
A <= B && C;
D <= !A;
end
The update to A does not “re-trigger” the always, so D has the negation of the previous value of A.
In reply to dave_59:
Thank you very much, Dave. I wonder, why does the LRM specify this behavior? If writing to a variable retriggered the always block, wouldn’t it be closer to the behavior of the synthesized code?
In reply to Farhad:
Maybe to avoid an infinite loop case .
bit A,C,D;
always @* begin
A <= D && C; // Previous value of D used
D <= !A; // Previous value of A used
$display(" TIME : %2t D would be assigned %0b " , $time , !( A ) );
$display(" TIME : %2t A would be assigned %0b \n" , $time , ( D && C ) );
end
initial #40 $finish();
initial begin
#5 ; B = 0 ; C = 0 ;
#5 ; B = 0 ; C = 1 ;
#5 ; B = 1 ; C = 0 ;
#5 ; B = 1 ; C = 1 ;
end
Since always @( * ) models combinational logic , we should use blocking assignment instead of non-blocking assignment .
In reply to Have_A_Doubt:
Thank you very much, Have_A_Doubt. I got your point. In your example, if writing to D re-triggered the always block, that would cause an infinite loop.
But your last sentence confuses me. I guess the example code you showed is erroneous for synthesis, isn’t it? If that’s the case, then why use blocking assignments, which actually screens the infinite loop problem in simulation? In every example I see, using non-blocking assignments causes simulation to behave exactly like synthesized design, while using blocking assignments can sometimes cause simulation-synthesis mismatch. I don’t really understand why every guideline insists on using blocking assignments for combinational logic. If we just commit ourselves to always use blocking assignments for clocks and asynchronous resets, then we can safely use non blocking assignments for all other combinational logic, which causes exact match between synthesis and simulation, and causes nothing bad to happen. This is really driving me crazy! I need some help on this. I understand that, as Dave said, “variables that you make assignments to are not put into the senstivity list to re-trigger”. But I know that Mentor tools, which I use for simulations, don’t obey this rule. So is there really some reason to stick with the guidelines and use blocking assignments for combinational logic?