Diseño VLSI - Introducción a Verilog

Verilog es un LENGUAJE DE DESCRIPCIÓN DE HARDWARE (HDL). Es un lenguaje utilizado para describir un sistema digital como un conmutador de red o un microprocesador o una memoria o un flip-flop. Significa que al usar un HDL podemos describir cualquier hardware digital en cualquier nivel. Los diseños, que se describen en HDL son independientes de la tecnología, muy fáciles de diseñar y depurar, y normalmente son más útiles que los esquemas, especialmente para circuitos grandes.

Verilog admite un diseño en muchos niveles de abstracción. Los tres principales son:

  • Nivel de comportamiento
  • Nivel de transferencia de registro
  • Nivel de puerta

Nivel de comportamiento

Este nivel describe un sistema mediante algoritmos concurrentes (Behavioural). Cada algoritmo es secuencial, lo que significa que consta de un conjunto de instrucciones que se ejecutan una a una. Las funciones, tareas y bloques son los elementos principales. No se tiene en cuenta la realización estructural del diseño.

Nivel de transferencia de registro

Los diseños que utilizan el nivel de transferencia de registros especifican las características de un circuito que utiliza operaciones y la transferencia de datos entre los registros. La definición moderna de un código RTL es "Cualquier código sintetizable se llama código RTL".

Nivel de puerta

Dentro del nivel lógico, las características de un sistema se describen mediante enlaces lógicos y sus propiedades de temporización. Todas las señales son señales discretas. Solo pueden tener valores lógicos definidos (`0 ',` 1', `X ',` Z`). Las operaciones utilizables son primitivas lógicas predefinidas (puertas básicas). El modelado a nivel de puerta puede no ser una buena idea para el diseño lógico. El código de nivel de puerta se genera utilizando herramientas como herramientas de síntesis y su lista de conexiones se utiliza para la simulación de nivel de puerta y para backend.

Fichas léxicas

Los archivos de texto de origen del idioma Verilog son un flujo de tokens léxicos. Un token consta de uno o más caracteres, y cada carácter individual está en exactamente un token.

Los tokens léxicos básicos utilizados por Verilog HDL son similares a los del lenguaje de programación C. Verilog distingue entre mayúsculas y minúsculas. Todas las palabras clave están en minúsculas.

Espacio en blanco

Los espacios en blanco pueden contener caracteres para espacios, tabulaciones, nuevas líneas y alimentaciones de formularios. Estos caracteres se ignoran excepto cuando sirven para separar tokens.

Los caracteres de espacio en blanco son espacios en blanco, tabulaciones, retornos de carro, nueva línea y alimentaciones de formulario.

Comentarios

Hay dos formas de representar los comentarios.

  • 1) Los comentarios de una sola línea comienzan con el token // y terminan con el retorno de carro.

Ej .: // esta es una sintaxis de una sola línea

  • 2) Los comentarios de varias líneas comienzan con el token / * y terminan con el token * /

Ej .: / * esto es sintaxis multilínea * /

Números

Puede especificar un número en formato binario, octal, decimal o hexadecimal. Los números negativos se representan en números complementarios de 2. Verilog permite enteros, números reales y números con y sin signo.

La sintaxis viene dada por - <tamaño> <radix> <valor>

El tamaño o el número sin tamaño se puede definir en <Size> y <radix> define si es binario, octal, hexadecimal o decimal.

Identificadores

Identificador es el nombre que se utiliza para definir el objeto, como una función, módulo o registro. Los identificadores deben comenzar con caracteres alfabéticos o caracteres de subrayado. Ex. A_Z, a_z, _

Los identificadores son una combinación de caracteres alfabéticos, numéricos, de subrayado y $. Pueden tener hasta 1024 caracteres.

Operadores

Los operadores son caracteres especiales que se utilizan para poner condiciones o para operar las variables. Hay uno, dos y, a veces, tres caracteres que se utilizan para realizar operaciones en variables.

Ex. >, +, ~, &! =.

Palabras clave de Verilog

Las palabras que tienen un significado especial en Verilog se denominan palabras clave Verilog. Por ejemplo, assign, case, while, wire, reg, and, or, nand y module. No deben utilizarse como identificadores. Las palabras clave de Verilog también incluyen directivas del compilador y tareas y funciones del sistema.

Modelado de nivel de puerta

Verilog tiene primitivas integradas como puertas lógicas, puertas de transmisión e interruptores. Rara vez se utilizan para trabajos de diseño, pero se utilizan en el mundo de la post síntesis para el modelado de células ASIC / FPGA.

El modelado a nivel de puerta presenta dos propiedades:

Drive strength- La fuerza de las puertas de salida se define por la fuerza del accionamiento. La salida es más fuerte si hay una conexión directa a la fuente. La fuerza disminuye si la conexión es a través de un transistor conductor y menos cuando se conecta a través de un resistivo pull-up / down. Por lo general, no se especifica la fuerza de la unidad, en cuyo caso las fortalezas se establecen por defecto en strong1 y strong0.

Delays- Si no se especifican retardos, las puertas no tienen retardos de propagación; si se especifican dos retrasos, el primero representa el retraso de subida y el segundo, el retraso de caída; si solo se especifica un retraso, ambos, subida y bajada, son iguales. Los retrasos pueden ignorarse en la síntesis.

Primitivas de puerta

Las puertas lógicas básicas que utilizan una salida y muchas entradas se utilizan en Verilog. GATE usa una de las palabras clave, y, nand, o, nor, xor, xnor para usar en Verilog para N número de entradas y 1 salida.

Example:  
   Module gate() 
   Wire ot0; 
   Wire ot1; 
   Wire ot2; 
   
   Reg in0,in1,in2,in3; 
   Not U1(ot0,in0); 
   Xor U2(ot1,in1,in2,in3); 
   And U3(ot2, in2,in3,in0)

Primitivas de puerta de transmisión

Las primitivas de la puerta de transmisión incluyen tanto búferes como inversores. Tienen una sola entrada y una o más salidas. En la sintaxis de instanciación de puerta que se muestra a continuación, GATE significa la palabra clave buf o NOT gate.

Ejemplo: Not, buf, bufif0, bufif1, notif0, notif1

No - n inversor de salida

Buf - n búfer de salida

Bufifo - búfer triestado, habilitación baja activa

Bufif1 - búfer triestado, habilitación alta activa

Notifo - inversor tristate, habilitación baja activa

Notif1 - inversor tristate, habilitación alta activa

Example:  
   Module gate() 
   Wire out0; 
   Wire out1; 
   
   Reg in0,in1;
   Not U1(out0,in0); 
   Buf U2(out0,in0);

Tipos de datos

Conjunto de valores

Verilog consta, principalmente, de cuatro valores básicos. Todos los tipos de datos de Verilog, que se utilizan en Verilog almacenan estos valores:

0 (cero lógico o condición falsa)

1 (uno lógico o condición verdadera)

x (valor lógico desconocido)

z (estado de alta impedancia)

el uso de xyz es muy limitado para la síntesis.

Cable

Un cable se usa para representar un cable físico en un circuito y se usa para la conexión de puertas o módulos. El valor de un hilo solo se puede leer y no asignar en una función o bloque. Un cable no puede almacenar valor, pero siempre es impulsado por una declaración de asignación continua o conectando el cable a la salida de una puerta / módulo. Otros tipos específicos de cables son:

Wand (wired-AND) - aquí el valor de Wand depende del Y lógico de todos los controladores de dispositivo conectados a él.

Wor (wired-OR) - aquí el valor de Wor depende del OR lógico de todos los controladores de dispositivo conectados a él.

Tri (three-state) - aquí todos los controladores conectados a un tri deben ser z, excepto solo uno (que determina el valor de tri).

Example: 
   Wire [msb:lsb] wire_variable_list; 
   Wirec // simple wire 
   Wand d; 
   
   Assign d = a; // value of d is the logical AND of 
   Assign d = b; // a and b 
   Wire [9:0] A; // a cable (vector) of 10 wires. 
   
   Wand [msb:lsb] wand_variable_list; 
   Wor [msb:lsb] wor_variable_list; 
   Tri [msb:lsb] tri_variable_list;

Registrarse

Un reg (registro) es un objeto de datos, que contiene el valor de una asignación de procedimiento a la siguiente y se usa solo en diferentes funciones y bloques de procedimiento. Un reg es un Verilog simple, registro de tipo variable y no puede implicar un registro físico. En los registros de varios bits, los datos se almacenan en forma de números sin firmar y no se utiliza la extensión de signo.

Ejemplo -

reg c; // variable de registro única de 1 bit

reg [5: 0] gema; // un vector de 6 bits;

reg [6: 0] d, e; // dos variables de 7 bits

Entrada, salida, entrada

Estas palabras clave se utilizan para declarar puertos de entrada, salida y bidireccionales de una tarea o módulo. Aquí los puertos de entrada y salida, que son de tipo cable y el puerto de salida está configurado para ser de tipo cable, reg, wand, wor o tri. Siempre, el tipo de cable predeterminado es.

Example

Module sample(a, c, b, d);  
Input c;   // An input where wire is used. 

Output a, b;  // Two outputs where wire is used. 
Output [2:0] d;  /* A three-bit output. One must declare type in a separate statement. */ 
reg [1:0] a;  // The above ‘a’ port is for declaration in reg.

Entero

Los enteros se utilizan en variables de propósito general. Se utilizan principalmente en bucles: índices, constantes y parámetros. Son del tipo de datos de tipo 'reg'. Almacenan datos como números con signo, mientras que los tipos de registro declarados explícitamente los almacenan como datos sin firmar. Si el número entero no está definido en el momento de la compilación, el tamaño predeterminado sería de 32 bits.

Si un entero mantiene una constante, el sintetizador los ajusta al ancho mínimo necesario en el momento de la compilación.

Example

Integer c;   // single 32-bit integer 
Assign a = 63;  // 63 defaults to a 7-bit variable.

Supply0, Supply1

Supply0 define cables conectados a la lógica 0 (tierra) y supply1 define los cables conectados a la lógica 1 (alimentación).

Example

supply0 logic_0_wires; 
supply0 gnd1;  // equivalent to a wire assigned as 0 

supply1 logic_1_wires; 
supply1 c, s;

Hora

El tiempo es una cantidad de 64 bits que se puede utilizar junto con la tarea del sistema $ time para mantener el tiempo de simulación. El tiempo no es compatible con la síntesis y, por lo tanto, se utiliza solo con fines de simulación.

Example

time time_variable_list; 
time c; 
c = $time;   //c = current simulation time

Parámetro

Un parámetro define una constante que se puede establecer cuando se usa un módulo, lo que permite la personalización del módulo durante el proceso de creación de instancias.

Example 
Parameter add = 3’b010, sub = 2’b11; 
Parameter n = 3; 
Parameter [2:0] param2 = 3’b110; 

reg [n-1:0] jam; /* A 3-bit register with length of n or above. */ 
always @(z) 
y = {{(add - sub){z}};  

if (z)
begin 
   state = param2[1];
else
   state = param2[2]; 
end

Operadores

Operadores aritméticos

Estos operadores realizan operaciones aritméticas. Los + y −se utilizan como operadores unarios (x) o binarios (z − y).

Los operadores que se incluyen en la operación aritmética son:

+ (suma), - (resta), * (multiplicación), / (división),% (módulo)

Example -

parameter v = 5;
reg[3:0] b, d, h, i, count; 
h = b + d; 
i = d - v; 
cnt = (cnt +1)%16; //Can count 0 thru 15.

Operadores relacionales

Estos operadores comparan dos operandos y devuelven el resultado en un solo bit, 1 o 0.

Las variables Wire y Reg son positivas. Por lo tanto (−3'd001) = = 3'd111 y (−3b001)> 3b110.

Los Operadores que se incluyen en la operación relacional son:

  • == (igual a)
  • ! = (no es igual a)
  • > (mayor que)
  • > = (mayor o igual que)
  • <(menor que)
  • <= (menor o igual que)

Example

if (z = = y) c = 1; 
   else c = 0; // Compare in 2’s compliment; d>b 
reg [3:0] d,b; 

if (d[3]= = b[3]) d[2:0] > b[2:0]; 
   else b[3]; 
Equivalent Statement 
e = (z == y);

Operadores de bits

Operadores bit a bit que están haciendo una comparación bit a bit entre dos operandos.

Los operadores que se incluyen en la operación de bits son:

  • & (bit a bit AND)
  • | (bit a bit o)
  • ~ (bit a bit NO)
  • ^ (XOR bit a bit)
  • ~ ^ o ^ ~ (XNOR bit a bit)

Example

module and2 (d, b, c); 
input [1:0] d, b; 
output [1:0] c; 
assign c = d & b; 
end module

Operadores logicos

Los operadores lógicos son operadores de bits y se utilizan solo para operandos de un solo bit. Devuelven un valor de un solo bit, 0 o 1. Pueden trabajar con números enteros o grupos de bits, expresiones y tratar todos los valores distintos de cero como 1. Los operadores lógicos generalmente se usan en declaraciones condicionales ya que trabajan con expresiones.

Los operadores que se incluyen en la operación lógica son:

  • ! (NO lógico)
  • && (Y lógico)
  • || (OR lógico)

Example

wire[7:0] a, b, c; // a, b and c are multibit variables. 
reg x; 

if ((a == b) && (c)) x = 1; //x = 1 if a equals b, and c is nonzero. 
   else x = !a; // x =0 if a is anything but zero.

Operadores de reducción

Los operadores de reducción son la forma unaria de los operadores bit a bit y operan en todos los bits de un vector de operando. Estos también devuelven un valor de un solo bit.

Los operadores que se incluyen en la operación de Reducción son:

  • & (reducción Y)
  • | (reducción OR)
  • ~ & (reducción NAND)
  • ~ | (reducción NOR)
  • ^ (reducción XOR)
  • ~ ^ o ^ ~ (reducción XNOR)

Example

Module chk_zero (x, z); 

Input [2:0] x; 
Output z; 
Assign z = & x; // Reduction AND 
End module

Operadores de turno

Operadores de desplazamiento, que desplazan el primer operando según el número de bits especificado por el segundo operando en la sintaxis. Los puestos vacantes se llenan con ceros para ambas direcciones, turnos a la izquierda y a la derecha (no hay extensión de señal de uso).

Los operadores que se incluyen en la operación de cambio son:

  • << (desplazamiento a la izquierda)
  • >> (desplazamiento a la derecha)

Example

Assign z = c << 3; /* z = c shifted left 3 bits;

Los puestos vacantes se llenan con ceros * /

Operador de concatenación

El operador de concatenación combina dos o más operandos para formar un vector más grande.

El operador incluido en la operación de concatenación es - {} (concatenación)

Example

wire [1:0] a, h; wire [2:0] x; wire [3;0] y, Z; 
assign x = {1’b0, a}; // x[2] = 0, x[1] = a[1], x[0] = a[0] 
assign b = {a, h}; /* b[3] = a[1], b[2] = a[0], b[1] = h[1], 
b[0] = h[0] */ 
assign {cout, b} = x + Z; // Concatenation of a result

Operador de replicación

El operador de replicación está haciendo varias copias de un artículo.

El operador utilizado en la operación de replicación es: {n {item}} (replicación n veces de un elemento)

Example

Wire [1:0] a, f; wire [4:0] x; 
Assign x = {2{1’f0}, a}; // Equivalent to x = {0,0,a } 
Assign y = {2{a}, 3{f}}; //Equivalent to y = {a,a,f,f} 
For synthesis, Synopsis did not like a zero replication.

For example:- 
Parameter l = 5, k = 5; 
Assign x = {(l-k){a}}

Operador condicional

El operador condicional sintetiza en un multiplexor. Es del mismo tipo que se utiliza en C / C ++ y evalúa una de las dos expresiones según la condición.

El operador utilizado en la operación condicional es:

(Condición)? (Resultado si la condición es verdadera) -

(resultado si la condición es falsa)

Example

Assign x = (g) ? a : b; 
Assign x = (inc = = 2) ? x+1 : x-1; 
/* if (inc), x = x+1, else x = x-1 */

Operandos

Literales

Los literales son operandos de valor constante que se utilizan en las expresiones de Verilog. Los dos literales de Verilog de uso común son:

  • String - Un operando literal de cadena es una matriz unidimensional de caracteres, que se encierran entre comillas dobles ("").

  • Numeric - Un operando de número constante se especifica en número binario, octal, decimal o hexadecimal.

Example

n - entero que representa el número de bits

F - uno de los cuatro posibles formatos base -

b para binario, o para octal, d para decimal, h para hexadecimal.

“time is”  // string literal 
267        // 32-bit decimal number 
2’b01      // 2-bit binary 
20’hB36F   // 20-bit hexadecimal number 
‘062       // 32-bit octal number

Cables, Regs y Parámetros

Los cables, las reglas y los parámetros son los tipos de datos que se utilizan como operandos en las expresiones de Verilog.

Selección de bits "x [2]" y selección de piezas "x [4: 2]"

Las selecciones de bits y las selecciones de partes se utilizan para seleccionar un bit y varios bits, respectivamente, de un vector de cable, registro o parámetro con el uso de corchetes “[]”. Las selecciones de bits y las selecciones de partes también se usan como operandos en expresiones de la misma manera que se usan sus objetos de datos principales.

Example

reg [7:0] x, y; 
reg [3:0] z; 
reg a; 
a = x[7] & y[7];      // bit-selects 
z = x[7:4] + y[3:0];  // part-selects

Llamadas a funciones

En las llamadas de función, el valor de retorno de una función se utiliza directamente en una expresión sin necesidad de asignarlo primero a un registro o cable. Simplemente coloca la llamada a la función como uno del tipo de operandos. Es necesario asegurarse de que conoce el ancho de bits del valor de retorno de la llamada a la función.

Example  
Assign x = y & z & chk_yz(z, y); // chk_yz is a function 

. . ./* Definition of the function */ 
Function chk_yz; // function definition 
Input z,y; 
chk_yz = y^z; 
End function

Módulos

Declaración del módulo

En Verilog, un módulo es la principal entidad de diseño. Esto indica el nombre y la lista de puertos (argumentos). Las siguientes líneas que especifican el tipo de entrada / salida (entrada, salida o inout) y el ancho de cada puerto. El ancho del puerto predeterminado es de solo 1 bit. Las variables de puerto deben declararse por cable, varita ,. . ., reg. La variable de puerto predeterminada es cable. Normalmente, las entradas son cableadas porque sus datos están bloqueados fuera del módulo. Las salidas son de tipo reg si sus señales se almacenan en el interior.

Example

module sub_add(add, in1, in2, out); 
input add; // defaults to wire 
input [7:0] in1, in2; wire in1, in2; 

output [7:0] out; reg out; 
... statements ... 
End module

Asignación continua

La asignación continua en un módulo se utiliza para asignar un valor a un cable, que es la asignación normal utilizada en el exterior de los bloques siempre o iniciales. Esta asignación se realiza con una declaración de asignación explícita o para asignar un valor a un cable durante su declaración. Las asignaciones continuas se ejecutan continuamente en el momento de la simulación. El orden de las sentencias de asignación no lo afecta. Si realiza algún cambio en cualquiera de las señales de entrada del lado derecho, cambiará una señal de salida del lado izquierdo.

Example

Wire [1:0] x = 2’y01;   // assigned on declaration 
Assign y = c | d;       // using assign statement 
Assign d = a & b; 
/* the order of the assign statements does not matter. */

Instancias de módulo

Las declaraciones de módulo son plantillas para crear objetos reales. Los módulos se instancian dentro de otros módulos, y cada instancia crea un objeto único a partir de esa plantilla. La excepción es el módulo de nivel superior que es su propia instanciación. Los puertos del módulo deben coincidir con los definidos en la plantilla. Se especifica -

  • By name, utilizando un punto ".template nombre del puerto (nombre del cable conectado al puerto)". O

  • By position, colocando los puertos en el mismo lugar en las listas de puertos tanto de la plantilla como de la instancia.

Example

MODULE DEFINITION 
Module and4 (x, y, z); 
Input [3:0] x, y; 
Output [3:0] z; 
Assign z = x | y; 
End module