Lab # 2 Verilog Structure: 2.1 Modules
Lab # 2 Verilog Structure: 2.1 Modules
Lab # 2 Verilog Structure: 2.1 Modules
Verilog Structure
This lab gives a quick overview of the structural elements of Verilog and discusses the time flow
and time control statements. Verilog differs from regular programming languages (C, Pascal, ...)
in 3 main aspects: (1) simulation time concept, (2) multiple threads, and (3) some basic circuit
concepts like network connections and primitive gates. If you know how to program in C and
you understand basic digital design then learning Verilog will be easy.
2.1 Modules
In Verilog, circuit components are designed inside a module. Modules can contain both
structural and behavioral statements. Structural statements represent circuit components like
logic gates, counters, and microprocessors. Behavioral level statements are programming
statements that have no direct mapping to circuit components like loops, if-then statements, and
stimulus vectors which are used to exercise a circuit.
Figure 1 shows an example of a circuit and a test bench module. A module starts with the
keyword module followed by an optional module name and an optional port list. The key word
endmodule ends a module.
2.2 Structural Design with Gate Primitives and the Delay operator
Verilog defines some basic logic gates as part of the language. In Figure 1, module
some_logic_component instantiates two gate primitives: the not gate and the and gate. The
output of the gate is the first parameter, and the inputs are the rest of the parameters. These
primitives are scaleable so you can get multiple input gates just by adding inputs into the
parameter list. For example:
By default the timing delay for the gate primitives is zero time. You can define the rising delay,
falling delay using the #(rise, fall) delay operator. And for tri-state gates you can also define the
turn-off delay (transition to high impedance state Z) by using the #(rise, fall, off) delay operator.
For example
Also each of the 3 delays can be defined to have minimum, typical, and a maximum value using
the a colon to separate the values like 8:10:12 instead of 10 in the above examples. At run time,
the Verilog simulator looks for to see if the +mindelay, +typdelay, or +maxdelay option has
been defined so that it will know which of the 3 time values to use. In VeriLogger these options
are set using the Project > Project Preferences menu. If none of the options are specified then
the typical value is used.
// min:typ:max values defined for the (rise, fall) delays
or #(8:10:12, 10:11:13) or1(c,a,b);
The delay operator has one subtle side effect: it swallows narrow input pulses. Normally, the
delay operator causes the output response of a gate to be delayed a certain amount of time.
However if the input pulse width is shorter then the overall delay of the gate then the change will
not be shown on the output.
If you have a lot of random logic, the gate primitives of the previous section are tedious to use
because all the internal wires must be declared and hooked up correctly. Sometimes it is easier to
just describe a circuit using a single Boolean equation. In Verilog, Boolean equations which have
similar timing properties as the gate primitives are defined using a continuous assignment
statement.
wire d;
and a1(d, a, b);
not n1(c, d);
assign c = !(a && b); //notice that wire d was not used here
Assignments can also be made during the declaration of a wire. In this case the assign keyword is
implicitly assumed to be there for example:
wire d;
assign d = a || b; //continuous assignment
By default the timing delay for assignment statements is zero time. You can define a propagation
delay using the #delay operator just like we did for the gate primitives. The following examples
have the exact same timing.
wire c;
assign #5 c = a && b; //delay in the continuous assignment
To demonstrate the pulse swallowing effect of the delays operator, consider the following
senario. In the above examples, if input a changed value at time 10 (and held its value for at least
5 time units), then the output c would change values at time 15. If input a had a value pulse that
was shorter then the propagation delay of the assignment then the value on a would not be passed
to the output.
The delay operator can also use the full rise, fall, and off delays and each delay can have a
minimum:typical: maximum value. The following is a valid line of code.
Appendix A defines all of the operators that can be used in an assignment statement.
Verilog supports hierarchical design by allowing modules to instantiate other modules. For
example in Figure1 module test_bench instantiates a component S1 of type
some_logic_component. The code is reprinted here for convince:
module test_bench;
...
some_logic_component S1(C, A, B); //instantiate a
some_logic_component module
...
endmodule
By default the timing inside a module is controlled by the module itself. However, modules can
be defined to have parameterized delays similar to the #(4,5) delay operator used with gate
primitives. In the module definition, use the parameter keyword to create delay variables.
Parameters can also be used to change other scalar values in the module. When the module is
instantiated then you can choose to override the delay values using the #(parameter) notation.
For example:
Modules also support a special kind of timing called specify blocks which can be used in
conjunction with SDF analyzers. Specify blocks also support continuous setup and hold
checking.
Home Tasks:
1) Implement a half adder
2) Implement a full adder
3) Implement a full adder by using 2 half adders