Next up, we will learn the NOR logic gate using three modeling styles of Verilog namely Gate Level, Dataflow, and Behavioral modeling. These various modeling styles do not affect the final hardware design that we obtain.
In the gate level modeling, the module is implemented in terms of concrete logic gates and interconnections between the gates. The designer should know the gate-level diagram of the design.
In Dataflow level modeling, a module is implemented by specifying how data flows between registers whereas, in behavioral modeling, the module’s high-level algorithm is implemented with little concern for the actual hardware. In every model, we get the same results, but abstraction levels and describing approaches vary. Let’s start with Gate Level modeling for the NOR gate.
Gate Level modeling
Designing circuits using basic logic gates is known as gate-level modeling. As gates are the basic components of any logic diagram, gate primitives can be used to construct complex level logic like multiplexers, encoders.
The primitives defined in Verilog have been set keeping the user requirements in mind making it easy to design bigger blocks. Gate level analysis also takes care of gate delays which is not possible in a higher level of abstraction. Most of the time we do not consider the delay induced in the circuits because of the gates.
Designers can create lower-level models from the higher-level models either manually or automatically. The process of automatically generating a gate-level model from either a dataflow or a behavioral model is called Logic Synthesis. Verilog supports describing circuits using basic logic gates as predefined primitives. The primitives are instantiated like modules except that they are predefined in Verilog’s syntax and do not need a module definition.
Logic Circuit of the NOR gate
The output of the NOR gate is high if both of the inputs are low else in every case the output is low. Here’s the logical representation of the NOR gate. The NOR Gate is the reverse or “Complementary” form of the inclusive OR gate.
Verilog code for NOR gate using gate-level modeling
We begin the hardware description for the NOR gate as follows:
module NOR_2(output Y, input A, B);
We declare the module using the keyword
module, a basic building block in Verilog HDL.
NOR_2 is the identifier here. The list in parenthesis contains input and output ports. This is called the port list. As Verilog has primitives, we can then write:
nor(Y, A, B); endmodule
Verilog has this functionality to describe the circuit at the gate level. Here
nor is the operation performed on A, B, to get output Y.
endmodule terminates the module.
Here is the complete code for your convenience:
module NOR_2_gate_level(output Y, input A, B); nor(Y, A, B); endmodule
Data flow modeling
Compared to gate-level modeling, dataflow modeling enables description which is more abstract. Dataflow modeling describes the circuits by their function instead of their gate structure. The module is implemented by specifying the way the data flows between registers. That’s pretty useful since gate-level modeling becomes very complicated for large circuits.
Hence dataflow modeling is a very important way of implementing the design. This style of design requires continuous assignment statements. The continuous assignments are created using the keyword
Equation of the NOR gate
The boolean equation of a NOR gate is Y = (A + B)’.
Verilog code for NOR gate using data-flow modeling
We would again start by declaring the module. The way it is done is:
module NOR_2_data_flow (output Y, input A, B);
module is a keyword,
NOR_2_data_flow is the identifier,
(output Y, input A, B) is the port list. Then we have semicolon to end the statement.
Next is the assignment statement in data flow modeling.
assign Y = ~(A | B); endmodule
The | operator performs the OR operation on the inputs we provide. Then
~ symbol compliments that value to spit out Y. If you check out the table of operators in Verilog that we have seen earlier you’ll notice that we don’t have a special operator for the NOR operation. Hence, we just use OR and NOT in tandem.
endmodule is used to terminate the module.
You may look over the entire description here.
module NOR_2_data_flow (output Y, input A, B); assign Y = ~(A | B); endmodule
Behavioral modeling is the highest level of abstraction in the Verilog HDL, whereas the other modeling techniques (like gate level, data flow level) are comparatively detailed. This level of modeling is as abstract as C language. This is a very strong abstraction technique.
Behavioral models in Verilog contain procedural statements, which control the simulation and manipulate variables of the data types. This level of abstraction simulates the behavior of the circuits without specifying the details.
We are not concerned about the fact that whether the circuit is implemented using particular logic gates. We are focussed on just the behavior of the design.
Most of the behavioral modeling is done using two important constructs:
always. All the other behavioral statements appear only inside these two structured procedure constructs. First of all, let’s have a look at the truth table.
Truth Table for NOR gate
|Y(A nor B)
Equation from the truth table
Simply by minimization, (or you may arrive by k-maps), we can state that:
Y = ~(A + B) or say Y = A nor B.
Verilog code for NOR gate using behavioral modeling
Declare the module, set up the identifier as
NOR_2_behavioral, and the port list.
module NOR_2_behavioral (output reg Y, input A, B);
In this case, 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. It is a vital point to note that in Verilog a reg is just a variable, not hardware register! All assignments in an always block must be assigned to a reg variable – the reg variable may or may not actually represent a hardware register.
always block assigns a value to the reg variable for all possible executions then the reg variable is not actually a hardware register. These types of data objects hold the value from one procedural assignment statement to the next. That means it holds its value over simulation data cycles. Then, we write:
always @ (A or B) begin ..... end
always block is a behavioral block which contains a list of expressions which are evaluated sequentially. This list is famously known as 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 controls when the statements in the always block are to be evaluated.
@ is a part of the syntax, used before the sensitivity list.
begin embarks and
end concludes any block which contains more than one statement in itself.
Note that the always statement
always @ ( A, B) could be written as always
@(*) construct creates a sensitivity list for all the signals in the always block.
The description in an always block can be very abstract similar to C. Therefore we have,
always @ (A or B) begin if (A == 1'b0 & B == 1'b0) begin Y = 1'b1; end else Y = 1'b0; end
The condition for the NOR gate is that if both the inputs are low, then the output is high, else in every other condition that has to be low.
if (A == 1'b0 & B == 1'b0) states that if both A and B are 0,
Y = 1'b1; then Y has to be 1, else 0.
== is the symbol for testing logical equality,
1'b0 conveys that the number is of 1 bit in binary number system and its value is 0. Likewise
& is the symbol for bitwise and operation.
Here is the full code:
module NOR_2_behavioral (output reg Y, input A, B); always @ (A or B) begin if (A == 1'b0 & B == 1'b0) begin Y = 1'b1; end else Y = 1'b0; end endmodule
RTL schematic of NOR gate
Testbench of the NOR 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 "NOR_2_behavioral.v" module NOR_2_behavioral_tb; reg A, B; wire Y; NOR_2_behavioral Instance0 (Y, 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 | A = %d| B = %d| Y = %d", $time, A, B, Y); $dumpfile("dump.vcd"); $dumpvars(); end endmodule
By observing the waveforms, we can derive that whenever both of the inputs A and B are low then the output is high, else in every other condition the output is low.