The second last logic gate in this Verilog course is the XOR logic gate. Let’s code the gate using the three modeling types: Gate Level, Dataflow, and Behavioral modeling.

Any digital circuit is implemented on the gate level in terms of concrete logic gates and gate interconnections in gate-level modeling. For this modeling, the designer should know the gate-level diagram of the design.

In Dataflow level modeling, a module is implemented by determining how data moves between registers.

Whereas, the high-level implementation of the application is implemented in behavioral modeling with little regard for the actual hardware itself.

These different types of modeling do not affect the final design of the hardware we receive. We get the same results in each case, but levels of abstraction and methodology vary. Let’s first start with modeling the XOR gate using Gate Level modeling.

**Gate Level modeling**

Circuit construction utilizing base logic gates is regarded as gate-level modeling. Gate primitives can be used to create complex level logic including multiplexers, encoders since gates are the basic components of any logic diagram. But as the design grows substantially, working on this level of abstraction becomes harder.

The primitives specified in Verilog have been designed with the user requirements in mind rendering designing bigger blocks simple. Analyzing gate-level often takes care of gate delays that are not feasible at a higher abstraction level. However, most of the time, we don’t acknowledge the delay induced by the gates in the circuits.

Designers can either manually or automatically build lower-level models from the higher-level models. The process of automatically generating a gate-level model from either a dataflow or a behavioral model is called *Logic Synthesis*.

**Logic Circuit of the ****XOR gate**

XOR gate is not a basic gate on its own, as it can be constructed using other basic logic gates. Regardless of that, its output boolean function is important to be considered.

The output of the XOR gate is high if the inputs are different from each other, else in every case, the output is low. It means that if both inputs are low or both are high, then the output will be low, else in other cases, the output will be high.

Here’s the logical representation of the XOR gate. It has a graphic symbol similar to that of the OR gate, except for the additional curved line on the input side.

**Verilog code for XOR gate using gate-level modeling**

We begin the hardware description for the XOR gate as follows:

module XOR_2_gate_level(output Y, input A, B);

In Verilog HDL, we define the module using the keyword ` module`

, a basic building block. `XOR_2_gate_level`

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:

xor(Y, A, B); endmodule

Verilog has this feature to describe the gate-level circuit. Here `XOR`

is the operation carried out on A, B, to obtain output Y. ` endmodule`

terminates the module.

Here is the complete code for your convenience:

module XOR_2_gate_level(output Y, input A, B); xor (Y, A, B); endmodule

**Data flow modeling**

Dataflow modeling allows a more detailed description as opposed to gate-level modeling. Dataflow modeling defines the circuits not by their gate structure, but by their function. The module is implemented by specifying the way the data flows between registers. That’s a nifty approach because gate-level modeling for large circuits becomes very complicated.

The dataflow simulation is, therefore, a very effective way to implement the architecture. This type of architecture generally requires “continuous assignment statements.” The continuous assignments are created using the keyword `assign`

. You’ll see in a little while how these are used.

**Equation of the ****XOR gate**

The boolean equation of an XOR gate is Y = (A **⊕** B).

**Verilog code for XOR gate using dataflow modeling**

We would again start by declaring the module. The way it goes is as follows.

module XOR_2_data_flow (output Y, input A, B);

` module`

is a keyword, `XOR_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 `^`

logical operator performs the XOR operation on the inputs we provide. `endmodule`

is used to terminate the module.

You may look over the entire description here.

module XOR_2_data_flow (output Y, input A, B); assign Y = A ^ B; endmodule

**Behavioral Modeling**

Behavioral modeling is Verilog HDL’s highest level of abstraction, while the other modeling strategies (such as gate level, data flow level) are comparatively comprehensive. This is a very powerful method of abstraction.

Verilog’s behavioral models include procedural statements that control the simulation and manipulate data type variables. This abstraction level simulates the circuit behavior without details. In behavioral modeling, we are focussed on just the behavior of the design. Most of the behavioral modeling is done using two important constructs: initial and always. All the other behavioral statements appear only inside these two structured procedure constructs.

Let’s have a look at the truth table.

**Truth Table for XOR gate**

A |
B |
Y(A XOR B) |

0 | 0 | 0 |

0 | 1 | 1 |

1 | 0 | 1 |

1 | 1 | 0 |

**Equation from the truth table**

Simply by minimization, (or you may arrive using k-maps), we can state that:

Y = A’B + AB’ or say Y = A XOR B.

**Verilog code for XOR gate using behavioral modeling**

Again, we begin by declaring module, setting up identifier as ` XOR_2_behavioral`

, and the port list.

module XOR_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.

All 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 actually a hardware register. These types of data objects hold the value from one procedural assignment statement to the next, and that means it holds its value over simulation data cycles. Then, we write,

always @ (A or B) begin.....end

An `always`

block is a behavioral block which contains a list of expressions which are evaluated sequentially. This list is 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. In Verilog, `begin`

begins and `end`

concludes any block which contains more than one statement in itself.

The always statement `always @ ( A, B)`

could be written as `always @( *)`

. The @(*) construct automatically creates a sensitivity list for all the signals in the always block.

The description in an always block can be very abstract. Therefore we have,

always @ (A or B) begin if (A == 1'b0 & B == 1'b0) begin Y = 1'b0; end if (A == 1'b1 & B == 1'b1) begin Y = 1'b0; end else Y = 1'b1; end

` if (A == 1'b0 & B == 1'b0)`

states that if both A and B are 0, ` Y = 1'b0;`

then Y has to be 0. == is the symbol for testing logical equality, 1’b0 conveys that the number is of 1 bit in the binary number system, and its value is 0. Likewise & is the symbol for bitwise and operation.

Here is the full code:

module XOR_2_behavioral (output reg Y, input A, B); always @ (A or B) begin if (A == 1'b0 & B == 1'b0) begin Y = 1'b0; end if (A == 1'b1 & B == 1'b1) begin Y = 1'b0; end else Y = 1'b1; end endmodule

**RTL schematic of XOR gate**

**Testbench of the XOR gate using Verilog**

The file to be included and the name of the module changes, but the basic structure of the testbench using Verilog remains the same in all the three modeling styles.

`include "XOR_2_behavioral.v" module XOR_2_behavioral_tb; reg A, B; wire Y; XOR_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

**Simulation Waveform**

By observing the waveforms, we can derive that whenever both of the inputs A and B are low or both of the inputs are high, then the output is low, else in every other condition, the output is high.