verilog-puertas-logicas-and-or-not-xor

Verilog Logic Gates: AND, OR, NOT, and XOR

  • 4 min

A logic gate is a circuit that computes a Boolean function from one or more binary inputs.

Any modern processor, from the one in your washing machine to the latest Intel i9, is composed of billions of the same basic building blocks: logic gates.

In classic electronics, you would have to buy chips from the 7400 series (like the 7408 for AND or the 7432 for OR) and fill a breadboard with wires. In an FPGA, we can describe these functions with a single line of code, always within the available resources.

Today, we’ll see how to translate the classic gates into Verilog.

Bitwise Operators

In Verilog, just like in C, Java, or Python, we use specific symbols to perform logical operations.

It is crucial to understand that in Verilog these operators are Bitwise. This means that if we operate on multi-bit buses, the operation is performed independently for each position (bit 0 with bit 0, bit 1 with bit 1, etc.).

Here is the table of the main operators:

Logic GateVerilog SymbolDescription
NOT (Inverter)~Inverts the value (0 → 1, 1 → 0).
AND&1 only if all inputs are 1.
OR|1 if any input is 1.
XOR (Exclusive OR)^1 if inputs are different.
NAND~&Opposite of AND.
NOR~|Opposite of OR.

Note for programmers:

Notice we use & and | (single), not && and || (double).

The double ones are logical Boolean operators that return a single bit (true/false). In hardware, we almost always want to operate on the actual bits, so we use the single ones.

Basic Implementation

Let’s create a module that has two inputs (a, b) and outputs the result of these operations through different ports. Since these are direct relationships, we will use continuous assignment (assign).

module my_gates (
    input wire a,
    input wire b,
    output wire y_not,
    output wire y_and,
    output wire y_or,
    output wire y_xor
);

    // 1. NOT Gate (Inverter)
    // Applies only to 'a'. If a=0 -> y=1.
    assign y_not = ~a;

    // 2. AND Gate
    // Output is high only if A AND B are high.
    assign y_and = a & b;

    // 3. OR Gate
    // Output is high if A or B (or both) are high.
    assign y_or = a | b;

    // 4. XOR Gate (Exclusive OR)
    // Output is high if A is different from B.
    // It is fundamental for binary addition.
    assign y_xor = a ^ b;

endmodule
Copied!

Operations with Buses

This is where the FPGA starts to show one of its best advantages. Suppose we want to perform an AND operation between two 4-bit buses.

In discrete electronics, we would need 4 physical AND gates (a whole 7408 chip). In Verilog, the syntax is identical.

module quadruple_and (
    input wire [3:0] bus_a, // Example: 1010
    input wire [3:0] bus_b, // Example: 1100
    output wire [3:0] result
);

    // Verilog expands the operation automatically
    assign result = bus_a & bus_b;

    /* Explanation of what happens bit by bit:
       
          1 0 1 0  (bus_a)
       &  1 1 0 0  (bus_b)
       -----------
          1 0 0 0  (result)
          
       bit 3: 1 & 1 = 1
       bit 2: 0 & 1 = 0
       bit 1: 1 & 0 = 0
       bit 0: 0 & 0 = 0
    */

endmodule
Copied!

The XOR Gate

I want to give a special mention to the XOR gate (^). Often, when we start programming, we only think about AND and OR.

However, in digital electronics, the XOR is especially useful.

  1. Difference Detector: It tells us if two bits are different.
  2. Controlled Inverter: If you do A ^ 0, you get A. If you do A ^ 1, you get ~A (A inverted).
  3. Adder: The sum of 1 + 1 in binary is 0 (and carry 1). That’s exactly what an XOR does for the result bit!

Combining Gates

We can combine operators in a single line to create more complex logic. The ~ operator has higher precedence than &, and & has higher precedence than |. When in doubt, use parentheses.

// Example: A complex logic function
// Y = (A AND B) OR (NOT C)
assign output = (a & b) | (~c);
Copied!