Does Verilog support short circuit evaluation? - verilog

If I have an if statement like:
if(risingEdge && cnt == 3'b111)
begin
...
end
Will it check on cnt if risingEdge is not true?
Does this even matter inside of an HDL?

For simulation it is undefined as to whether short-circuited expressions are evaluated or not. In the above example it makes no difference, but if you have a function call on the right hand side then you may run into problems with undefined side effects.
See Gotcha #52 in "Verilog and SystemVerilog Gotchas: 101 Common Coding Errors and How to Avoid Them" by Stuart Sutherland and Don Mills.

In terms of whether it matters in an HDL, I presume you are asking whether it would matter when synthesized. Short answer is that it would. For example, the following code is synthesizable SystemVerilog :
if(risingEdge && cnt++ == 3'b111)
begin
...
end
In Verilog (not SV) the post-increment could be replaced with a verilog function that has other assignments to module variables to show the same thing. So yes it is a relevant question.
Paul R is generally correct, and the Sutherland reference is a great one (lots of good things like that described in those Gotchas). For reference though, this has changed with SystemVerilog, at least as far as the specification is concerned. While Verilog specifies that short-circuited operations may or may not be executed, SV disambiguates this by indicating that implementations shall not evaluate the short circuited operands (similar to C++, Java, etc). See IEEE-1800-2009 section 11.3.5 if you are interested. While this is great, the track record for adhering to the SV spec is not stellar across all tool providers, so use care when relying on it in SV.

Related

Incomplete assignment and latches

When incompletely assigning a value I get a latch. But why did I get a latch in the example below? I think there is no need for the latch of F output because it is defined at all values of SEL.
Verilog code:
always # (ENB or D or A or B pr SEL)
if (ENB)
begin
Q=D;
if (SEL)
F=A;
else
F=B;
end
Inferred logic:
Although it is defined at all values of SEL, it is not defined for all values of ENB. If ENB = 0, your code says that both Q and F should hold the value from the previous cycle. This is also what is inferred in the image you are linking: only update Q and F if ENB = 1.
If you want Q to be a latch and F not, you can do this:
always # (ENB or D or A or B or SEL)
begin
if (ENB)
Q=D;
if (SEL)
F=A;
else
F=B;
end
Edit: additional information
As pointed out in the comments, I only showed how you could realize combinational logic and a latch, without modifying your code too much. There are, however, some things which could be done better. So, a non-TL;DR version:
Although it is possible to put combinational logic and latches in one procedural block, it is better to split them into two blocks. You are designing two different kinds of hardware, so it is also better to seperate them in Verilog.
Use nonblocking assignments instead of blocking assignments when modeling latches. Clifford E. Cummings wrote an excellent paper on the difference between blocking and nonblocking assignments and why it is important to know the difference. I am also going to use this paper as source here: Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill!
First, it is important to understand what a race condition in Verilog is (Cummings):
A Verilog race condition occurs when two or more statements that are scheduled to execute in the same simulation time-step, would give different results when the order of statement execution is changed, as permitted by the IEEE Verilog Standard.
Simply put: always blocks may be executed in an arbitrary order, which could cause race conditions and thus unexpected behaviour.
To understand how to prevent this, it is important to understand the difference between blocking and nonblocking assignments. When you use a blocking assignment (=), the evaluation of the right-hand side (in your code A, B, and D) and assignment of the left-hand side (in your code Q and F) is done without interruption from any other Verilog statement (i.e., "it happens immediately"). When using a nonblocking assignment (<=), however, the left-hand side is only updated at the end of a timestep.
As you can imagine, the latter assignment type helps to prevent race conditions, because you know for sure at what moment the left-hand side of your assignment will be updated.
After an analysis of the matter, Cummings concludes, i.a., the following:
Guideline #1: When modeling sequential logic, use nonblocking assignments.
Guideline #2: When modeling latches, use nonblocking assignments.
Guideline #3: When modeling combinational logic with an always block, use blocking assignments.
A last point which I want to highlight from the aforementioned paper is the "why". Except from the fact that you are sure the right hardware is infered, it also helps when correlating pre-synthesis simulations with the the behaviour of your actual hardware:
But why? In general, the answer is simulation related. Ignoring the above guidelines [about using blocking or nonblocking assignments on page 2 of the paper] can still infer the correct synthesized logic, but the pre-synthesis simulation might not match the behavior of the synthesized circuit.
This last point is not possible if you want to strictly adhere to Verilog2001, but if you are free to choose your Verilog version, try to use always_combfor combinational logic and always_latch for latches. Both keywords automatically infer the sensitivity list, and it is easier for tools to find out if you actually coded up the logic you intended to design.
Quoting from the SystemVerilog LRM:
The always_latch construct is identical to the always_comb construct except that software tools should perform additional checks and warn if the behavior in an always_latch construct does not represent latched logic, whereas in an always_comb construct, tools should check and warn if the behavior does not represent combinational logic.
With these tips, your logic would look like this:
always_latch
begin
if (ENB)
Q <= D;
end
always_comb
begin
if (SEL)
F = A;
else
F = B;
end

Synthesizable arithmetic shift in Verilog

I recently came across this answer on stackoverflow.
With Verilog, once you take a part-select, the result is unsigned. Use the $signed system task on the part select to make it signed.
Is this method synthesizable (ie the system task $signed)
If it is not synthesizable, is there a different way to perform arithmetic shift on variables like a <= a>>>2 (this should give the quotient when a is divided by 4).
It certainly is synthesizable. Whether your particular tool supports it is another question.
You can also use a cast in SystemVerilog.
res = signed'(registers[0][0]) >>> 2;

What is the difference between "," and "or" in always #?

Is there a difference between using , and or in always #.
For example:
always #(S or C)
and
always #(S,C)
If there is a difference, what is it?
They're synonymous. There's no difference whatsoever.
Also, consider using always #(*) for combinational blocks; it's supported by all modern synthesis tools, and automatically makes the block sensitive to any signals referenced in the block.
If you're using SystemVerilog, you should consider using always_comb instead.
There's no difference; they are alternative syntaxes for the same behavior. Originally (in the 1980s) Verilog only allowed #(S or C), but many people confused that with #(S || C). That means wait for a change in the result of the logical or expression S || C. Further complicating matters is that VHDL uses or for their logical boolean operator. So #(S, C) was added probably before 1990 to avoid confusion with the logical operator.
Note that for synthesizable combinational logic, you should be using implicit sensitivity with either
alway #(*) // ... Verilog
always_comb // ... SystemVerilog

Want help in understanding verilog constructs

I am new to understanding Verilog as this language requires thinking in terms of synthesis.
While doing some program I found that:
begin
buf_inm[row][col] =temp_data;
#1 mux_data=buf_inm[row][col];
end
gave correct results than
begin
buf_inm[row][col] =temp_data;
mux_data=buf_inm[row][col];
end
in terms of assignments of variables.
Can anybody explain what is the difference between these two?
In any other higher level languages construct 2 (without delay) would have given correct assignments.
Thanking you,
Yours sincerely,
R. Ganesan.
First of all #1 is a one time scale delay that you can use in simulation, but it is not synthesizeable. When you say "gave correct results", it might help if you explained what results you are seeing, but my guess is that you assigned something to the 2 dimensional vector, and then you assign that to the max_data and are expecting mux_data to be what temp data was. Is it retaining old data? Is it undefined?
That said, I would say the difference is a synthesizeable assignment versus a non-sythesizeble one. In the first case you should see two state changes separated by a timescale unit. The second case, because it is blocking, should see both values update in zero-time, and in the order as written top to bottom. If you aren't seeing that, something else is potentially at foot here. What tool are you using? Tool version? Maybe you can share your full code and test bench so we can see why your results are unexpected.

Verilog Best Practice - Incrementing a variable

I'm by no means a Verilog expert, and I was wondering if someone knew which of these ways to increment a value was better. Sorry if this is too simple a question.
Way A:
In a combinational logic block, probably in a state machine:
//some condition
count_next = count + 1;
And then somewhere in a sequential block:
count <= count_next;
Or Way B:
Combinational block:
//some condition
count_en = 1;
Sequential block:
if (count_en == 1)
count <= count + 1;
I have seen Way A more often. One potential benefit of Way B is that if you are incrementing the same variable in many places in your state machine, perhaps it would use only one adder instead of many; or is that false?
Which method is preferred and why? Do either have a significant drawback?
Thank you.
One potential benefit of Way B is that if you are incrementing the same variable in many places in your state machine, perhaps it would use only one adder instead of many; or is that false?
Any synthesis tool will attempt automatic resource sharing. How well they do so depends on the tool and code written. Here is a document that describes some features of Design Compiler. Notice that in some cases, less area means worse timing.
Which method is preferred and why? Do either have a significant drawback?
It depends. Verilog(for synthesis) is a means to implement some logic circuit but the spec does not specify exactly how this is done. Way A may be the same as Way B on an FPGA but Way A is not consistent with low power design on an ASIC due to the unconditional sequential assignment. Using reset nets is almost a requirement on an ASIC but since many FPGAs start in a known state, you can save quite a bit of resources by not having them.
I use Way A in my Verilog code. My sequential blocks have almost no logic in them; they just assign registers based on the values of the "wire regs" computed in the combinational always blocks. There is just less to go wrong this way. And with Verilog we need all the help we can get.
What is your definition of "better" ?
It can be better performance (faster maximum frequency of the synthesized circuit), smaller area (less logic gates), or faster simulation execution.
Let's consider smaller area case for Xilinx and Altera FPGAs. Registers in those FPGA families have enable input. In your "Way B", *count_en* will be directly mapped into that enable register input, which will result in less logic gates. Essentially, "Way B" provides more "hints" to a synthesis tool how to better synthesize that circuit. Also it's possible that most FPGA synthesis tools (I'm talking about Xilinx XST, Altera MAP, Mentor Precision, and Synopsys Synplify) will correctly infer register enable input from the "Way A".
If *count_en* is synthesized as enable register input, that will result in better performance of the circuit, because your counter increment logic will have less logic levels.
Thanks

Resources