Verilog Práctico

Capítulo 19. Decoders, Code Converters y Encoders

25 de enero de 2023

Encoders y Decoders son ampliamente utilizados en sistemas digitales. 

Utilizamos decodificadores como selectores para habilitar uno entre varios dispositivos de E/S, para implementar multiplexores, para controlar displays de 7 segmentos, etc. 

Los codificadores se utilizan como arbitradores en buses de datos cuando se implementan como Priority Encoders en el diseño de interrupciones. 

1. Decoders

Los decodificadores son circuitos combinacionales con  un número n de entradas y 2n salidas.

Un decodificador es un circuito que recibe un código binario y cuyas salidas se activan para valores específicos de ese código, es decir, cada salida se activará sólo con un código de entrada concreto. 

Una aplicación típica puede ser utilizarlos como selectores. Si conectamos las salidas de un decoder a la entrada enable de diferentes módulos, podemos habilitar un módulo en concreto, mientras el resto permanece apagado. Por ejemplo,  seleccionar un dispositivo de memoria entre varios disponibles.

Los siguientes ejemplos ilustran lo que se conoce como One-Hot Decoders, donde sólo una de las salidas está activa cada vez. 

1.1.  Decodificador 2 x 4  (case statement)


Vamos a modelar un decodificador con 2 entradas y 4 salidas, donde en función del valor de la entrada, sólo una de las salidas está a nivel alto,

Modelar un decodificador con una declaración case es muy sencillo. Como es un circuito combinacional puro, utilizamos asignaciones blocking =. El código Verilog queda como sigue: 

Utilizaremos los pulsadores sw1 y sw2 para introducir los valores de in[0] e in[1]. La salida la mostramos en los ledes LD4 a LD7.

El archivo .pcf queda así:

1.2. Decodificador 3 → 8 con enable


A veces es muy útil encender o apagar un circuito. Vamos a añadir una señal de enable para habilitar o deshabilitar las salidas a nuestra conveniencia.

Unos ledes conectados en las entradas nos ayudan a visualizar las entradas seleccionadas.

La salida la mostramos por los ledes de la Alhambra FPGA y las entradas las implementamos con un dip switch.

Otra forma de describir el circuito es con la declaración always @ * cuando queremos que la declaración se evalúe cuando haya un cambio en cualquiera de las entradas.

Las opciones dentro de la declaración case también se pueden listar en decimal. 

La salida la mostramos en los ledes LD7 a LD0. Para las entradas utilizamos los pines D3 a D0. El archivo .pcf queda así: 

1.3. Decodificador 4 - 16 ( Code Converters)


Una aplicación de los decodificadores son los llamados Code Converters; circuitos combinacionales que convierten un código en otro, tales como BCD a 7-segmentos, binario a hexadecimal, etc…

Estos convertidores tienen un campo de aplicación muy útil: los decodificadores para displays de 7 segmentos.

Vamos a conectar un display de 7 segmentos a la Alhambra FPGA y con un dip switch de 4 entradas vamos a seleccionar el código binario que luego se mostrará en hexadecimal en el display. 

El código Verilog queda como sigue:

Archivo .pcf 

Decodificador binario a hexadecimal con display de 7 segmentos. 

el código binario 1100 se muestra como C en el display 

2. Encoders


Un encoder tiene 2n entradas y n salidas.

Un encoder funciona de forma opuesta a un decoder. Una expresión en la entrada corresponde a un código único en la salida, es decir, codifica la información en una forma más compacta.

Los encoders se utilizan para reducir el número de bits necesarios para representar una información dada. Codificar la información permite transmitir datos usando menos líneas de comunicación.

Algunas aplicaciones son: 

2.1. Binary Encoder 4 x 2 


La imagen siguiente muestra un encoder binario 4 a 2 y la tabla de la verdad correspondiente.

El código binario que obtenemos en la salida, nos dice cuál de las entradas está activa.

Con un dip switch conectado en los pines D3 a D0 seleccionamos qué entrada hacemos activa. La salida la mostraremos en los ledes de la Alhambra FPGA. 

El código Verilog queda como sigue.

Declaramos la salida out como registro, ya que dentro de un bloque always sólo se pueden hacer asignaciones a variables tipo reg. Como es un circuito combinacional utilizamos asignaciones blocking =.

De las 16 posibles combinaciones que se pueden hacer con 4 entradas, sólo nos interesan aquellas en las que sólo una entrada está activa. El resto aplicamos un default: out = 2’bxx que significa no importa o desconocido. 

Las entradas se conectan en los pines D3 a D0. La salida la mostramos con los ledes LED6 y LED7. 

2.2. Priority Encoder 2 x 4 (if-else)


En el ejemplo anterior no hemos contemplado el caso de que varias entradas estén activas a la vez. Un Priority Encoder nos dice cúal de todas las entradas activas es la que tiene mayor prioridad. Las que están por debajo en la jerarquía no importan, por eso las representamos con una x en la tabla de la verdad. Además añadimos la salida y que nos dice que una de las entradas con prioridad está activa. 

Un Priority Encoder se usa por ejemplo, cuando tenemos múltiples sensores y hay que priorizar cual transmite en caso de colisión con otro sensor; así se generan interrupciones con prioridad. 

El código Verilog queda como sigue:

Las salidas output [4:0] ld son los ledes que no se utilizan. 

Con la declaración assign ld[4:0] = 5'b00000; los mantenemos apagados, ya que a veces los ledes de la Alhambra FPGA se quedan encendidos y falsean el resultado. 

La salida y es la operación OR de in es decir, de todos los bits del vector in [3:0] esto se hace con la operación reducción OR.

Como estamos describiendo un encoder con prioridad, utilizamos declaraciones if-else

El esquema de conexión es el mismo que en el ejemplo anterior. Conectamos un dip switch en los pines  D3 a D0. La salida la mostramos con los ledes LED6 y LED7, mientras que la salida y la mostramos en el LED0. 

2.3. Priority Encoder 2 x 4 (casex)


Otra forma de modelar un Priority Encoder es mediante declaraciones casex.

A veces nos encontramos circuitos -como el que nos ocupa hoy- en cuya tabla de la verdad hay variables que no importa si son ceros o unos, es esos casos utilizamos la letra x, que representa desconocido o no importa si vale  0 o 1. 

En verilog, una señal puede tener cuatro posibles valores: 1, 0, x, z, donde x significa desconocido y z alta impedancia. Una declaración casex interpreta los valores x, z como no importa, es decir, ignora su valor. 

El esquema de conexión es el mismo que en los dos  ejemplos anteriores. El archivo .pcf no cambia. 

Descargas

Puedes descargar el código Verilog de los ejemplos anteriores aquí abajo.