Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial Internet of Things >> Incrustado

Descripción de circuitos combinacionales en Verilog

06 de enero de 2019 por el Dr. Steve Arar

Este artículo presenta las técnicas para describir circuitos combinacionales en Verilog al examinar cómo usar el operador condicional para describir tablas de verdad combinacionales.

Este artículo presenta las técnicas para describir circuitos combinacionales en Verilog examinando cómo usar el operador condicional para describir tablas de verdad combinacionales. También muestra cómo utilizar el bloque "siempre" de Verilog para describir circuitos combinacionales; un bloque "siempre" puede proporcionarnos una solución aún más fácil para describir un circuito digital.

En un artículo anterior, discutimos el uso de la palabra clave "asignar" de Verilog para realizar una asignación continua. Estas asignaciones están siempre activas y se pueden utilizar para adquirir una descripción a nivel de puerta de los circuitos digitales. Por ejemplo, en el siguiente código, que describe una puerta AND, el lado derecho se evalúa continuamente y el resultado se coloca en la red out1:

  asignar out1 =a &b;  

Verilog tiene un operador condicional (? :) que nos permite verificar una condición antes de realizar tales asignaciones. La sintaxis se proporciona a continuación:

  asignar [nombre_señal] =[expresión_condicional]? [valor_si_verdadero]:[valor_si_falso];  

Se evalúa la "expresión_condicional". Si es cierto, "value_if_true" se asigna a "signal_name". Si no es cierto, "signal_name" obtiene "value_if_false". Como ejemplo, considere el siguiente código:

  asignar out1 =(sel)? (a &b):(a | b);  

Si "sel" es verdadero, a &b se asignará a "out1". Si no es cierto, "out1" obtendrá a | b. Por lo tanto, el código anterior implementa la funcionalidad de un multiplexor 2 a 1. La implementación conceptual de este código puede ser como se muestra en la Figura 1 a continuación.

La asignación condicional nos permite tener una descripción más abstracta de ciertos circuitos porque tiene la funcionalidad de una declaración "si" que se encuentra en los lenguajes tradicionales de programación de computadoras. El operador condicional se puede utilizar de forma anidada para implementar circuitos más complejos. El ejemplo 1 analiza estos detalles.

Ejemplo 1:Operadores condicionales anidados

Utilice el operador condicional (? :) para describir un codificador de prioridad 4 a 2 con la siguiente tabla de verdad:

El código Verilog para este codificador de prioridad se proporciona a continuación:

  módulo Prio_4_to_2 (cable de entrada [3:0] x, cable de salida [1:0] y, cable de salida v); asignar y =x [3]? 2'b11:x [2]? 2'b10:x [1]? 2'b01:2'b00; asignar v =(x [3] | x [2] | x [1] | x [0])? 1'b1:1'b0; endmodule  

Aparte de las líneas 7 a 10, el código contiene los elementos básicos del lenguaje discutidos en nuestro artículo anterior. Así que echemos un vistazo a estas líneas.

Los términos 2'b11, 2'b10, 2'b01 se refieren a las notaciones de Verilog que representan números binarios de dos bits. En general, el primer número (antes de "b) especifica el número de bits. La letra b especifica que los números son binarios. Los dígitos después de "b dan el valor del número. Por lo tanto, 2'b01 es la notación Verilog para representar un número binario de dos bits con valor 01 y 3'b100 denota un número binario de tres bits con valor 100.

La línea 7 comprueba el MSB de la entrada, x [3], en un operador condicional. Si x [3] =1, la condición se evalúa como verdadera y 2'b11 se asigna ay (el valor asignado se toma de la tabla de verdad). Si x [3] =0, la condición se evalúa como falsa y la expresión después de los dos puntos (:) se asignará a y. La expresión después de los dos puntos es el código de la línea 8, que en sí mismo es otro operador condicional.

El segundo operador condicional en la línea 8 examina el segundo bit más significativo de la entrada, x [2], para determinar si 2'b10 debe asignarse ay o la expresión después de los dos puntos, que es de nuevo otro operador condicional (línea 9). ser evaluado. Puede verificar que los valores asignados ay coincidan con la tabla de verdad dada.

La salida válida (v) de la tabla de verdad será lógica alta si al menos un bit de la entrada es lógica alta. La línea 11 muestra esta descripción aplicando el operador OR bit a bit (|) a los bits de la entrada. En la Figura 2 se muestra una simulación ISE de Xilinx del código anterior.

Figura 2. Una simulación de Xilinx ISE del código anterior.

Es importante tener en cuenta que las expresiones condicionales se evalúan sucesivamente hasta que se encuentra una expresión verdadera. Se realizará la asignación correspondiente a esta expresión verdadera. Como resultado, las expresiones evaluadas anteriormente tienen una mayor prioridad en comparación con las siguientes. Esto significa que, teóricamente, un operador condicional es más adecuado para implementar una red prioritaria (Figura 3) que una estructura balanceada como un multiplexor (Figura 4).

Figura 3. Una red prioritaria.

Figura 4. Un multiplexor n-a-1 en el que no hay prioridad entre las entradas.

Un artículo anterior revela una discusión similar sobre las asignaciones concurrentes de VHDL.

Declaraciones de procedimiento de Verilog

Podemos separar cualquier circuito combinacional en unas pocas puertas lógicas básicas (Y, O, NO, etc.) y usar la declaración "asignar" para describir estas puertas (una descripción a nivel de puerta). También podemos usar el operador condicional discutido en la sección anterior para tener una forma más abstracta de describir algunos circuitos combinacionales (similar a la declaración "if" de los lenguajes de programación de computadoras). Sin embargo, todavía hay una solución más poderosa:usar el bloque Verilog "always".

Dentro de un bloque "siempre", podemos tener sentencias de procedimiento que se ejecutan en secuencia. Además, el bloque "always" admite construcciones de lenguaje abstracto como declaraciones "if" y "case".

La función de ejecución secuencial junto con las construcciones de lenguaje abstracto disponibles dentro de un bloque "siempre" nos permite describir más fácilmente la funcionalidad de un circuito, debido al hecho de que el razonamiento humano tiene una naturaleza secuencial y se basa en descripciones abstractas. Por lo general, pensamos en una forma algorítmica de alto nivel en lugar de en términos de puertas lógicas de bajo nivel. Un bloque "siempre" puede proporcionarnos una solución más fácil para describir un circuito digital. Para obtener más detalles sobre por qué las HDL admiten descripciones basadas en declaraciones secuenciales, consulte mi artículo Introducción a las declaraciones secuenciales de VHDL.

Ejemplo 2:instrucciones de bloqueo "siempre"

La sintaxis simplificada de un bloque "siempre" se da a continuación:

  siempre @ (lista_de_sensibilidad) comienza las declaraciones_secuenciales; fin  

La lista de sensibilidad especifica cuándo deben ejecutarse las instrucciones secuenciales dentro del bloque "siempre". Por ejemplo, considere usar el bloque "siempre" para describir el circuito en la Figura 5.

Figura 5. Circuit_1

Cuando aob cambia, la salida puede cambiar, lo que significa que tanto a como b deben estar en la lista de sensibilidad del bloque "siempre". En general, para un circuito combinacional, todas las señales de entrada deben incluirse en la lista de sensibilidad.

Ahora, podemos usar el operador AND bit a bit para describir la funcionalidad del circuito (a &b) y asignar el resultado a la salida. Dentro de un bloque "siempre", hay dos tipos diferentes de asignaciones:la asignación de bloqueo (=) y la asignación de no bloqueo (<=). Usando la asignación de bloqueo, obtenemos el siguiente código:

  siempre @ (a, b) begin out1 =a &b; end  

¿Cuál es la diferencia entre una asignación de bloqueo y una asignación sin bloqueo?

Con una asignación de bloqueo, el lado derecho se evalúa y se asigna inmediatamente a out1. Por lo tanto, cuando se ejecuta la Línea 3, out1 se actualiza inmediatamente antes de pasar a la siguiente línea del código. El nombre "asignación de bloqueo" enfatiza que las próximas líneas están bloqueadas hasta que se actualice el lado izquierdo.

Con una asignación sin bloqueo, la expresión de la derecha se evalúa pero no se aplica a la variable de la izquierda hasta que llegamos al final del bloque "siempre". La elección de la asignación de bloqueo o no bloqueo puede ser confusa para un principiante y el uso inadecuado de ellos puede conducir a una funcionalidad no deseada. Por ejemplo, el uso de asignaciones de bloqueo para inferir flip-flops puede introducir una condición de carrera.

Para este artículo introductorio, no entraremos en más detalles y solo nos ceñiremos a una pauta simple para evitar posibles errores:use las asignaciones de bloqueo al escribir el código para un circuito combinacional. Por lo tanto, el bloque "always" en el Listado 1 se utilizará para describir una puerta AND.

En un artículo anterior, nos familiarizamos con el tipo de datos "cable" de Verilog. Este tipo de datos representa un cable físico en nuestro diseño de FPGA. Dentro de un bloque "siempre", el estándar Verilog no nos permite asignar un valor a un "cable". En su lugar, usamos el tipo de datos "reg". El nombre "reg" es algo confuso, pero tenga en cuenta que un "reg" puede conducir o no a un elemento de almacenamiento físico en su diseño. El siguiente código es la descripción de Verilog de la Figura 5 usando un bloque "siempre". Tenga en cuenta que el tipo de datos de salida debe ser "reg" porque obtiene su valor de una asignación de procedimiento.

  módulo Circuit_1 (cable de entrada a, cable de entrada b, salida reg out1); siempre @ (a, b) comienzan desde1 =a &b; end endmodule  

En este artículo, nos familiarizamos con el operador condicional Verilog. Usamos la forma anidada de este operador para describir un codificador de prioridad. Luego, tocamos una construcción de lenguaje más poderosa, el bloque "siempre", para describir los circuitos combinacionales. En artículos futuros, examinaremos el uso del bloque "always" para implementar circuitos secuenciales.


Incrustado

  1. Introducción a Verilog
  2. Introducción a los circuitos de CC
  3. Introducción a los circuitos de CA
  4. Uso de múltiples circuitos combinacionales
  5. Circuitos rectificadores
  6. Circuitos de control
  7. Operadores de C#
  8. C# ternario (? :) Operador
  9. Tutorial de Verilog
  10. Concatenación Verilog
  11. Compilación condicional de Verilog `ifdef