In this post, we will learn to describe NOT logic gate using three modeling styles in Verilog, namely Gate Level, Dataflow, and Behavioral modeling.
Gate level modeling relates to describing the circuit in terms of basic logic gates. The gates are wired according to the circuit. Gate level modeling is easier to understand at first glance as it relates directly to the circuit. The dataflow design comprises describing the circuit in terms of movement of data, and it is another lower level of abstraction. The third type of modeling is the behavioral modeling, where we describe the design in terms of high-level abstraction, the core behavior of the circuit.
Gate Level modeling
Hardware design at this level is intuitive for a user with a basic knowledge of digital logic design because it is possible to see a one-to-one correspondence between the logic circuit diagram and the Verilog description. A logic circuit can be designed by the use of logic gates. Verilog supports basic logic gates as predefined primitives. These primitives are instantiated like modules except that they are predefined in Verilog and do not need a module definition. All logic circuits can be designed by using basic gates.
Logic Circuit of the NOT gate
Verilog code for NOT gate using gate-level modeling
We begin the hardware description for the NOT gate as follows:
module NOT_gate_level(output Y, input A);
In Verilog HDL, we define the module using
module, a basic building block.
NOT_gate_level is the identifier here. The list in parenthesis contains input and output ports, called the port list. As Verilog has primitives, we can then write:
not(Y, A); endmodule
Verilog has this feature to describe the gate-level circuit. Here,
not is the operation carried out on A to obtain output Y.
endmodule terminates the module.
Here is the complete code for your convenience:
module NOT_gate_level(output Y, input A); not (Y, A); endmodule
Data flow level
For small circuits, the gate-level modeling approach works because the number of gates is limited, and the designer can instantiate and connect every gate individually. Also, gate-level modeling is very intuitive to the designer.
However, the designer can not design when the number of gates is large. Hence we have dataflow modeling, where we implement the function at a level of abstraction higher than the gate level.
Verilog allows us to design the circuit in terms of the data flow between registers and the way data is processed rather than an instantiation of a gate. The approach of data flow allows us to concentrate on optimizing the circuit in terms of dataflow.
Equation of the NOT gate
The boolean equation of a NOT gate is Y = A’.
Verilog code for NOT gate using dataflow modeling
We would again start by declaring the module. The way it goes is as follows-
module NOT_data_flow (output Y, input A);
module is a keyword,
NOT_data_flow is the identifier,
(output Y, input A) is the port list. Then we have semicolon to end the statement.
Next is the assignment statement in data flow modeling.
assign Y = ~A; endmodule
~ operator performs the NOT operation on the input we provide.
endmodule is used to terminate the module.
You may look over the entire description here.
module NOT_data_flow (output Y, input A); assign Y = ~A; endmodule
As the complexity of any digital circuit increases, it becomes crucial to make trade-offs of various architectures and algorithms. A chip designer needs to focus on optimum architecture and algorithms to implement. Hence, we can use a higher algorithmic level where we do not think in terms of the logic gates or data flow. Verilog provides the ability to describe design functionality in an algorithm manner, or we can say in terms of the behavior of the circuit. This behavior of the circuit can be understanding using its truth table.
Truth Table for NOT gate
Equation from the truth table
Simply by minimization, (or you may arrive by k-maps), we can state that:
Y = A’ or say Y = A Complement.
Verilog code for NOT gate using behavioral modeling
We begin by declaring module, setting up identifier as
NOT_2_behavioral, and the port list.
module NOT_behavioral (output reg Y, input A);
The port list includes the output and input ports. When our level of abstraction is behavioral level, then we use reg datatype in the output ports. In Verilog, a
reg is just a variable, not a hardware register. All the assignments in an always block must be assigned to a reg variable. If the always block assigns a value to the reg variable for all possible executions, then the reg variable is not a hardware register. These types of data objects hold the value from one procedural assignment statement to the next. Then, we write,
always @ (A) begin.....end
An always block is a behavioral block which contains a list of expressions which are evaluated sequentially. This list is called the sensitivity list or trigger list. Here,
(A, B) is the sensitivity list or the trigger list. It includes all signals used by the always block. It changes when the statements in the always block are to be evaluated. @ is a part of the syntax, used before the sensitivity list. In Verilog,
begin embarks and
end concludes any block which contains more than one statement in itself.
The description in an always block can be very abstract similar to C. Therefore we have,
always @ (A) begin if (A == 1'b0) begin Y = 1'b1; end else if (A == 1'b1) begin Y = 1'b0; end
The condition for the NOT gate is that if the input is low, the output is high and vice-versa.
(A == 1'b0) states that if A is 0,
Y = 1'b1; then Y has to be 1.
== is the symbol for testing logical equality, 1’b1 conveys that the number is of 1 bit in the binary number system, and its value is 1. Here is the full code:
module NOT_behavioral (output reg Y, input A); always @ (A) begin if (A == 1'b0 ) begin Y = 1'b1; end else if (A == 1'b1) begin Y = 1'b0; end endmodule
RTL schematic of NOT gate
Testbench of the NOT gate using Verilog
The file to be included and the name of the module changes, but the basic structure of the testbench remains the same in all the three modeling styles.
`include "NOT_behavioral.v" module NOT_behavioral_tb; reg A;wire Y; NOT_behavioral Instance0 (Y, A); initial begin A = 0; #1 A = 1; #1 A = 0; endinitial begin $monitor ("%t | A = %d| Y = %d", $time, A, Y); $dumpfile("dump.vcd"); $dumpvars(); end endmodule
By observing the waveforms, we can derive that whenever the input A is low, then the output is high, else the output is low.