Designing circuits using basic logic gates is known as gate-level modeling. A digital circuit is implemented using logic gates and interconnections between these gates. The primitives (The most basic commands of a language) defined in Verilog have been set keeping the user requirements in mind making it easy to design bigger blocks. For example, for implementing AND gate or logic, the primitive is simply and(Yd, A, B)
.
Gate level modeling also takes care of gate delays, which is not possible in a higher level of abstraction like behavioral modeling.
However, the designer should know the gate-level diagram of the circuit. In general, gate-level modeling is used for implementing lowest level modules in a design like full-adder, multiplexers, and other digital circuits.
In this post, we will take an in-depth look at the theory behind gate-level modeling in Verilog. This is the first modeling style that we will be studying in this Verilog course.
First, we view the logic values and ‘strengths.’ Then we talk about gate primitives. We will also have a look at the gate delays and, finally, see the subtle difference between gate-level modeling and switch-level modeling.
Contents
Logic values
A logic value is a state in which a data-type or a signal line in a chip can be present. In Verilog, there are four logic values, which means that a signal line can take one of the four values shown in the table below:
Logic Value | Description |
0 | low |
1 | high |
X | Unknown logic |
Z | High impedance state |
These values are either assigned in the hardware description or the output of a block.
Strengths
Usually, in chip design, multiple signal paths are combined into one to save space. In this scenario, the logic values need to be assigned a higher value to facilitate this. Thus we have the strength values. These strength values assign a relative value to logic values. Strengths are used to resolve which value should appear on a net or gate output. The types of strengths are mentioned below:
supply, strong, pull, weak, highz strengths, large, medium, and small strengths.
Their value orders their strengths. The supply strength is the strongest, and the highz strength is the weakest strength level. Strength values can be displayed by system tasks ($display, $monitor – by using the %v characters).
Strength Level | Signal Strength Name | Specification |
0 | High Impedance | highz0 highz1 |
1 (Weakest) | Small Capacitance | small |
2 | Medium Capacitance | medium |
3 | Weak Drive | weak0 weak1 |
4 | Large Capacitance | large |
5 | Pull Drive | pull0 pull1 |
6 | Strong Pull | strong0 strong1 |
7 (Strongest) | Supply drive | supply0 supply1 |
If two or more drivers drive a signal, then it will have the value of the strongest driver.
Gate primitives
Gate primitives are predefined modules in Verilog. There are two classes of gate primitives:
Single input gate primitives
Single input gate primitives have a single input and one or more outputs. The gate primitives notif1, bufif1, notif0, and bufif0 also have a control signal. The gates propagate only if the control signal is asserted, else the output is high impedance state (z).
not, buf gates
These gates have only one scalar input but may have multiple outputs.
buf
stands for a buffer that transfers the input value to the output without any change.
not
stands for an inverter that inverts the input signal. So a 0 at its input will produce a 1 and vice versa. Let’s view the implementation.
module buf_not_gates (input a, b, output c, d); buf (c, a, b); // c is the output, a and b are inputs not (d, a, b); // d is the output, a and b are inputs endmodule
module buf_not_gates_tb; reg a, b; wire c, d; buf_not_gates Instance0 (a, b, c,d); initial begin a = 0; b = 0; #1 a = 0; b = 1; #1 a = 1; b = 0; #1 a = 1; b = 1; end initial begin $monitor ("T=%t| a=%b |b=%b| c(buf)=%b |d(not)=%b", $time, a, b, c, d); end endmodule
bufif/notif gates
bufif
and notif
primitives are buffers and inverters, respectively, with an added control signal to enable the output. The gates have a valid output only if the control signal is enabled else the output will be in high impedance state.
These gates are available in two flavors.
One with the normal polarity of control indicated by a 1 like bufif1
and notif1
and second with the inverted polarity of control indicated by a 0 like bufif0
and notif0
.
module bufif_notif_gates (output c, d, input a, b); bufif (c, a, b); // c is the output, a and b are inputs notif (d, a, b); // d is the output, a and b are inputs endmodule
module bufif_notif_gates_tb; reg a, b; wire c, d; bufif_notif_gates Instance0 (c, d, a, b); initial begin a = 0; b = 0; #1 a = 0; b = 1; #1 a = 1; b = 0; #1 a = 1; b = 1; end initial begin $monitor ("T=%t| a=%b |b=%b| c(bufif)=%b |d(notif)=%b", $time, a, b, c, d); end endmodule
Multiple input gate primitives
Multiple input gate primitives include AND, OR, NOR, XOR, and XNOR. They may have multiple inputs and a single output.
AND/OR/XOR gates
Both primitives we introduce here, an AND, OR, and an XOR gate, need multiple scalar inputs and produce a single scalar output. The first terminal in the argument list to these primitives is the output that is changed as any of the inputs shift. Here is the implementation to get a clear picture of the behavior of inputs and outputs.
module and_or_xor_gates (output c, d, e, input a, b); and (c, a, b); // c is the output, a and b are inputs or (d, a, b); // d is the output, a and b are inputs xor (e, a, b); // e is the output, a and b are inputs endmodule module and_or_xor_gates_tb; reg a, b; wire c, d, e; and_or_xor_gates Instance0 (c, d, e, a, b); initial begin a = 0; b = 0; #1 a = 0; b = 1; #1 a = 1; b = 0; #1 a = 1; b = 1; end initial begin $monitor ("T=%t |a=%b |b=%b |c(and)=%b |d(or)=%b |e(xor)=%b", $time, a, b, c, d, e); end endmodule
NAND/NOR/XNOR gates
The inverse of all the above gates are nand
, nor
and xnor
. The same design from above is reused only that the primitives are interchanged with their inverse versions.
module nand_nor_xnor_gates (output c, d, e, input a, b); nand (c, a, b); // c is the output, a and b are inputs nor (d, a, b); // d is the output, a and b are inputs xnor (e, a, b); // e is the output, a and b are inputs endmodule module nand_nor_xnor_gates_tb; reg a, b; wire c, d, e; nand_nor_xnor_gates Instance0 (c, d, e, a, b); initial begin a = 0; b = 0; #1 a = 0; b = 1; #1 a = 1; b = 0; #1 a = 1; b = 1; end initial begin $monitor ("T=%t |a=%b |b=%b |c(nand)=%b |d(nor)=%b |e(xnor)=%b", $time, a, b, c, d, e); end endmodule
All these gates may also have more than two inputs.
module all_gates (output x1, y1, z1, x2, y2, z2 , input a, b, c, d); and (x1, a, b, c, d); // x1 is the output, a, b, c, d are inputs or (y1, a, b, c, d); // y1 is the output, a, b, c, d are inputs xor (z1, a, b, c, d); // z1 is the output, a, b, c, d are inputs nand (x2, a, b, c, d); // x2 is the output, a, b, c, d are inputs nor (y2, a, b, c, d); // y2 is the output, a, b, c, d are inputs xnor (z2, a, b, c, d); // z2 is the output, a, b, c, d are inputs endmodule
Gate Delays
In Verilog, the gate delays may be defined by a designer in a primitive instance. This allows the engineer to get the logic circuit to function in real-time.
Rise delay
It is equal to the time taken by a gate output transition to 1, from another value 0, x, or z.
Fall delay
It is equal to the time taken by a gate output transition to 0, from another value 1, x, or z.
Turn off delay
It is equal to the time taken by a gate output transition to a high impedance state, from another value 1, x, or z.
Syntax
primitive_gate #(rise delay, fall delay, turn-off delay) gate_instatiation (outputs, inputs);
Some syntax rules to be kept in mind are:
- If all the three values are specified then, they are considered as rise, fall, and turn-off delays.
- If two values are specified then, they are considered as rise and fall delays.
- If only one delay is specified then, it is used for all delays.
Lets us see some examples which can be used in Verilog:
and #(2) and_gate_2 (out, in0, in1); // all delay values are 2-time units nand #(3,4,5) nand_gate_2 (out, in0, in1); // rise delay = 3, fall delay = 4, and turn-off delay = 5. or #(3,4) or_gate_2 (out, in0, in1); // rise delay = 3, fall delay = 4, and turn-off delay = min(3,4) = 3.
Verilog empowers us to control the delays more extensively in the form of min: typ: max values for each delay. Only one of the min/typ/max values can be used in the entire simulation run. It is specified at the start of the simulation and depends on the simulator used. To distinguish precisely, analyze the following example:
nand #(3:4:5,4:5:6,5:6:7) nand_gate_2 (out, in0, in1); // rise delay: min=3, typ=4, max=5, fall delay: min=4, typ=5, max=6, turn-off delay: min=5, typ=6, max=7.
Here, the typical value is the default value. In the above example, if the designer chooses min values, then rise delay = 3, fall delay = 4, turn-off delay = 5.
This helps the designer to have a much better real-time experience of design simulation, as in real-time logic circuits, the delays are not constant.
Difference between gate-level modeling and switch level modeling
Gate Level |
Switch Level |
The module is implemented in terms of logic gates and interconnections between these gates. The designer should know the gate-level diagram of the design. The design is specified as wiring between logic gates. Gate level is typically not used as it requires working out the interconnects, and it is not practical for large examples. | This is the lowest level of abstraction. The design is described in terms of switching (modeling a transistor). The designer requires knowledge of transistors, like MOSFET. It is not that useful in general logic design as compared to behavioral modeling. |