Verilog

Ajustar Compartir Imprimir Citar
Hardware descripción del idioma

Verilog, estandarizado como IEEE 1364, es un lenguaje de descripción de hardware (HDL) que se utiliza para modelar sistemas electrónicos. Se usa más comúnmente en el diseño y verificación de circuitos digitales en el nivel de abstracción de transferencia de registro. También se utiliza en la verificación de circuitos analógicos y circuitos de señal mixta, así como en el diseño de circuitos genéticos. En 2009, el estándar Verilog (IEEE 1364-2005) se fusionó con el estándar SystemVerilog, creando el estándar IEEE 1800-2009. Desde entonces, Verilog es oficialmente parte del lenguaje SystemVerilog. La versión actual es el estándar IEEE 1800-2017.

Resumen

Los lenguajes de descripción de hardware como Verilog son similares a los lenguajes de programación de software porque incluyen formas de describir el tiempo de propagación y la intensidad de la señal (sensibilidad). Hay dos tipos de operadores de asignación; una asignación de bloqueo (=) y una asignación de no bloqueo (<=). La asignación sin bloqueo permite a los diseñadores describir una actualización de máquina de estado sin necesidad de declarar y usar variables de almacenamiento temporal. Dado que estos conceptos son parte de la semántica del lenguaje de Verilog, los diseñadores pueden escribir rápidamente descripciones de circuitos grandes en una forma relativamente compacta y concisa. En el momento de la introducción de Verilog (1984), Verilog representó una tremenda mejora en la productividad para los diseñadores de circuitos que ya usaban software de captura de esquemas gráficos y programas de software especialmente escritos para documentar y simular circuitos electrónicos.

Los diseñadores de Verilog querían un lenguaje con una sintaxis similar al lenguaje de programación C, que ya se usaba ampliamente en el desarrollo de software de ingeniería. Al igual que C, Verilog distingue entre mayúsculas y minúsculas y tiene un preprocesador básico (aunque menos sofisticado que el de ANSI C/C++). Sus palabras clave de flujo de control (if/else, for, while, case, etc.) son equivalentes y su precedencia de operadores es compatible con C. Las diferencias sintácticas incluyen: anchos de bits requeridos para declaraciones de variables, demarcación de bloques de procedimiento (Verilog usa begin /fin en lugar de llaves {}), y muchas otras diferencias menores. Verilog requiere que a las variables se les dé un tamaño definido. En C, estos tamaños se deducen del 'tipo' de la variable (por ejemplo, un tipo entero puede ser de 8 bits).

Un diseño de Verilog consta de una jerarquía de módulos. Los módulos encapsulan la jerarquía de diseño y se comunican con otros módulos a través de un conjunto de puertos de entrada, salida y bidireccionales declarados. Internamente, un módulo puede contener cualquier combinación de lo siguiente: declaraciones de red/variable (wire, reg, integer, etc.), bloques de declaraciones concurrentes y secuenciales e instancias de otros módulos (subjerarquías). Las declaraciones secuenciales se colocan dentro de un bloque de inicio/fin y se ejecutan en orden secuencial dentro del bloque. Sin embargo, los propios bloques se ejecutan simultáneamente, lo que convierte a Verilog en un lenguaje de flujo de datos.

El concepto de Verilog de 'alambre' consta de valores de señal (4 estados: "1, 0, flotante, indefinido") e intensidades de señal (fuerte, débil, etc.). Este sistema permite el modelado abstracto de líneas de señal compartidas, donde múltiples fuentes impulsan una red común. Cuando un cable tiene varios controladores, el valor (legible) del cable se resuelve en función de los controladores de origen y sus puntos fuertes.

Un subconjunto de declaraciones en el lenguaje Verilog son sintetizables. Los módulos de Verilog que se ajustan a un estilo de codificación sintetizable, conocido como RTL (nivel de transferencia de registro), se pueden realizar físicamente mediante software de síntesis. El software de síntesis transforma algorítmicamente la fuente de Verilog (abstracta) en una lista de conexiones, una descripción lógicamente equivalente que consta solo de primitivas lógicas elementales (AND, OR, NOT, flip-flops, etc.) que están disponibles en una tecnología FPGA o VLSI específica. Las manipulaciones adicionales de la lista de conexiones finalmente conducen a un modelo de fabricación de circuitos (como un conjunto de máscaras fotográficas para un ASIC o un archivo de flujo de bits para un FPGA).

Historia

Principio

Verilog fue creado por Prabhu Goel, Phil Moorby, Chi-Lai Huang y Douglas Warmke entre finales de 1983 y principios de 1984. Chi-Lai Huang había trabajado anteriormente en una descripción de hardware LALSD, un lenguaje desarrollado por el profesor S.Y.H. Su, por su trabajo de doctorado. El titular de los derechos de este proceso, en ese momento propietario, era "Automated Integrated Design Systems" (luego rebautizado como Gateway Design Automation en 1985). Gateway Design Automation fue adquirida por Cadence Design Systems en 1990. Cadence ahora tiene todos los derechos de propiedad de Verilog de Gateway y Verilog-XL, el simulador HDL que se convertiría en el estándar de facto (de los simuladores lógicos Verilog) para el próxima década. Originalmente, Verilog solo pretendía describir y permitir la simulación; la síntesis automatizada de subconjuntos del lenguaje a estructuras físicamente realizables (puertas, etc.) se desarrolló después de que el lenguaje lograra un uso generalizado.

Verilog es un acrónimo de las palabras "verificación" y "lógica".

Verilog-95

Con el creciente éxito de VHDL en ese momento, Cadence decidió hacer que el lenguaje estuviera disponible para la estandarización abierta. Cadence transfirió Verilog al dominio público bajo la organización Open Verilog International (OVI) (ahora conocida como Accellera). Más tarde, Verilog se envió a IEEE y se convirtió en el estándar IEEE 1364-1995, comúnmente conocido como Verilog-95.

En el mismo período de tiempo, Cadence inició la creación de Verilog-A para respaldar el soporte de estándares de su simulador analógico Spectre. Verilog-A nunca tuvo la intención de ser un lenguaje independiente y es un subconjunto de Verilog-AMS que abarcaba Verilog-95.

Verilog 2001

Se enviaron extensiones a Verilog-95 a IEEE para cubrir las deficiencias que los usuarios habían encontrado en el estándar Verilog original. Estas extensiones se convirtieron en el estándar IEEE 1364-2001 conocido como Verilog-2001.

Verilog-2001 es una actualización importante de Verilog-95. Primero, agrega soporte explícito para (complemento a 2) redes y variables firmadas. Anteriormente, los autores de código tenían que realizar operaciones firmadas utilizando manipulaciones de nivel de bit complicadas (por ejemplo, el bit de ejecución de una suma simple de 8 bits requería una descripción explícita del álgebra booleana para determinar su valor correcto). La misma función en Verilog-2001 se puede describir de forma más sucinta mediante uno de los operadores integrados: +, -, /, *, >>>. Una construcción de generación-finalización (similar a la generación-finalización de VHDL) permite que Verilog-2001 controle la creación de instancias de instancias y declaraciones a través de operadores de decisión normales (case-if-else). Usando generar-endgenerar, Verilog-2001 puede instanciar una matriz de instancias, con control sobre la conectividad de las instancias individuales. La E/S de archivos se ha mejorado con varias tareas nuevas del sistema. Y finalmente, se introdujeron algunas adiciones de sintaxis para mejorar la legibilidad del código (por ejemplo, siempre, @*, anulación de parámetro con nombre, declaración de encabezado de función/tarea/módulo estilo C).

Verilog-2001 es la versión de Verilog compatible con la mayoría de los paquetes de software EDA comerciales.

Verilog 2005

No debe confundirse con SystemVerilog, Verilog 2005 (estándar IEEE 1364-2005) consta de correcciones menores, aclaraciones de especificaciones y algunas funciones de lenguaje nuevas (como la palabra clave uwire).

Una parte separada del estándar Verilog, Verilog-AMS, intenta integrar el modelado de señales mixtas y analógicas con el Verilog tradicional.

Verilog del sistema

La llegada de los lenguajes de verificación de hardware, como OpenVera, y el lenguaje electrónico de Verisity alentaron el desarrollo de Superlog por parte de Co-Design Automation Inc (adquirida por Synopsys). Los cimientos de Superlog y Vera fueron donados a Accellera, que luego se convirtió en el estándar IEEE P1800-2005: SystemVerilog.

SystemVerilog es un superconjunto de Verilog-2005, con muchas características y capacidades nuevas para ayudar en la verificación y el modelado del diseño. A partir de 2009, los estándares de lenguaje SystemVerilog y Verilog se fusionaron en SystemVerilog 2009 (IEEE Standard 1800-2009). La versión actual es el estándar IEEE 1800-2017.

Ejemplo

A continuación se muestra un ejemplo simple de dos flip-flops:

módulo nivel superior()reloj,reseteo); entrada reloj; entrada reseteo; reg flop1; reg flop2; siempre @ ()posada reseteo o posada reloj) si ()reseteo) comenzar flop1 . 0; flop2 . 1; final más comenzar flop1 . flop2; flop2 . flop1; finalendmodule

El operador <= en Verilog es otro aspecto de ser un lenguaje de descripción de hardware en lugar de un lenguaje de procedimiento normal. Esto se conoce como "sin bloqueo" asignación. Su acción no se registra hasta después de que se haya ejecutado el bloque siempre. Esto significa que el orden de las asignaciones es irrelevante y producirá el mismo resultado: flop1 y flop2 intercambiarán valores cada reloj.

El otro operador de asignación = se denomina asignación de bloqueo. Cuando se utiliza la asignación =, a efectos lógicos, la variable de destino se actualiza inmediatamente. En el ejemplo anterior, si las declaraciones hubieran utilizado el operador de bloqueo = en lugar de <=, flop1 y flop2 no se habrían intercambiado. En cambio, como en la programación tradicional, el compilador entendería simplemente establecer flop1 igual a flop2 (y posteriormente ignorar la lógica redundante para establecer flop2 igual a flop1).

A continuación se muestra un circuito contador de ejemplo:

módulo Div20x ()rst, clk, cet, cep, Cuenta, tc);// TITLE 'Divide-by-20 contador con habilitaciones '// habilitar CEP es un reloj habilitado solamente// habilitar CET es una opción de reloj// permite la salida TC// un contador usando el lenguaje Verilogparámetro tamaño = 5;parámetro longitud = 20;entrada rst; // Estas entradas/salidas representanentrada clk; // conexiones al módulo.entrada cet;entrada cep;Producto [tamaño-1:0] Cuenta;Producto tc;reg [tamaño-1:0] Cuenta; // Señales asignados // dentro de un siempre // (o inicial)block // debe ser de tipo regalambre tc; // Otras señales son de alambre de tipo// La siempre declaración a continuación es paralela// Declaración de ejecución que// ejecuta en cualquier momento las señales// rst o clk transición de baja a altasiempre @ ()posada clk o posada rst) si ()rst) // Esto causa el restablecimiento del cntr Cuenta . {}tamaño{}1'b0} más si ()cet " cep) // Permite ambas cosas verdaderas comenzar si ()Cuenta == longitud-1) Cuenta . {}tamaño{}1'b0} más Cuenta . Cuenta + 1B1; final// el valor de tc se asigna continuamente// el valor de la expresiónc) tc = ()cet " ()Cuenta == longitud-1));endmodule

Un ejemplo de retrasos:

...reg a, b, c, d;alambre e;...siempre @(b o e) comenzar a = b " e; b = a Silencio b; #5 c = b; d = #6 c ^ e; final

La cláusula siempre anterior ilustra el otro tipo de método de uso, es decir, se ejecuta siempre que cualquiera de las entidades de la lista (la b o e) cambios. Cuando uno de estos cambios, a a se le asigna inmediatamente un nuevo valor, y debido a la asignación de bloqueo, a b se le asigna un nuevo valor posteriormente (teniendo en cuenta el nuevo valor de a). Después de un retraso de 5 unidades de tiempo, a c se le asigna el valor de b y el valor de c ^ e se guarda en una tienda invisible. Luego, después de 6 unidades de tiempo más, se le asigna a d el valor que se guardó.

Las señales que son impulsadas desde dentro de un proceso (un bloque inicial o siempre) deben ser del tipo reg. Las señales que se manejan desde fuera de un proceso deben ser del tipo cable. La palabra clave reg no implica necesariamente un registro de hardware.

Definición de constantes

La definición de constantes en Verilog admite la adición de un parámetro de ancho. La sintaxis básica es:

<Ancho en bits>'<letra base><número>

Ejemplos:

Construcciones sintetizables

Verilog es ampliamente considerado como un HDL (lenguaje de descripción de hardware). Hay varias declaraciones en Verilog que no tienen analogía en el hardware real, p. $pantalla. En consecuencia, gran parte del lenguaje no se puede utilizar para describir el hardware. Esto parecería implicar que la definición misma del lenguaje Verilog en general necesita ser recaracterizada adecuadamente. Sin embargo, los ejemplos presentados aquí son el subconjunto clásico (y limitado) del lenguaje que tiene un mapeo directo a puertas reales.

// Ejemplos de mux Tres maneras de hacer lo mismo.// El primer ejemplo utiliza la asignación continuaalambre Fuera.;c) Fuera. = Sel ? a : b;// el segundo ejemplo utiliza un procedimiento// para lograr lo mismo.reg Fuera.;siempre @(a o b o Sel) comenzar Caso()Sel) 1'b0: Fuera. = b; 1B1: Fuera. = a; maleta final// Finalmente, se puede utilizar si/else en un// Estructura procesal.reg Fuera.;siempre @(a o b o Sel) si ()Sel) Fuera. = a; más Fuera. = b;

La siguiente estructura interesante es un pestillo transparente; pasará la entrada a la salida cuando la señal de la puerta esté configurada para 'paso a través', y capturará la entrada y la almacenará tras la transición de la señal de la puerta a 'mantener'. La salida permanecerá estable independientemente de la señal de entrada mientras la puerta esté configurada en 'mantener'. En el siguiente ejemplo, el "paso a través" el nivel de la puerta sería cuando el valor de la cláusula if es verdadero, es decir, puerta = 1. Esto se lee "si la puerta es verdadera, el din se envía a latch_out continuamente." Una vez que la cláusula if sea falsa, el último valor en latch_out permanecerá y es independiente del valor de din.

// Ejemplo de cierre transparentereg Latch_out;siempre @(Puerta o din) si()Puerta) Latch_out = din; // Pasa por el estado // Tenga en cuenta que el otro no es requerido aquí. La variable // latch_out seguirá el valor de din mientras la puerta es // alto. Cuando la puerta baja, latch_out seguirá siendo constante.

El flip-flop es la próxima plantilla importante; en Verilog, el D-flop es el más simple y se puede modelar como:

reg q;siempre @(posada clk) q . d;

Lo importante a notar en el ejemplo es el uso de la asignación sin bloqueo. Una regla general básica es usar <= cuando hay una declaración posedge o negedge dentro de la cláusula always.

Una variante del D-flop es uno con reinicio asíncrono; existe una convención de que el estado de reinicio será la primera cláusula if dentro de la instrucción.

reg q;siempre @(posada clk o posada reseteo) si()reseteo) q . 0; más q . d;

La siguiente variante incluye tanto un restablecimiento asíncrono como una condición de configuración asíncrona; de nuevo entra en juego la convención, es decir, el término de reinicio es seguido por el término establecido.

reg q;siempre @(posada clk o posada reseteo o posada set) si()reseteo) q . 0; más si()set) q . 1; más q . d;

Nota: si este modelo se utiliza para modelar un flip flop Set/Reset, pueden producirse errores de simulación. Considere la siguiente secuencia de prueba de eventos. 1) el restablecimiento sube 2) el reloj sube 3) el ajuste sube 4) el reloj vuelve a subir 5) el restablecimiento baja seguido de 6) el ajuste baja. Suponga que no hay infracciones de configuración y retención.

En este ejemplo, la declaración always @ se ejecutaría primero cuando se produzca el flanco ascendente de reset, lo que colocaría a q en un valor de 0. La próxima vez que se ejecute el bloque always sería el flanco ascendente de clk, que nuevamente mantendría q en un valor de 0. El bloque siempre se ejecuta cuando set sube, lo que debido a que reset es alto obliga a q a permanecer en 0. Esta condición puede o no ser correcta según el flip flop real. Sin embargo, este no es el principal problema de este modelo. Tenga en cuenta que cuando el reinicio es bajo, ese conjunto sigue siendo alto. En un flip flop real, esto hará que la salida vaya a 1. Sin embargo, en este modelo no ocurrirá porque el bloque siempre se activa por los flancos ascendentes de establecer y restablecer, no los niveles. Puede ser necesario un enfoque diferente para los flip-flops de configuración/reinicio.

La variante básica final es una que implementa un D-flop con un mux alimentando su entrada. El mux tiene una entrada d y retroalimentación del mismo flop. Esto permite una función de carga cerrada.

// Estructura básica con una ruta de retroalimentación EXPLICITsiempre @(posada clk) si()Puerta) q . d; más q . q; // ruta explícita de retroalimentación// La estructura más común ASSUMES la retroalimentación está presente// Esta es una suposición segura ya que así es como// Compilador de hardware lo interpretará. Esta estructura// se parece mucho a un latch. Las diferencias son las// '''@(posedge clk)''' y el no bloqueo ''' '//siempre @(posada clk) si()Puerta) q . d; // el mux "else" es "implied"

Tenga en cuenta que no hay "inicial" bloques mencionados en esta descripción. Hay una división entre las herramientas de síntesis FPGA y ASIC en esta estructura. Las herramientas de FPGA permiten bloques iniciales en los que se establecen los valores de registro en lugar de usar un "restablecimiento" señal. Las herramientas de síntesis ASIC no admiten tal declaración. La razón es que el estado inicial de un FPGA es algo que se descarga en las tablas de memoria del FPGA. Un ASIC es una implementación de hardware real.

Inicial y siempre

Hay dos formas distintas de declarar un proceso de Verilog. Estas son las palabras clave siempre y inicial. La palabra clave siempre indica un proceso de ejecución libre. La palabra clave inicial indica que un proceso se ejecuta exactamente una vez. Ambas construcciones comienzan a ejecutarse en el tiempo 0 del simulador y ambas se ejecutan hasta el final del bloque. Una vez que un bloque siempre ha llegado a su fin, se reprograma (nuevamente). Es un error común creer que un bloque inicial se ejecutará antes que un bloque siempre. De hecho, es mejor pensar en el bloque inicial como un caso especial del bloque siempre, que termina después de completarse por primera vez.

//Ejemplos:inicial comenzar a = 1; // Asignar un valor a reg a la vez 0 #1; // Espera 1 unidad de tiempo b = a; // Asignar el valor de la reg a reg b finalsiempre @(a o b) // En cualquier momento a o b CHANGE, ejecute el procesocomenzar si ()a) c = b; más d = ~b;final // Hecho con este bloque, ahora volver a la parte superior (es decir, el control de eventos @)siempre @(posada a)// Correr cada reg a tiene un cambio bajo a alto a . b;

Estos son los usos clásicos de estas dos palabras clave, pero hay dos usos adicionales significativos. La más común de ellas es una palabra clave siempre sin la lista de confidencialidad @(...). Es posible usar siempre como se muestra a continuación:

siempre comenzar // Siempre comienza a ejecutar a tiempo 0 y NUNCA se detiene clk = 0; // Set clk to 0 #1; // Esperar 1 unidad de tiempo clk = 1; // Set clk a 1 #1; // Espera 1 unidad de tiempo final // Sigue ejecutando - así que continúe de nuevo en la parte superior del comienzo

La palabra clave always actúa de manera similar a la construcción del lenguaje C while(1) {..} en el sentido de que se ejecutará para siempre.

La otra excepción interesante es el uso de la palabra clave inicial con la adición de la palabra clave para siempre.

El siguiente ejemplo es funcionalmente idéntico al ejemplo anterior de siempre.

inicial para siempre // Comienza a tiempo 0 y repite el inicio/fin por siempre comenzar clk = 0; // Set clk to 0 #1; // Esperar 1 unidad de tiempo clk = 1; // Set clk a 1 #1; // Espera 1 unidad de tiempo final

Bifurcación/unión

Verilog utiliza el par fork/join para crear procesos paralelos. Todas las declaraciones (o bloques) entre un par bifurcación/unión comienzan a ejecutarse simultáneamente cuando el flujo de ejecución llega a la bifurcación. La ejecución continúa después de join al completarse la declaración o bloque de ejecución más larga entre fork y join.

inicial tenedor $write()"A"); // Print char A $write()"B"); // Print char B comenzar #1; // Espera 1 unidad de tiempo $write()"C"); // Print char C final Únase

De la forma en que está escrito lo anterior, es posible tener las secuencias "ABC" o "BAC" imprimir. El orden de simulación entre la primera $escritura y la segunda $escritura depende de la implementación del simulador, y el simulador puede aleatorizarla a propósito. Esto permite que la simulación contenga tanto condiciones de carrera accidentales como comportamiento no determinista intencional.

Observe que VHDL no puede generar dinámicamente múltiples procesos como Verilog.

Condiciones de carrera

El orden de ejecución no siempre está garantizado en Verilog. Esto se puede ilustrar mejor con un ejemplo clásico. Considere el fragmento de código a continuación:

inicial a = 0;inicial b = a;inicial comenzar #1; Display()"Valor a=%d Valor de b=%d",a,b); final

¿Qué se imprimirá para los valores de a y b? Dependiendo del orden de ejecución de los bloques iniciales, podría ser cero y cero, o alternativamente cero y algún otro valor arbitrario no inicializado. La instrucción $display siempre se ejecutará después de que se hayan completado ambos bloques de asignación, debido al retraso n.º 1.

Operadoras

(feminine)

Nota: Estos operadores no se muestran en orden de precedencia.

Tipo de operadorSímbolos de operadorOperación realizada
Bitwise~Bitwise NO (1's complement)
"Bitwise
SilencioBitwise OR
^Bitwise XOR
################################################################################################################################################################################################################################################################Bitwise XNOR
Lógica!NO
"Y
SilencioO
Reducción"Reducción
~Reducción NAND
SilencioReducción o reducción
~ SobrevivirReducción NOR
^Reducción XOR
################################################################################################################################################################################################################################################################Reducción XNOR
Arithmetic+Adición
-Sustracción
-Complemento de 2
*Multiplicación
/División
#Exposición (*Verilog-2001)
RelaciónMás grande que
.Menos que
>=Mayor o igual a
.Menos o igual a
==Igualdad lógica (valor bit 1'bX se elimina de la comparación)
!La desigualdad lógica (valor bit 1'bX se elimina de la comparación)
==Igualdad lógica de 4 estados (valor de bits 1'bX se toma como literal)
!La desigualdad lógica de 4 estados (valor de bits 1'bX se toma como literal)
Cambio>Cambio lógico derecho
..Cambio lógico izquierdo
, tituladoCambio de derecho Aritmético (*Verilog-2001)
c).Desplazamiento de la izquierda Aritmético (*Verilog-2001)
Concatenación{}Concatenación
Replicación{n{m}Replicar el valor m por n veces
condicional?condicional

Lógica de cuatro valores

El estándar IEEE 1364 define una lógica de cuatro valores con cuatro estados: 0, 1, Z (alta impedancia) y X (valor lógico desconocido). Para el VHDL de la competencia, existe un estándar dedicado para la lógica de valores múltiples como IEEE 1164 con nueve niveles.

Tareas del sistema

Las tareas del sistema están disponibles para manejar E/S simples y varias funciones de medición de diseño durante la simulación. Todas las tareas del sistema tienen el prefijo $ para distinguirlas de las tareas y funciones del usuario. En esta sección se presenta una breve lista de las tareas más utilizadas. De ninguna manera es una lista exhaustiva.

Interfaz de lenguaje de programación (PLI)

El PLI proporciona a un programador un mecanismo para transferir el control de Verilog a una función de programa escrita en lenguaje C. Está oficialmente obsoleto por IEEE Std 1364-2005 a favor de la interfaz de procedimiento Verilog más nueva, que reemplaza completamente al PLI.

El PLI (ahora VPI) permite a Verilog cooperar con otros programas escritos en lenguaje C, como arneses de prueba, simuladores de conjuntos de instrucciones de un microcontrolador, depuradores, etc. Por ejemplo, proporciona las funciones C tf_putlongp() y tf_getlongp() que se utilizan para escribir y leer el argumento de la tarea o función actual de Verilog, respectivamente.

Software de simulación

Para obtener información sobre los simuladores de Verilog, consulte la lista de simuladores de Verilog.