The differences between 5 behavioral model for OR gate - delay

I want to design 5 behavioral model for OR gate. What is the difference between these models? Each of models implement which of delays (inertial delay and transport delay) and what is the reason?
Model 1: LHS blocking
#4 O = (A | B);
Model 2: LHS non-blocking
#4 O <= (A | B);
Model 3: RHS blocking
O = #4 (A | B);
Model 4: RHS non-blocking
O <= #4 (A | B);
Model 5: Continuous assignment
assign #4 O = (A | B);

There is a very good paper "Correct Methods For Adding Delays To Verilog Behavioral Models" by Clifford E. Cummings, where you can find some hints about using different delay models in Verilog:
Blocking assignment delay models:
Modeling Guideline: do not place delays on the LHS of
blocking assignments to model combinational logic. This
is a bad coding style.
Testbench Guideline: placing delays on the LHS of
blocking assignments in a testbench is reasonable since
the delay is just being used to time-space sequential input
stimulus events.
RHS blocking delays:
Modeling Guideline: do not place delays on the RHS of
blocking assignments to model combinational logic. This
is a bad coding style.
Testbench Guideline: do not place delays on the RHS of
blocking assignments in a testbench.
General Guideline: placing a delay on the RHS of any
blocking assignment is both confusing and a poor coding
style. This Verilog coding practice should be avoided.
Nonblocking assignment delay models:
Modeling Guideline: do not place delays on the LHS of
nonblocking assignments to model combinational logic.
This is a bad coding style.
Testbench Guideline: nonblocking assignments are less
efficient to simulate than blocking assignments; therefore,
in general, placing delays on the LHS of nonblocking
assignments for either modeling or testbench generation is
discouraged.
RHS nonblocking delays:
Recommended Application: Use this coding style to
model behavioral delay-line logic.
Modeling Guideline: place delays on the RHS of
nonblocking assignments only when trying to model
transport output-propagation behavior. This coding style
will accurately model delay lines and combinational logic
with pure transport delays; however, this coding style
generally causes slower simulations.
Testbench Guideline: This coding style is often used in
testbenches when stimulus must be scheduled on future
clock edges or after a set delay, while not blocking the
assignment of subsequent stimulus events in the same
procedural block.
Continuous assignment delay models:
RHS delay model is illegal with continuous assignment
Models mentioned earlier model following delays:
Adding delays to continuous assignments accurately models combinational logic with inertial delays.
Adding delays to the right hand side (RHS) of nonblocking assignments will accurately model combinational logic with transport
delays.

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

Will latches occur in sequential logic in verilog

This is a basic question but it seems to lack of clear explanation to me.
In many of code examples,one style to write FSM output is
assign a = (current_state==DONE)?1:0;
I confuse this with definition of latches. Will this combinational logic infer latches as "a" holds its previous value if current_state != DONE? It seems no warnings from my compiler.
sometimes, i would have
always#(posedge clk)
begin
if(reset)
a<= 1'b0;
else
if(current_state == DONE)
a <=1'b1;
end
This is certainly a sequential logic(tho my output does not depend on my chains of past input) and a would keep its previous value until my control signal current_state == DONE.I would guess this logic will synthesize to a mux to the input of a flipflop.
so if in the 2nd case that I actually have a clocked FSM, i would have my mux with FSM states output as the select signal input.
Until now, can i say anything that is not combinational logic will not generate any latches?
However,when i have a structure like the following,
always#(posedge DCO or posedge reset or posedge enable)
begin
if(reset)
begin
end
else if(enable)
begin
end
else
begin
end
end
I get a warning in my FPGA that i have inferred a latch with control signal enable.
Why?
My enable changes based on another state machine for example,
assign enable = (pcurrent_state == START)?1:0;
Moreover, we have unintentional latches and intentional latches. but design rule basically says to avoid latches to avoid timing arches. Can someone give some examples of where intentional latches should be used in design rather than clock gating example?
Plus,
The output of all the storage elements (flip-flops) in the circuit at any given time, the binary data they contain, is called the state of the circuit. The state of a synchronous circuit only changes on clock pulses. At each cycle, the next state is determined by the current state and the value of the input signals when the clock pulse occurs.(from https://en.wikipedia.org/wiki/Sequential_logic)
This sounds like describing a mealy machine to me rather than a typical sequential logic. My simplest sequential logic does not need my output change determined by my current_state
Thank you for any help. I am doing this coding everyday and reading its definition but it seems that i am confusing myself without discuss with others.
To answer your question in parts:
The given assign statement will not infer a latch as a does not retain it's value. It will be 1 if current_state == DONE and otherwise be 0. So it's pure combinational logic.
The second block of code implements a flip-flop with synchronous reset and only loads itself with 1'b1 if current_state == DONE so there is retention in that code. This code shouldn't generate a latch due to the edge sensitivity on a single clock.
The last block would be difficult for any synthesis tool to handle due to the sensitivity on serveral signals, which is not common in hardware. Moreover, if say enable is asserted but not an edge when a positive edge of DC0 comes along, the code would have the body of the else if (enable) run, thus simulating some sort of latching behavior. Synthesis tools generally allow for a single clock and single reset to be specified in the sensitivity list of an always block to indicate a flip-flop with asynchronous reset. While Verilog certainly allows for more complicated sensitivity lists, their physical meaning gets complicated quickly, thus inferring latches. In most designs, you shouldnt ever need these complex sensitivity lists are you are then getting into asynchronous design for which most synthesis tools are not well suited on a behavioral level. FPGA tools especially are poor at asynchronous elements and even latches as the logic cells in the fpga to which the design must be mapped are designed specifically for synchronous designs using flip-flops; that's how fpgas are implemented.
Finally, in non-fpga designs, it is sometimes desirable to use latches if edge sensitivity isn't required, as latches are physically smaller and can allow a design to be smaller, faster and more power efficient in some cases. However, you need to have a firm grasp on what you are designing and understand potential trade offs and timing requirements when doing so. Here's an example of when a latch is a useful element: https://electronics.stackexchange.com/questions/255009/what-is-application-of-latch-in-vlsi-design

What is the difference between structural Verilog and behavioural Verilog?

As in the title, what are the main differences between structural and behavioural Verilog?
There is no strict definition of these terms, according to the IEEE Std. However, customarily, structural refers to describing a design using module instances (especially for the lower-level building blocks such as AND gates and flip-flops), whereas behavioral refers to describing a design using always blocks.
Gate netlists are always structural, and RTL code is typically behavioral. It is common for RTL to have instances of clock gates and synchronizer cells.
Structural
Here functions are defined using basic components such as an invertor,
a MUX, a adder, a decoder, basic digital logic gates etc.. It is just
like connecting and arranging different parts of circuits available to
implement a function.
Behavorial
The Behavioral description in Verilog is used to describe the function
of a design in an algorithmic manner. Behavioral modeling in Verilog
uses constructs similar to C language constructs. Further , this is
divided into 2 sub categories .
(a) Continuous
assignment of data to outputs are continuous. This will be
implemented using explicit "assign" statements or by assigning a
value to a wire during its declaration .
In case of assign any change in input will
immediately effect the output . Hence output is to be declared as
wire
(b) Procedural
Here the data assignments are not carried out continuously instead it
happens on specific events specified in sensitivity list. This type of
modelling scheme is implemented using procedural blocks such as
"always"or "initial" .
Here, output variables must be defined as reg because they need to
keep hold of previous value until new assignment occurs after any change in specified sensitivity list.
Hope this helps :)
Structural Verilog is usually referred to a Verilog code which is synthesizable (has an accurate and meaningful hardware realization) and is usually written in Register Transfer Level (RTL).
On the other hand Behavioral Verilog is usually a behavioral description of a hardware or functionality on a higher level. behavioral code does not have to be synthesizable for example when you define a delay in your verilog code scaled by the timescale, the synthesizer does not consider it when it is translating your code into logic and hardware, but rather it has simulation purposes.
The same goes for structural and behavioral VHDL.
Behavioral doesn't use logic gates description you can use And,Or,Not gates that are already defined in verilog
while structural uses logic gates description where you describe that you want a module called (And/Or/Not) and describe what it does & / | / ~.
Structural verilog deals with the primitives in simple word like and, or, not etc..
The primitives are called/inferred from libraries and connected with input output ports.
Example
module structural(y,a,b);
input a,b;
output y;
and a1 (y,a,b); // and is the primitive inferred and a1 is the instance name.
endmodule
Behavioral verilog deals with the logic or behavior of a system. It handles complex logic implementation and which is why in industry all implement the behavioral models of the system called as RTL. Once the behavioral RTL is validated by front end engineers using SV/UVM then this RTL is converted into Gate Level i.e Structural which go for synthesis.
Please refer the book of verilog written by Samir Palnitkar for more details.
Verilog is both a behavioral and a structural language. Internals of each module can be defined at four levels of abstraction, depending on the needs of the design.
Structural Verilog describes how a module is composed of simpler modules or of basic primitives such as gates or transistors. Behavioral Verilog describes how the outputs are computed as functions of the inputs.
Behavioral level
->This is the highest level of abstraction provided by Verilog HDL. mainly construct using
"always" and "initial" block.
Dataflow level
-> At this level, the module is designed by specifying the data flow. condition describe using "assign" keyword.
Gate level
->The module is implemented in terms of logic gates and interconnections between
these gates.
Switch level
->This is the lowest level of abstraction provided by Verilog. A module can be
implemented in terms of switches, storage nodes, and the interconnections
between them.

Using blocking assignments to infer flip-flops in Verilog

I have read "Nonblocking Assignments in Verilog Synthesis, Coding Styles that Kill!" by Clifford Cummings. He says that the following code (page 12, simplified) is a correct implementation of a flip-flop often used in textbooks, even if not exactly the kind that anyone should use. The document won a best paper award, so I assume the claim is true.
module ff (q, d, clk)
output q;
input d, clk;
reg q;
always #(posedge clk)
q = d;
endmodule
I would like to know why this would continue to work correctly if two or more of these flip-flops were connected in series. Say
module two_ffs (q, d, clk)
input d, clk;
output q;
wire tmp;
ff firstff (tmp, d, clk);
ff secondff (q, tmp, clk);
endmodule
The way I see it, it's possible that the value of tmp is updated before it is used by secondff, thus resulting in one flip-flop rather than two. Can someone please tell me what part of the standard says that cannot happen? Many thanks.
[not that I would ever contemplate writing code like that, I just want to understand the blocking/nonblocking behavior even in cases when poor coding style makes the meaning non-obvious]
Added later:
I now think the paper is unlikely to be correct. Section 5 "Scheduling Semantics" of the 1364-2201 Verilog standard explains what happens. In particular, section 5.6.6 "Port connections" on page 68 says that unidirectional ports are just like continuous assignments. In turn, a continuous assignment is just an always block sensitive to everything. So the bottom line is that that the two instantiations of an ff in my example below are equivalent to a module with multiple always clauses, which everyone would agree is broken.
Added after Clive Cummings answered the question:
I am grateful to CC for pointing out that that the statements above taken out of section 5 of the standard only refer to the timing of update events, and do not imply literal equivalence between e.g. some continuous assignments and always blocks. Nevertheless, I think they explain why some simulators (e.g. Icarus Verilog) will produce different simulation results with a blocking and a non-blocking assignment in the "flip-flop". [On a larger example, I got 2 apparent ffs with a blocking assignment, and the correct five with a non-blocking one.] Other simulators (e.g. Modelsim with default options or Cver) seem to produce the same result no matter which form of assignment is used.
All -
A few corrections and updates. Section 5.6.6 of the 2001 Verilog Standard does not say that "unidirectional ports are just like continuous assignments," it says "Ports connect processes through implicit continuous assignment statements." There is a difference that I will note below.
Second, "a continuous assignment is just an always block sensitive to everything," is not true. Continuous assignments Drive values onto nets that can be driven by other sources with pre-defined resolution functions as described in the Verilog Standard. Always blocks Change values of variables and last procedural change wins (no resolution).
Regarding my description of the 1-always block flip-flop, my description in the paper is not 100% accurate (but is usually accurate). The 2-instantiated flip-flop model in theory does have a race condition, though it is rarely seen. The race is rarely seen because when you make an always block assignment to a variable that is declared as an output, Verilog compilers automatically throw in an "implicit continuous assignment statement" (IEEE-1364-2001, Section 5.6.6, 1st paragraph) to convert the procedural variable into a net-Driving assignment (you never see this happen!) This conversion is typically sufficient to introduce the equivalent of a nonblocking assignment delay on the port, so the simulation works. I have experimented in the past with compiler optimization switches that effectively remove the module ports between the flip-flops and have observed the unwanted race conditions, so technically, my description of an okay 1-always, blocking-assignment flip-flop is not 100% correct; hence, you should still use the nonblocking assignments described in the paper.
The 2-always blocking-assignment example in the same module has a definite race condition. As written, it will probably work because most compilers execute the code top-down, but if you reverse the order of the always blocks, you will probably see a race.
Regards - Cliff Cummings -
Verilog & SystemVerilog Guru
Reading Version 1.3 of the paper, Section 9 Example 13. The text under it explains that it is OK if the module only contains a single always block. My current understanding is that it is not an issue between separate modules. Allowing your example to work. However if a module contained multiple always blocks then the order of execution is undefined and will lead to the race conditions talked about in section 2 of the paper.
The example below is almost the same as the 2 flop example in the question, except it is in 1 module and so has an undefined order of execution, this will likely not work.
module ff (q, d, clk)
output reg q;
input d, clk;
reg d_delay ;
always #(posedge clk)
d_delay = d;
always #(posedge clk)
q = d_delay;
endmodule

Precise rules to determine what Verilog tool is synthesisable

I am reading the IEEE Standard Verilog Hardware Description Language (specifically IEEE Std 1364-2001) which unambiguously defines and discusses simulatable Verilog. Unfortunately, the document does not touch upon the notion of synthesis.
I haven't been able to find a similar reference for synthesisable Verilog. All I find is vague rules, or unnecessarily restrictive ones.
Where can I learn the formal language of synthesisable Verilog?
IEEE 1364.1 is an adjunct to the 1364 Verilog standard titled Verilog Register Transfer Level Synthesis, which attempts to define a common synthesizable subset. However, as Jerry points out, different tools support different constructs, and to determine tool-specific behavior, you need to consult the tool documentation.
There isn't a formal (BNF-style) syntax definition for synthesizable Verilog. Whether code is synthesizable depends on usage as well as syntax. For example, the behavior described by an always construct with incomplete sensitivity, like always #(a) o = a || b, isn't synthesizable. (Most tools will synthesize that code as if the sensitivity list were complete, resulting in a possible simulation/synthesis mismatch.)
Circuit constructs like latches and multiply-driven nets can be synthesized from a Verilog description, but are disallowed or discouraged under most design rules. There are also synthesizable constructs that are unsupported or inadvisable given the choice of target library. For example, describing a RAM that's larger than the maximum supported by a chosen FPGA technology, or describing tri-state drivers when they aren't present in the target library.
The general constructs to stick to for synthesizable Verilog are:
Combinational logic modeled with continuous assignments (assign statements)
Combinational logic modeled with always blocks, which should use blocking assignments, and either have a complete sensitivity list or use always #*
Sequential logic (flip-flops) modeled with always blocks, which should use non-blocking assignments, and have either posedge clock alone (for sync reset or non-reset flops) or posedge clock and posedge or negedge reset (for async reset flops) in the sensitivity list.
The safest coding style for sequential logic is to code only reset logic in the sequential always block:
always #(posedge clk or posedge reset)
if (reset)
q <= reset_value;
else
q <= next_value;
However, if you're careful, you can code additional combinational logic in the sequential block. A common case where it may make sense to do this is a mux in front of a flop:
always #(posedge clk)
if (!sel)
q <= sel0_value;
else if (sel)
q <= sel1_value;
else
q <= 'bx;

Resources