M4 Verilog Notes
M4 Verilog Notes
MODULE 4
Verilog HDL is a hardware description language that can describe hardware not
only at the gate level and the register-transfer level (RTL), but also at the algorithmic
level. This makes translating a design described in Verilog HDL to logic gates a non-
trivial process. It explains how the basics involved in the mapping of a Verilog HDL
model to logic gates.
Having produced a gate level netlist, a logic optimizer reads in the netlist and optimizes
the circuit for the user-specified area and timing constraints. These area and timing
constraints may also be used by the module builder for appropriate selection or generation
of RTL blocks.
Figure 4-2 shows the basic elements of Verilog HDL and the elements used in
hardware. A mapping mechanism or a construction mechanism has to be provided that
Because of these problems, different synthesis systems support different Verilog HDL
subsets for synthesis. Since there is no single object in Verilog HDL that means a latch or
a flip-flop, each synthesis system may provide different mechanisms to model a flip-flop
or a latch. Each synthesis system therefore defines its own subset of Verilog HDL
including its own modeling style.
Figure 4-3 shows a circuit that is described in many different ways using Verilog HDL. A
synthesis system that supports synthesis of styles A and B may not support that of style C
This implies that typically synthesis models are non-portable across different synthesis
systems. Style D may not be synthesizable at all.
This limitation creates a severe handicap because now the designer not only has to
understand Verilog HDL, but also has to understand the synthesis-specific modeling style
before a synthesizable model can be written. The typical design process shown in Figure
4-4 cannot always be followed for Verilog HDL synthesis.
The problem with this design process is that if the Verilog HDL model is written without
knowing the synthesis modeling style (this assumes that the model is being written for
synthesis; if not, then a non-synthesizable model may be perfectly okay), only during the
synthesis phase will the de signer learn about the synthesis-specific modeling restriction
and style for synthesis. A model rewrite may be necessary at this point. Also a lot of time
may have been wasted in the "Write Verilog HDL model" -> "Compile model" ->
"Verify" -> "Edit model” loop. Instead, a more practical design process shown in Figure
4-5 has to be followed for Verilog HDL synthesis. The synthesis methodology checker is
B.S.BALAJI, ASST. PROF, DEPT. ECE. BGSIT – ACU. 3
V SEMESTER BE(ECE) VERILOG HDL (18EC55) 2020-21
needed to ensure that the model being written is synthesizable. Note that this must be
done within the first verification loop. In this way, after the verification results have been
checked, a verified synthesizable model exists, which can then be synthesized.
logic-0
logic-1
high-impedance
don't care
unknown
All these values are defined explicitly in Verilog HDL except for the don't-care value. A
synthesis system treats the value x, when it is assigned to a variable, as a don't care value.
Here is the mapping between the Verilog HDL values and the hardware modeling values:
1 <--> logic-1
z<--> high-impedance
x <--> unknown
x <--> unknown
4.4 Bit-widths
4.4.1 Data Types
In Verilog HDL, a variable belongs to one of the two data types:
When no size is explicitly specified in a net declaration, the default size is one bit.
Here are the different kinds of net data types that are supported for synthesis.
The wire net is the most commonly used net type. When there are multiple drivers driving
a wire net, the outputs of the drivers are shorted together. Here is an example.
The wor nets and wand nets are used when multiple driver resolution needs to be
performed using or-logic and and-logic respectively. Upon synthesis, multiple drivers of
such a net are connected together by an or gate (for a wor net) and by an and gate (for a
wand net). Here is an example that shows this effect.
Figure 4-7 Wand net and wor net have multiple drivers.
The different kinds of register types that are supported for synthesis are:
A reg declaration explicitly specifies the size, that is, the corresponding number of bits of
the variable in hardware. For example,
When no size is explicitly specified in a reg declaration, the default is one bit.
For an integer type, the maximum size is 32 bits and the number is assumed to be in 2's
complement form. Optionally a synthesis system may perform data flow analysis of the
model to determine the maximum size of an integer variable. For example,
Size of Arb is determined to be 6 bits. An adder of size 6 is sufficient. The leftmost bit is
the carry bit.
The register types: time and real, are not supported for synthesis.
i. Simple decimal
4.4.3 Parameters
RED and GREEN are two 32-bit signed constants. READY, BUSY and EXIT is three
parameters of size 2 bits each.
wire
A variable in Verilog HDL can either be of the net data type or the register data type. For
synthesis, a variable of net type maps to a wire in hardware and a variable of the register
type maps either to a wire or a storage element (flip-flop or latch) depending on the
B.S.BALAJI, ASST. PROF, DEPT. ECE. BGSIT – ACU. 8
V SEMESTER BE(ECE) VERILOG HDL (18EC55) 2020-21
context under which the variable is assigned a value. Let us look at a variable of register
type in more detail.
In Verilog HDL, a register variable retains its value through the entire simulation run,
thus inferring memory. However, this is too general for synthesis. Here is an example of a
variable that is used as a temporary and therefore need not be a candidate for a storage
element.
Variable Trq is assigned in the first statement and then used in the right hand-side
expression of the second statement. Verilog HDL semantics indicate that Trq retains its
value through the entire simulation run. However, it is not necessary to store the value of
Trq as a storage element in hardware, since it is assigned and used immediately. Figure 4-
8 shows the logic generated.
Let us look at another example. In this case, variable Trq is used before its assignment.
The semantics of this always statement is very clear in Verilog HDL. Whenever an event
occurs on Bar, Acr, or Fra (those in the event list), execute the always statement. Since
Trq is used before its assignment, Trq has to hold its value during repeated executions of
the always statement, thus inferring memory. However, it is not clear how to build a latch
for Trq because Trq is not assigned a value under the control of any condition.
The variable Fox is not assigned in the else-branch of the conditional statement.
Consequently, a latch is inferred for Fox since it needs to retain its value when Sat is true.
The circuit synthesized in shown in Figure 4-10. How is a flip-flop inferred? It depends
on the modeling style being followed and the context under which a variable is assigned a
value.
This and other examples for flip-flop and latch inferencing are discussed in the next
chapter. A memory in hardware can be modeled as an array of flip flops or latches.
4.6 Verification
B.S.BALAJI, ASST. PROF, DEPT. ECE. BGSIT – ACU. 10
V SEMESTER BE(ECE) VERILOG HDL (18EC55) 2020-21
Having synthesized a Verilog HDL model into a netlist, it is important to verify the
functionality of the synthesized netlist to ensure that it still matches the intended
functionality. This step is important since a synthesis system may make certain
assumptions or interpretations of the Verilog HDL code that may not match those
intended by the model writer.
In this chapter, we assume that this verification step is performed using simulation which
verifies the functionality between the design model and its synthesized netlist. We
illustrate some cases of functional mismatches between the design model and its
synthesized netlist that might possibly occur, describe their cause, and provide
recommendations for avoiding them.
In this chapter, we assume that the synthesis process produces a synthesized netlist in
Verilog HDL as shown in Figure 4-11. A Verilog HDL netlist is a collection of module
instances interconnected by nets.
If vectors from a stimulus file were applied, say every 1 ns, and all the module instances
in the netlist represent behavioral models with no delay, the results between the design
B.S.BALAJI, ASST. PROF, DEPT. ECE. BGSIT – ACU. 13
V SEMESTER BE(ECE) VERILOG HDL (18EC55) 2020-21
model and the netlist will be skewed because of the difference in delays. The correct
approach in such a case is:
ii. Or to apply the stimulus with a period greater than 5 ns: a better rule. When delays are
present in the models for the library modules, these delays must also be considered in
determining the stimulus period.
Recommendation: A good synthesis system will issue warning messages about a value
used before being assigned (such as variable C in the module AO122). Pay attention to
these warnings.
In this always statement, variable DebugX is assigned in all branches of the if statement.
However, data flow analysis reveals that the value of DebugX needs to be saved (since its
value is used before an assignment when Control is false). In this case, a synthesis system
may produce a warning message about variable DebugX being used before its assignment
and also about a potential functional mismatch that may occur between the design model
and its synthesized netlist.
ii. Variable is NOT assigned in all branches of the conditional statement, and
iii. Value of variable needs to be saved between multiple invocations of the always
statement.
All the three conditions must be satisfied before a variable is inferred as a latch. In the
above always statement, DebugX violates rule (ii). Therefore no latch is produced for
DebugX.
In this always statement, it appears that there should be a latch for either DebugX or Bdy.
There is no latch for DebugX since it violates rule (ii). There is no latch for Bdy since it
violates rule (i). Language semantics however indicate that value for Bdy needs to be
saved. A synthesis system in this case may not produce a latch; instead it may issue a
warning message about Bdy being used before its assignment and in addition, produce a
warning message about a potential for functional mismatch that may occur.
In the following always statement, no latch is produced for DebugX since it violates rule
(ii) but a latch is produced for Bdy.
Model simulation shows a value of 1 on LX after 3 ns and the value going to 0 after 5 ns
if the condition CondA is true. However, since a synthesis system ignores delays, if
CondA is true, the net effect is as if a 0 is assigned to LX and the appropriate hardware
gets synthesized to reflect this. Notice that if the synthesized netlist is simulated, the value
of LX will not go to 1 if CondA is true.
Here is another example of an always statement with an incomplete event list that may
cause functional mismatches.
The variable Pbus is not in the event list of the always statement. However in the
synthesized netlist, any changes on Pbus will propagate into Treg if the if condition is
false. This is not consistent with the design model semantics and thus a functional
mismatch occurs.
Recommendation: For an always statement without a clock event (that is, when modeling
combinational logic), include all variables read in the always statement in the event list.
The full_case directive tells the synthesis tool that all possible values that can possibly
occur in CurrentState have been listed and the value of Next State is a don't care for all
other cases, and therefore, the synthesis tool should not generate latches for NextState.
However this may not be true in simulation. It could happen that CurrentState for some
reason, gets a value of 2'b00. In such a case, the case statement simulates as if NextState
value is saved, but in the synthesized netlist, the value of NextState may not be saved.
Simulation semantics of the case statement (the parallel_case directive is ignored since it
is a comment) specifies that if Gatel is a 1, then assign 1 to Mask1, else if Gate2 is a 1,
assign 1 to Mask2, else if Gate3 is a 1, assign 1 to Mask3. However, with the
parallel_case directive, instead of a priority if-structure being synthesized, a parallel
decoder is synthesized. This can cause functional mismatches to occur. What if both
Gate3 and Gatel were 1 at the same time? In the case statement, the first branch is taken,
whereas in the synthesized netlist, both branches 1 and 3 are enabled. Here is the
semantics for the case statement expressed using an if statement.
Recommendation: Use caution when using the synthesis directives: full case and
parallel_case. Use only if really necessary.
Two flip-flops with asynchronous preset and clear are synthesized for the variable
QuickBus. The variable LoadData is connected to the preset clear inputs of the flip-flops
through other logic. When PreLoad is active (is 0) and LoadData changes, the outputs of
the flip-flops are immediately affected because of the asynchronous data change.
However in the design model, any change on LoadData has no effect on the output
QuickBus. Thus there is a mismatch.
Recommendation: Avoid asynchronously reading a variable and as signing it to a flip-
flop; else ensure that there are no changes on asynchronous data when the asynchronous
conditions are active.
When the first assignment statement executes, TM does not get updated immediately but
is scheduled to be assigned at the end of the current simulation cycle. Since all statement
executions occur sequentially and in zero time, so when the third statement is executed,
the old value of TM is used to compute the value of TO (TM has not been assigned its
new value yet). Consequently, the output TZ does not reflect the and-or-invert behavior
of the logic. The problem is that TM, TN, and TO all get updated at the end of the current
simulation cycle and these updated values are not used again to reevaluate the logic.
A solution to this problem is to place variables TM, TN and TO also in the event list of
the always statement, such as:
In this case, when TM, TN or TO changes, the always statement is re evaluated and
eventually TZ does get the correct value. So there are two problems that have been
identified:
These problems can simply be avoided by using blocking assignments when modeling
combinational logic and are therefore recommended.
To avoid this simulation behavior dependence, it is best to force the assignment to occur
at a later time, a time after which all reads are guaranteed to have been completed. This
can be achieved by using the non blocking assignment. In such a case, the read of
DataOut occurs at the current time, while a new value is assigned to DataOut at the end of
the current simulation step (that is, after all reads are completed). This makes the behavior
of the model insensitive to the order of the always state ments. Here are the always
statements with non-blocking assignments used.
So we see that if a variable is assigned a value in one always statement and its value read
external to that always statement, the assignment should be a non-blocking procedural
assignment.
What if the assignment and reading of a variable all occur in the same clocked always
statement? In such a case, blocking assignments may be used.
Total is a variable assigned and then read within the same always statement. In this case,
we would like the assignment to Total to be completed before the if condition is
evaluated. Total is a temporary; a value is assigned to it and then read. Thus a blocking
assignment is suitable for Total.
then the value of Total when the if condition is evaluated is the old value of Total, not the
value that is scheduled to be assigned to it in the previous assignment.
Therefore, the recommendation is to use non-blocking assignments for variables that are
read outside of the always statement in which they are assigned. Additionally, for
variables that are assigned and used only within an always statement, use blocking
assignments.