Docsity
Docsity

Prepara tus exámenes
Prepara tus exámenes

Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity


Consigue puntos base para descargar
Consigue puntos base para descargar

Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium


Orientación Universidad
Orientación Universidad


Tutorial Verilog, aspectos básicos e introducción , Apuntes de Microcontroladores

Introduccion basica a Verilog

Tipo: Apuntes

2016/2017

Subido el 17/03/2017

Eric.garcia1
Eric.garcia1 🇲🇽

4.5

(2)

1 documento

1 / 23

Toggle sidebar

Esta página no es visible en la vista previa

¡No te pierdas las partes importantes!

bg1
Tutorial
Tutorial Verilo
g
Este tutorial pretende ser una guía de aprendizaje para el diseño HDL usando Verilog. Los
conceptos del diseño se explican a lo largo de los ejemplos que se van desarrollando. Cada
apunte a la sintaxis, representación de constantes, directivas, etc… se introduce a medida que
van siendo necesarios para el desarrollo del ejemplo. Por todo esto y debido a la estructura de
su contenido, no se puede considerar este tutorial una guía de consulta sino de aprendizaje de
este lenguaje.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17

Vista previa parcial del texto

¡Descarga Tutorial Verilog, aspectos básicos e introducción y más Apuntes en PDF de Microcontroladores solo en Docsity!

T u t o r i a l^ Tutorial Verilog

Este tutorial pretende ser una guía de aprendizaje para el diseño HDL usando Verilog. Los conceptos del diseño se explican a lo largo de los ejemplos que se van desarrollando. Cada apunte a la sintaxis, representación de constantes, directivas, etc… se introduce a medida que van siendo necesarios para el desarrollo del ejemplo. Por todo esto y debido a la estructura de su contenido, no se puede considerar este tutorial una guía de consulta sino de aprendizaje de este lenguaje.

A c e r c a d e l l e n g u a j e

  • 1 INTRODUCCIÓN..............................................................................................................................
    • 1.1 A CERCA DEL LENGUAJE ................................................................................................................
    • 1.2 N IVELES DE ABSTRACCIÓN EN V ERILOG ........................................................................................
  • 2 MI PRIMER DISEÑO .......................................................................................................................
    • 2.1 I NTRODUCCIÓN .............................................................................................................................
    • 2.2 A LGUNAS CONSIDERACIONES ACERCA DEL LENGUAJE ..................................................................
    • 2.3 N ÚMEROS EN V ERILOG .................................................................................................................
    • 2.4 TIPOS DE DATOS ............................................................................................................................
  • 3 PROCESOS ........................................................................................................................................
    • 3.1 A SIGNACIÓN CONTINUA ................................................................................................................
    • 3.2 TEMPORIZACIONES ........................................................................................................................
    • 3.3 EVENTOS .....................................................................................................................................
  • 4 MÓDULOS Y JERARQUÍAS.........................................................................................................
    • 4.1 CONEXIONADO ............................................................................................................................
  • 5 TESTBENCH....................................................................................................................................
    • 5.1 ESTRUCTURA DE UN TESTBENCH .................................................................................................
    • 5.2 MÓDULO TEST .............................................................................................................................
      • 5.2.1 Interfaz de entrada/salida...................................................................................................
      • 5.2.2 Generación de estímulos ....................................................................................................
  • 6 MODELADO DE MEMORIAS EN VERILOG............................................................................
    • 6.1 U SO DE PARÁMETROS ..................................................................................................................
  • 7 OPERADORES EN VERILOG ......................................................................................................
    • 7.1 O PERADORES ARITMÉTICOS ........................................................................................................
    • 7.2 O PERADORES RELACIONALES ......................................................................................................
    • 7.3 O PERADORES DE IGUALDAD ........................................................................................................
    • 7.4 O PERADORES LÓGICOS ................................................................................................................
    • 7.5 O PERADORES BIT A BIT ( BIT- WISE) ..............................................................................................
    • 7.6 O PERADORES DE REDUCCIÓN ......................................................................................................
    • 7.7 O PERADORES DE DESPLAZAMIENTO ............................................................................................
    • 7.8 O PERADOR DE CONCATENACIÓN .................................................................................................
    • 7.9 O PERADOR CONDICIONAL ...........................................................................................................
    • 7.10 P RECEDENCIA DE LOS OPERADORES ............................................................................................
  • 8 ESTRUCTURAS MÁS COMUNES ...............................................................................................
    • 8.1 S ENTENCIAS CONDICIONALES IF – ELSE .......................................................................................
    • 8.2 S ENTENCIA CASE .........................................................................................................................
    • 8.3 S ENTENCIA CASEZ Y CASEX .........................................................................................................
    • 8.4 S ENTENCIAS DE BUCLE ................................................................................................................
      • 8.4.1 Sentencia forever ................................................................................................................
      • 8.4.2 Sentencia repeat .................................................................................................................
      • 8.4.3 Sentencia while...................................................................................................................
      • 8.4.4 Bucle for .............................................................................................................................
  • 9 DIRECTIVAS DE COMPILACIÓN..............................................................................................
    • 9.1 D EFINE ........................................................................................................................................
    • 9.2 I NCLUDE ......................................................................................................................................
    • 9.3 I FDEF – ELSE - ENDIF ...................................................................................................................
    • 9.4 TIMESCALE ..................................................................................................................................
  • 10 FUNCIONES DEL SISTEMA ....................................................................................................
  • 11 TAREAS EN VERILOG..............................................................................................................

A c e r c a d e l l e n g u a j e

1 Introducción

1.1 Acerca del lenguaje

Verilog es un lenguaje de descripción hardware ( Hardware Description Language, HDL ) utilizado para describir sistemas digitales, tales como procesadores, memorias o un simple flip- flop. Esto significa que realmente un lenguaje de descripción hardware puede utilizarse para describir cualquier hardware (digital) a cualquier nivel.

La descripción del sistema puede ser tan sencilla como la de un flip-flop, tal y como se refleja en la Figura 1-1, o un sistema complejo de más de un millón de transistores, tal es el caso de un procesador. Verilog es uno de los estándares HDL disponibles hoy en día en la industria para el diseño hardware. Este lenguaje nos permite la descripción del diseño a diferentes niveles, denominados niveles de abstracción.

DFF

q

q_bar

d

clk

module ff(d,clk,q,q_bar); input d,clk; output q,q_bar;

always @(posedge clk) begin q <= d; q_bar <= !d; end endmodule

ƒ Figura 1-1 Descripción Verilog de un flip-flop.

1.2 Niveles de abstracción en Verilog

Verilog soporta el diseño de un circuito a diferentes niveles de abstracción, entre los que destacan: Nivel de puerta. Corresponde a una descripción a bajo nivel del diseño, también denominada modelo estructural. El diseñador describe el diseño mediante el uso de primitivas lógicas (AND, OR, NOT, etc...), conexiones lógicas y añadiendo las propiedades de tiempo de las diferentes primitivas. Todas las señales son discretas, pudiendo tomar únicamente los valores ‘0’, ‘1’, ‘X’ o ‘Z’ (siendo ‘X’ estado indefinido y ‘Z’ estado de alta impedancia).

La representa la descripción de un multiplexor a nivel de puertas. Este nivel de descripción no resulta ni mucho menos adecuado por lo que no se volverá a tratar a lo largo del presente texto.

Figura 1-

ƒ Figura 1-2 Descripción a nivel de puerta de un multiplexor.

a

b sel

f

g

g

g4 g

module mux(f,a,b,sel); input a,b,sel; output f;

and #5 g1(f1,a,nsel), g2(f2,b,sel); or #5 g3(f,f1,f2); not g4(nsel,sel); endmodule

Nivel de transferencia de registro o nivel RTL. Los diseños descritos a nivel RTL especifican las características de un circuito mediante operaciones y la transferencia de

I n t r o d u c c i ó n

datos entre registros. Mediante el uso de especificaciones de tiempo las operaciones se realizan en instantes determinados. La especificación de un diseño a nivel RTL le confiere la propiedad de diseño sintetizable , por lo que hoy en día una moderna definición de diseño a nivel RTL es todo código sintetizable se denomina código RTL.

La corresponde a la descripción a nivel RTL de un flip-flop. Este nivel de descripción, por la propiedad de ser sintetizable, será el nivel utilizado por excelencia en el diseño HDL.

Figura 1-

ƒ Figura 1-3 Descripción a nivel RTL de un flip-flop.

DFF

q

q_bar

d

clk

module ff(d,clk,q,q_bar); input d,clk; output q,q_bar; reg q,q_bar; always @(posedge clk) begin q <= #1 d; // Retardo de 1 unidad q_bar <= #1 !d; // Retardo de 1 unidad end endmodule

Nivel de comportamiento (Behavioral level )^1. La principal característica de este nivel es su total independencia de la estructura del diseño. El diseñador, más que definir la estructura, define el comportamiento del diseño. En este nivel, el diseño se define mediante algoritmos en paralelo. Cada uno de estos algoritmos consiste en un conjunto de instrucciones que se ejecutan de forma secuencial. La descripción a este nivel pude hacer uso de sentencias o estructuras no sintetizables, y su uso se justifica en la realización de los denominados testbenches (definidos más adelante).

2 Mi primer diseño

2.1 Introducción

La descripción de un diseño en Verilog comienza con la sentencia: module <(definición las señales de interfaz)>;

En segundo lugar se declaran las entradas/salidas: input/output señal;

Seguidamente se describe el módulo/diseño (tarea que veremos más adelante) y se termina la descripción con: endmodule //Notar que a diferencia de las demás sentencias, no se introduce “;”

La Figura 2-1muestra las diferentes partes en la descripción de un diseño.

ƒ Figura 2-1 Descripción del interfaz_._

a

b sel

f

clk en

ejemplo1 module^ ejemplo1(a,b,sel,clk,en,f); //Inputs-Ouputs input a,b,sel,clk,en; output f;

//Descripción del diseño ......

endmodule

(^1) Si bien se define el nivel de comportamiento como un nivel diferente al nivel RTL, hay que decir que éste último se

puede englobar dentro del nivel de comportamiento como una descripción a bajo nivel.

T i p o s d e d a t o s

De los diferentes tipos de registers sólo utilizaremos el tipo reg y el tipo integer (estos últimos solo en la construcción de los testbenches).

La Figura 2-4introduce la definición de los nodos, tanto wire como reg para el ejemplo1.

ƒ Figura 2-4 Definición de las señales de interfaz y nodos internos_._

0 & 0 0

net

net

net1 (^) net4 (^) net dff

a ejemplo

b sel

f

clk en

module ejemplo1(a,b,sel,clk,en,f); //Inputs-Ouputs input a,b,sel,clk,en; output f; wire f; //Descripción de los nodos internos reg net5; wire net1,net2,net3,net4; // Descripción del diseño

endmodule

Las señales de interfaz y los nodos internos se declaran de la siguiente forma: Inputs. El tipo de las señales de entrada NO SE DEFINEN, por defecto se toman como wire. Outputs. Las salidas pueden ser tipo wire o reg , dependiendo si tienen capacidad de almacenamiento de información. OJO, en Verilog, un nodo tipo wire puede atacar a una salida. Nodos internos. Siguen la misma filosofía que las salidas.

No piense el usuario que la declaración de un nodo tipo reg lleva asociado la síntesis del mismo mediante un elemento secuencial, tal y como se observa en la Figura 2-4. La Figura 2- muestra la descripción del ejemplo1 declarando net4 tipo reg. Si observamos el diseño final

vemos que es idéntico. La diferencia está en la forma de definir el código.

0 & 0 0

net

net

net1 (^) net4 (^) net dff

a ejemplo

b sel

f

clk en

module ejemplo1(a,b,sel,clk,en,f); //Inputs-Ouputs input a,b,sel,clk,en; output f; wire f; //Descripción de los nodos internos reg net4,net5; wire net1,net2,net3; // Descripción del diseño

endmodule

ƒ Figura 2-5 Definición de las señales de interfaz y nodos internos.

3 Procesos

El concepto de procesos que se ejecutan en paralelo es una de las características fundamentales del lenguaje, siendo ese uno de los aspectos diferenciales con respecto al lenguaje procedural como el lenguaje C.

Toda descripción de comportamiento en lenguaje Verilog debe declararse dentro de un proceso, aunque existe una excepción que trataremos a lo largo de este apartado. Existen en Verilog dos tipos de procesos, también denominados bloques concurrentes. Initial. Este tipo de proceso se ejecuta una sola vez comenzando su ejecución en tiempo cero. Este proceso NO ES SINTETIZABLE, es decir no se puede utilizar en una descripción RTL. Su uso está íntimamente ligado a la realización del testbecnh.

T i p o s d e d a t o s

Always. Este tipo de proceso se ejecuta continuamente a modo de bucle. Tal y como su nombre indica, se ejecuta siempre. Este proceso es totalmente sintetizable. La ejecución de este proceso está controlada por una temporización (es decir, se ejecuta cada determinado tiempo) o por eventos. En este último caso, si el bloque se ejecuta por más de un evento, al conjunto de eventos se denomina lista sensible. La sintaxis de este proceso es pues: always o <@(lista sensible)>

La Figura 3-1 muestra dos ejemplo de utilización de los procesos initial y always. De estos ejemplos se pueden apuntar las siguientes anotaciones:

initial

begin clk = 0; reset = 0; enable = 0; data = 0; end

always @(a or b or sel) begin //Sobra en este caso if (sel == 1) y = a; else y = b; end //Sobra en este caso

ƒ Figura 3-1 Procesos initial y always.

Begin, end. Si el proceso engloba más de una asignación procedural (=) o más de una estructura de control ( if-else , case , for , etc…), estas deben estar contenidas en un bloque delimitado por begin y end. Initial. Se ejecuta a partir del instante cero y, en el ejemplo, en tiempo 0 (no hay elementos de retardo ni eventos, ya los trataremos), si bien las asignaciones contenidas entre begin y end se ejecutan de forma secuencial comenzando por la primera. En caso de existir varios bloques initial todos ellos se ejecutan de forma concurrente a partir del instante inicial. Always. En el ejemplo, se ejecuta cada vez que se produzcan los eventos variación de la variable a o variación de b o variación de sel (estos tres eventos conforman su lista de sensibilidad) y en tiempo 0. En el ejemplo, el proceso always sólo contiene una estructura de control por lo que los delimitadores begin y end pueden suprimirse.

Todas las asignaciones que se realizan dentro de un proceso initial o always se deben de realizar sobre variables tipo reg y NUNCA sobre nodos tipo wire. La Figura 3-2 muestra un ejemplo de asignación errónea sobre nodos tipo wire en un proceso initial.

wire clk,reset; reg enable,data; initial begin clk = 0; //Error reset = 0; //Error enable = 0; data = 0; end

reg clk,reset; reg enable,data; initial begin clk = 0; reset = 0; enable = 0; data = 0; end

ƒ Figura 3-2 a) Error de asignación de valores a variables tipo wire. B) Código corregido.

En general, la asignación dentro de un proceso initial o always tiene la siguiente sintaxis: variable = f(wire,reg,constante numérica)

La variable puede ser tanto una variable interna como una señal del interfaz del módulo. La asignación puede ser de un nodo tipo wire , de una variable tipo reg , de una constante numérica o una función de todas ellas.

E v e n t o s

3.3 Eventos

La segunda manera de controlar el instante en que se produce una asignación procedural o la ejecución de un proceso always es por el cambio de una variable, denominándose control por eventos. Para ello se emplea el carácter @ seguido del evento.

Se distinguen dos tipos de eventos: Eventos de nivel. Este evento se produce por el cambio de valor de una variable simple o de una lista sensible. Veamos los siguientes ejemplos:

Evento Descripción always @(a) b = b+c;

Cada vez que varía a se evalúa la expresión

always @(a or b or c) d = a+b;

Cada vez que varía a o b o c se evalúa la expresión. En este caso, a, b y c conforman la lista sensible.

Eventos de flanco. Este evento se produce por la combinación de flanco/s de subida y/o bajada de una variable simple o de una lista sensible. Veamos los siguientes ejemplos:

Evento Descripción always @(posedge clk or posedge mr) b <= b+c;

Cada vez que se produce un flanco de subida de clk o de mr se evalúa la expresión always @(posedge clk or negedge mr) b <= b+c;

Cada vez que se produce un flanco de subida de clk o de bajada de mr se evalúa la expresión

4 Módulos y jerarquías

Tal y como se comentó en el aparatado 2.1, el identificador module se utiliza para la definición

de módulos/diseños. Estos módulos pueden utilizarse para construir diseños de mayor complejidad, creando lo que se denomina un diseño con jerarquía. La manera de incluir un módulo en un diseño es: master_name instante_name(port_list);

La muestra un ejemplo de un módulo, denominado muxt , formado por dos módulos, denominados mux , y cuya declaración de interfaz es la que a continuación se muestra:

Figura 4-

ƒ Figura 4-1 Llamada a un módulo.

Module mux(a,b,sl,y); //a, b, out son señales de 8 bits

module muxt(in0,in1,sel,out); input [7:0] in0,in1; input sel; output [7:0] out; wire [7:0] out;

//nodos internas

wire [7:0] y0; //Conexionado por orden mux mux0(in0,in1,sel,y0); //Conexionado por nombre mux mux1(.y(out), .b(in1), .a(y0), .sl(sel)); endmodule

out

in

in

sel

sl

a

b

y

mux

sl

a

b

y

mux

y

mux0 mux

4.1 Conexionado

El conexionado de un módulo dentro de un diseño se puede realizar de dos formas: por orden (conexión implícita) o por nombre (conexión explícita).

E s t r u c t u r a d e u n t e s t b e n c h

En el conexionado por orden, utilizado en mux0 en el ejemplo anterior, las señales utilizadas en la llamada al bloque se asignan a las señales internas por orden. En ese caso, si se tiene en cuenta la declaración del módulo: module mux(a,b,sl,y); //a, b, out son señales de 8 bits

y la llamada al mismo: mux mux0(in0,in1,sel,y0);

se producen la siguientes asignaciones: in0 Æ a in1 Æ b sl Æ sel y Æ y

En el conexionado por nombre, utilizado en mux1 en el ejemplo anterior, se debe especificar, además de la señal, el puerto al que va conectado siguiendo la siguiente sintaxis: .(puerto) señal

5 Testbench

El propósito de un testbench no es otro que verificar el correcto funcionamiento de un módulo/diseño. La escritura de un testbench es casi tan compleja como la realización en RTL del módulo a verificar, a partid de ahora DUT ( Desing Under Test ). Una de las ventajas que presenta la escritura de un testbench es la posibilidad de no tener que ser sintetizable y, por tanto RTL.

Para escribir un testbench el diseñador debe tener siempre presente las especificaciones de diseño, en la que quedan reflejadas las funciones del diseño y, por tanto, las funciones a verificar.

5.1 Estructura de un testbench

La estructura de un testbench es la que se refleja en la Figura 5-1. Se compone de: Módulo dut : Diseño a verificar Módulo test : Módulo generador/analizador. Este módulo es el encargado de generar las señales de entrada al módulo dut y de analizar sus salidas. Módulo tb : Este módulo incluye los módulos anteriores. Se caracteriza por no tener entradas ni salidas. Corresponde a una declaración estructural del conexionado de los módulos dut y test. En el ejemplo de la se ha incluido un proceso ( initial ) cuya única finalidad es la de abrir una base de datos con las formas de ondas del testbench.

Figura 5-

Figura 5-

5.2 Módulo test

El módulo test será el encargado de proporcionar los estímulos de entrada al dut y de analizar sus salidas. Su realización se hace a nivel de comportamiento (behavioral) y no necesariamente utilizando código RTL. Tal y como se indicó anteriormente, la realización de este módulo implica el conocer en detalle el diseño a verificar. En este apartado se realizará la verificación del contador, denominado cnt , que se muestra en la , por lo que en primer lugar se ha de conocer las especificaciones de este módulo.

Las especificaciones del módulo cnt son: Funcionamiento general. Se trata de un contador de 8 bits con señal de habilitación de contaje ( enable ) y señal de carga ( load ). El contador no es cíclico, por lo que al llegar al valor 8’HFF debe detenerse. Señal de reset. Cuando se activa se produce el reset asíncrono del contador a 0. Señal de enable. El contador realiza el contaje cuando la señal de enable está activa. En caso contrario el contaje queda detenido. Señal de load. La señal de load habilita la carga del contaje inicial, presente en din. Esta señal no tiene efecto si el contaje está habilitado. Una vez cargado, el contador debe comenzar el contaje con el valor cargado.

M ó d u l o t e s t

Señal de reset (asíncrona). La muestra la generación de una señal de reset de forma asíncrona. Esta señal se inicializa a ‘0’ en tiempo 0. Después de 35 unidades de tiempo se activa a ‘1’ y tras 50 unidades de tiempo, respecto al último evento, se pone de nuevo a ‘0’.

Figura 5-

ƒ Figura 5-3 Generación de la señal de reset (asíncrona).

initial begin reset = 1’b0;

reset = 1’b1;

reset = 1’b end

reset

t=0 t=35 t=

Señal de reset (síncrona). La muestra la generación de la señal de reset de forma síncrona. Hay que destacar que la activación/desactivación de esta señal se controla mediante eventos de, en este caso, de la señal de reloj. Tras su inicialización, se activa después de dos flancos de reloj y con un retardo de una unidad de tiempo. Se desactiva al siguiente flanco de reloj.

Figura 5-

ƒ Figura 5-4 Generación de la señal de reset (síncrona).

initial begin reset = 1’b0; repeat(2) @(posedge clk) #1; reset = 1’b1; @(posedge clk) #1; reset = 1’b0; end

reset

t=

1

clk

1

Señal de reloj. La señal de reloj, por sus características, se genera usando otro tipo de procesos, generalmente always. La muestra la generación de una señal de reloj de 5 unidades de tiempo de semiperiodo. Hacer notar que para que la señal de reloj se genere de forma correcta hay que inicializar la variable clk a cero.

Figura 5-

ƒ Figura 5-5 Generación de la señal de reloj.

define SPER 5 ... always #SPER clk = !clk; initial begin clk = 1’b end

t=

clk

t=5 t=10 t=15 t=20 t=

Señales de control/datos. Al igual que ocurría con el reset, estas señales pueden ser asíncronas o síncronas. En este último caso habrá que tener en cuenta la señal de reloj para generarlas. La muestra un test para el contador que estamos desarrollando.

Figura 5-

Hay que destacar como en el módulo de test presentado existen dos procesos que se ejecutan en paralelo. El primero de ellos corresponde al always para la generación de la señal de reloj. El segundo corresponde al bloque initial. Debido a la existencia de un bloque always y para poder parar la simulación se hace necesario el uso del comando $finish que, al ejecutarse, para la simulación.

M ó d u l o t e s t

//Señal de reloj always #`SPER clk = !clk; //Reset, señales de control y datos initial begin

reset = 1’b0;

reset = 1’b1; en = 1’b0; ld = 1’b0; din = 8’b0;

reset = 1’b

//Enable count @(posedge) clk) #1; en = 1’b1; //Dejar 30 ciclos contando repeat(30) @(posedge) clk) #1; //Deshabilitar contaje durante 10 ciclos

en = 1’b0; repeat(10) @(posedge) clk) #1; //Volvemos a habilitar contaje @(posedge) clk) #1; en = 1’b1; //Habilitamos carga de nuevo dato @(posedge) clk) #1; ld = 1’b1; din = 8’h4A; @(posedge) clk) #1; ld = 1’b0; //Esperamos 10 ciclos de reloj y repetimos la operación //deshabilitando el contaje @(posedge) clk) #1; en = 1’b0; ld = 1’b1; din = 8’hF0; @(posedge) clk) #1; en = 1’b1; //Habilitamos 30 ciclos de reloj y finalizamos repeat(30) @(posedge) clk) #1; $finish; end

ƒ Figura 5-6 Test del contador cnt.

6 Modelado de memorias en Verilog

Con la intención de facilitar el modelado de memorias, Verilog acepta la declaración de arrays de dos dimensiones. En Verilog las memorias se modelan mediante arrays de registros. Cualquier palabra de la memoria puede ser accedida mediante un índice. El acceso a un determinado bit de una palabra se realiza mediante la declaración de una variable temporal. La sintaxis de la declaración es: reg [wordsize:0] array_name[arraysize:0]

O p e r a d o r e s r e l a c i o n a l e s

“-“ a = b – c; “” a = b * c; “/” a = b / c; Resultado: Se devuelve la parte entera de la división “%” a = b % c; Resultado: Se devuelve el módulo de la división El resultado del módulo toma el signo del primer operando. Si algún bit del operando tiene el valor “x”, el resultado completo es “x”. Los números negativos se representan en complemento a 2.

7.2 Operadores relacionales

“<” a < b a es menor que b “>“ a > b a es mayor que b “<=” a <= b a es menor o igual que b “>=“ a >= b a es mayor o igual que b El resultado que se devuelve es: 0 si la condición no se cumple 1 si la condición se cumple x si alguno de los operandos tiene algún bit a “x”

7.3 Operadores de igualdad

“==” a == b a es igual a b “!=“ a != b a es diferente de b “===” a === b a es igual a b, incluyendo “x” y “z” “!==“ a !== b a es diferente a b, incluyendo “x” y “z” Los operandos se comparan bit a bit, rellenando con ceros para ajustar el tamaño en caso de que no sean de igual ancho. Estas expresiones se utilizan en condicionales. El resultado es: 0 si se cumple la igualdad 1 si no se cumple la igualdad x únicamente en las igualdades “==” o “!=” si algún operando contiene algún bit a “x” o “z”

7.4 Operadores lógicos

“!” negación lógica “&&“ AND lógica “||” OR lógica Las expresiones con “&&” o “||” se evalúan de izquierda a derecha. Estas expresiones se utilizan en condicionales. El resultado es: 0 si la relación es falsa 1 si la relación es verdadera x si algún operando contiene algún bit a “x” o “z”

7.5 Operadores bit a bit (bit-wise)

“~” negación “& “ AND “|” OR “^“ OR exclusiva Los citados operadores pueden combinarse obteniendo el resto de operaciones, tales como ~& (AND negada), ~^ (OR exclusiva negada), etc… El cálculo incluye los bits desconocidos (x) en la siguiente manera: ~x = x 0&x = 0 1&x = x&x = x 1|x = 1 0|x = x|x = x 0^x = 1^x = x^x = x

7.6 Operadores de reducción

“&” AND Ejemplo: &a Devuelve la AND de todos los bits de a

O p e r a d o r e s d e d e s p l a z a m i e n t o

“~&“ AND negada Igual que el anterior “|” OR Ejemplo: |a Devuelve la OR de todos los bits de a “~|“ OR negada Igual que el anterior “^” OR exclusiva Ejemplo: ^a Devuelve la OR exclusiva de todos los bits de a “~^“ OR exclusiva negada Igual que el anterior Estos operadores de reducción realizan las operaciones bit a bit sobre un solo operando. Las operaciones negadas operan como AND, OR o EXOR pero con el resultado negado.

7.7 Operadores de desplazamiento

“<<” Desplazamiento a izquierda Ejemplo: a = b << 2; “>>“ Desplazamiento a derecha Ejemplo: a = b >> 2; Notas: Los bits desplazados se rellenan con ceros.

7.8 Operador de concatenación

“{}” Concatenación de operandos. Los operandos se separan por comas Ejemplos: {a,b[3:0],c} Si a y c son de 8 bits, el resultado es de 20 bits {3{a}} Es equivalente a {a,a,a} {b,3{c,d}} Es equivalente a {b,c,d,c,d,c,d} Nota: No se permite la concatenación con constantes sin tamaño.

7.9 Operador condicional

“?” El formato de uso de dicho operador es (condición)? trae_expr : false_expr Ejemplos: out = (enable)? a : b; La salida out toma el valor de a si enable está a 1, en caso contrario toma el valor de b

7.10 Precedencia de los operadores

El orden de precedencia de los diferentes operadores es el siguiente:

Operador Símbolo Unary, Multiplicación, División, Módulo +,-,*,% Suma, Resta, Desplazamientos +,-,<<,>> Relación, Igualdad <,>,<=,>=,==,!=,===,!=== Reducción &,!&,^,~^,|,~| Lógicos &&,|| Condicional ?:

ƒ Figura 7-1 Orden de precedencia de los operadores en Verilog.

8 Estructuras más comunes

En este apartado se presentan las estructuras más comunes para la descripción de comportamiento en Verilog. A continuación se presentan cada una de ellas por separado indicando, además de un ejemplo, si son sintetizables o no.

8.1 Sentencias condicionales if – else

La sentencia condicional if – else controla la ejecución de otras sentencias y/o asignaciones (estas últimas siempre procedurales). El uso de múltiples sentencias o asignaciones requiere el uso de begin – end. La sintaxis de la expresión es:

if (condición) //Condición simple sentencias; if (condición) //Condición doble sentencias; else sentencias;

if (condición1) // Múltiples condiciones sentencias; else if (condición2)

S e n t e n c i a c a s e z y c a s e x

8.3 Sentencia casez y casex

Estas sentencias corresponden a versiones especiales del case y cuya particularidad radica en que los valores lógicos z y x se tratan como valores indiferentes. casez : usa el valor lógico z como valor indiferente casex : toma como indiferentes tanto el valor z como el valor lógico x La Figura 8-3 muestra un ejemplo de uso de casez.

casez (opcode) 4’b1zzz: out = a; // Esta sentencia se ejecuta siempre que el bit más significativo sea 1. 4’b01??: out = b; // El símbolo? siempre se considera como “indiferente”, luego en este caso es equivalente a poner 4’b01zz 4’b001?: out = c; default: $display(“Error en el opcode”); endcase

ƒ Figura 8-3 Ejemplo de uso de casez.

8.4 Sentencias de bucle

Todas las sentencias de bucles en Verilog deben estar contenidas en bloques procedurales ( initial o always ). Verilog soporta cuatro sentencias de bucles.

8.4.1 Sentencia forever

El bucle forever se ejecuta de forma continua, sin condición de finalización. Su sintaxis es: forever

En caso de englobar mas de una sentencia o asignación, éstas se deben incluir entre begin – end.

initial begin clk = 0; forever #5 clk = !clk; end

ƒ Figura 8-4 Ejemplo de uso de forever.

8.4.2 Sentencia repeat

El bucle repeat se ejecuta un determinado número de veces, siendo este número su condición de finalización. Su sintaxis es: repeat ()

En caso de englobar mas de una sentencia o asignación, éstas se deben incluir entre begin – end.

if (opcode == 10) //Realización de una operación de rotación repeat (8) begin temp = data[7]; data = {data <<1,temp}; end

ƒ Figura 8-5 Ejemplo de uso de repeat.

8.4.3 Sentencia while

El bucle while se ejecuta mientras la condición que evalúa sea cierta. La condición que se especifica expresa la condición de ejecución del bucle. Su sintaxis es: while ()

D e f i n e

En caso de englobar mas de una sentencia o asignación, éstas se deben incluir entre begin – end.

loc = 0; if (data = 0)) //Ejemplo de cálculo del bit más significativo loc = 32; else while (data[0] == 1’b0) begin loc = loc + 1; data = data >> 1;

end

ƒ Figura 8-6 Ejemplo de uso de while.

8.4.4 Bucle for

El bucle for es similar a aquellos utilizados en los lenguajes de programación. Su sintaxis es: for (,, )

En caso de englobar mas de una sentencia o asignación, éstas se deben incluir entre begin – end.

for (i=0, i<64, i=i+1)) //Inicialización de memoria RAM

ram[i] = 0;

ƒ Figura 8-7 Ejemplo de uso de for.

9 Directivas de compilación

Verilog ofrece una serie de directivas de compilación que permiten, entre otras cosas, obtener diferentes códigos a partir de una única descripción. A continuación se detallan las más comunes. La sintaxis para la definición de una directiva es: `directiva

9.1 Define

La directiva define permite definir un valor. Ejemplo:

`define TD 1 ....

assign #`TD q = data_out;

ƒ Figura 9-1 Ejemplo de definición y uso de la directiva define.

9.2 Include

La directiva define permite incluir un fichero. En este caso, el fichero a incluir puede contener, por ejemplo, la definición de otros módulos.

`include “modulos.v”

....

ƒ Figura 9-2 Ejemplo de definición de la directiva include.

9.3 Ifdef – else - endif

La directiva ifdef permite compilar un código siempre y cuando se haya definido el símbolo al que hace referencia.

`define SUMA ...