Verilog Práctico

Capítulo 2.1. Puertas Lógicas.

publicado el 2 de enero de 2021actualizado el 20 de noviembre de 2021

Uno de los dispositivos básicos cuando hablamos de circuitos digitales son las puertas lógicas. En este capítulo veremos cómo programar puertas lógicas en la Alhambra.


1. Puerta AND


Tabla de la verdad.

Código.


La forma de implementar un dispositivo en Verilog empieza con module nombre (E/S); y entre paréntesis definimos las entradas y salidas del dispositivo separadas por comas.


module AND (input in1, in2, output out); 


Con assign indicamos que el valor de la salida out es la operación & (AND) de las entradas in1, in2.


assign out = in1 & in2; 


Lo ponemos todo junto y este es el código de una puerta AND en Verilog:


// AND gate

module AND (input in1, in2, output out);


// asignar la salida a las entradas 1 y 2

// mediante el operador &


  assign out = in1 & in2;


endmodule




El archivo pcf es el siguiente, donde 10 y 11 son los switches SW1 y SW2 y la salida 95 corresponde con el LED0. El archivo pcf  es el mismo para todas las puertas lógicas explicadas en este capítulo, ya que todas tienen dos entradas y una salida.


set_io in1 10

set_io in2 11

set_io out 95 


Lo verificamos, construimos y lo subimos a la Alhambra. Con los switches SW1 y SW2 simulamos las entradas, en el LED0 vemos la salida.

2. Puerta NAND


Tabla de la verdad.

Código


Para construir una puerta NAND solo hay que negar el resultado de (in1 & in2) colocando el operador ~ delante del paréntesis.


// NAND gate

module NAND (input in1, in2, output out);


// asignar la salida a las entradas 1 y 2

// mediante el operador &


  assign out = ~(in1 & in2);


endmodule

3. Puerta OR


Tabla de la verdad

Código


// OR gate

module OR (input in1, in2, output out);


// asignar la salida a las entradas 1 y 2

// mediante el operador |


  assign out = in1 | in2;


endmodule

4. Puerta NOR


Tabla de la verdad

Código


// NOR gate

module NOR (input in1, in2, output out);


// asignar la salida a las entradas 1 y 2

// mediante el operador |


  assign out = ~(in1 | in2);


endmodule

5. Puerta XOR


Tabla de la verdad

Código


// XOR gate

module XOR (input in1, in2, output out);


// asignar la salida a las entradas 1 y 2

// mediante el operador ^


  assign out = in1 ^ in2;


endmodule

6. Puerta XNOR


Tabla de la verdad

Código


// XNOR gate

module XNOR (input in1, in2, output out);


// asignar la salida a las entradas 1 y 2

// mediante el operador ^


  assign out = ~(in1 ^ in2);


endmodule

Como véis es muy fácil hacer una puerta lógica en Verilog y sintetizarla en la Alhambra.


A partir de aquí se pueden diseñar puertas lógicas de N entradas simplemente declarando más inputs dentro de module (input in1, in2, in3, output out) y asignando la salida a dichas entradas mediante el operador que corresponda, por ejemplo: assign out = ~(in1 & in2 & in3) para una puerta NAND de tres entradas. 

Actualización


10 de enero de 2021

Primitivas


Una forma de optimizar circuitos es mediante el uso de primitivas; están incorporadas en Verilog y se utilizan para describir circuitos a nivel de puerta.


Todas las primitivas tienen al menos dos parámetros, el primero es la salida, los siguientes son entradas.

La primitiva and (o, in1, in2); crea una puerta AND de salida o y entradas in1 e in2.


A continuación ejemplos de cómo declarar puertas lógicas mediante primitivas.

module gate (input in1, in2, output o);



// puertas lógicas básicas

and (o, in1, in2);

nand (o, in1, in2);

or (o, in1, in2);

nor (o, in1, in2);

xor (o, in1, in2);

xnor (o, in1, in2);

not (o, in1);


// si lo deseamos, se puede poner nombre

nor N1 (o, in1, in2);

xor XO5 (o, in1, in2);



// puertas lógicas de más de dos entradas

or (o, in1, in2, in3);

nand (o, A, B, C, D);


endmodule

Operaciones con buses


Cómo declarar un bus de datos.


Los buses de datos se declaran entre corchetes, por ejemplo:


[3:0] BUS1 // bus de 4 bits, formato little-endian, bit más significativo a la izquierda


[0:23] BUS2 // bus de 24 bits, formato big-endian, bit más significativo a la derecha


Se pueden hacer operaciones lógicas con buses. La forma de describir el circuito es la siguiente.


module and_bus ( input [3:0] BUS1, BUS2, output [3:0] OUT);


assign OUT = BUS1 & BUS2;


endmodule


Este circuito es equivalente a hacer la operación AND entre cada uno de los bits de mismo peso de cada bus.

Operación de Reducción


Equivale a hacer una operación lógica a todos los bits de un bus.


module or (input [3:0] BUS, output O);


assign O = &BUS;


endmodule


El circuito equivalente es:

Descargas


Descarga el código Verilog de las puertas lógicas aquí abajo: