









Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Prepara tus exámenes
Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Prepara tus exámenes con los documentos que comparten otros estudiantes como tú en Docsity
Encuentra los documentos específicos para los exámenes de tu universidad
Estudia con lecciones y exámenes resueltos basados en los programas académicos de las mejores universidades
Responde a preguntas de exámenes reales y pon a prueba tu preparación
Consigue puntos base para descargar
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Comunidad
Pide ayuda a la comunidad y resuelve tus dudas de estudio
Ebooks gratuitos
Descarga nuestras guías gratuitas sobre técnicas de estudio, métodos para controlar la ansiedad y consejos para la tesis preparadas por los tutores de Docsity
Breve introduccion a verilog y systemverilog
Tipo: Apuntes
1 / 16
Esta página no es visible en la vista previa
¡No te pierdas las partes importantes!










Departamento de Electr´onica, Universidad T´ecnica Federico Santa Mar´ıa, Av. Espa˜na 1680, [email protected]
Abstract Este tutorial est´a orientado a convertirse en un primer material de estudio al lenguaje Verilog que se usar´a durante el dictado del Laboratorio de Sistemas Digitales (ELO-212). El mismo ofrece una introducci´on sencilla a Verilog, mostrando sus caracter´ısticas m´as importantes. Este material re´une desarrollos personales como as´ı tambi´en lo hecho por otros autores. En m´erito de ello, las siguientes son las fuentes consultadas para elaborar este material de estudio. http://numato.com/learning-fpga-and-verilog-a-beginners-guide-part-1-introduction http://www.see.ed.ac.uk/~gerard/Teach/Verilog/manual/Intro/verilog.html (RECOMENDADO) http://www.see.ed.ac.uk/~gerard/Teach/Verilog/mjta/Gateway/html/delays.html http://ramos.elo.utfsm.cl/~elo212/docs/lsilva-ap5.pdf (Apunte Prof. Silva) http://ramos.elo.utfsm.cl/~elo212/docs/verilog-lrm.pdf (manual-RECOMENDADO) http://ramos.elo.utfsm.cl/~elo212/docs/verilog-chavez.pdf http://www.verilogtutorial.info/ http://www.ece.umd.edu/courses/enee359a/verilog_tutorial.pdf (RECOMENDADO) http://www.iuma.ulpgc.es/~nunez/clases-FdC/verilog/Verilog%20Tutorial%20v1.pdf (RECOMENDADO) http://www.doe.carleton.ca/~jknight/97.478/PetervrlK.pdf http://cva.stanford.edu/people/davidbbs/classes/ee108a/... ...winter0607%20labs/ee108a_nham_intro_to_verilog.pdf ALTAMENTE RECOMENDADO
Palabras clave: Verilog, sistemas digitales, FPGA, VHDL/HDL
Aprender electr´onica requiere paciencia, voluntad y, por supuesto, ganas de aprender. En el transcurso de mis aulas y de mi propia investigaci´on e interacci´on con mis estudiantes y ayudantes, he podido observar de primera mano como, cuando queremos aprender electr´onica, preferimos agarrar los componentes antes de estudiarlos, implementar antes que dise˜nar y luego ver con tristeza como nuestros proyectos no funcionan. Ergo, la intuici´on falla y no somos disen˜adores por default. Todo camino, todo proyecto,
sigue una l´ogica, y en este laboratorio se van a iniciar de primera mano en esa experiencia que los acompa˜nar´a por el resto de su profesi´on: la de dise˜nar, implementar y programar, todo en un mismo hardware. Una FPGA, por sus siglas en ing´es de Field Programmable Gate Array, se puede interpretar como un gran arreglo de compuertas que pueden ser programadas y reconfiguradas. Estas compuertas pueden ser interconectadas arbitrariamente durante la implementaci´on de nuestro circuito digital. Actualmente, Xilinx, Altera y Actel, son algunas de la compa˜n´ıas que comercializan FPGA’s. La figura 1 muestra la imagen de una FPGA construida por Xilinx. Observen que cuando hablo de FPGA’s, no me refiero al chip solamente, sino a todo el contexto que rodea al mismo (la placa o kit), aunque la FPGA, per se, es el chip.
Figure 1: Ejemplo de FPGA (http://www.robotshop.com/eu/digilent-atlys-spartan-6-fpga- development-kit.html).
Verilog es un lenguaje de descripci´on de hardware (HDL, por sus siglas en ing´es de Hardware Description Language), el cual puede ser usado para describir de forma textual, circuitos digitales. Es decir, nuestra FPGA se programa. Para programarla, usamos un c´odigo. Ese c´odigo (hasta esta altura de sus estudios) ser´a Verilog. As´ı, Verilog es un lenguaje, tal como lo es C o Python. Antes de usar lenguajes tipo HDL, los ingenieros hac´ıan sus disen˜os usando esquemas (esquem´aticos de compuertas l´ogicas). Si bien parece f´acil, pensemos lo siguiente: qu´e pasar´ıa si necesitamos disen˜ar un circuito que requiera 1000 compueras? o 10000? A esta altura parecer´ıa improbable que un circuito pudiera requerir tantas compuertas, pero ya ver´an en este ramo, que no todos los circuitos l´ogicos est´an compuestos solamente con compuertas. Resumiendo, la FPGA es nuestro hardware, y el lenguaje que nos permitir´a programarla es Verilog.
Figure 2: Bloque module gen´erico.
A continuaci´on, el c´odigo gen´erico de un bloque module.
module <nombre_modulo>(<lista_entrada>, <lista_salida>); //(1) input <lista_entrada>; //(2)
output <lista_salida>; //(3) . . . endmodule //(4)
Explicaci´on– La primera l´ınea comienza declarando que el bloque que estamos escribiendo es uno del tipo module, seguido por el nombre del mismo. Entre par´entesis tenemos, en ese orden, los par´ametros de entrada y los par´ametros de salida, bajo el nombre de listas. Una lista, puede ser vista como una enumeraci´on de par´ametros. Observen que terminamos la primera l´ınea de c´odigo con un punto y coma. Esto, es obligatorio en nuestros bloques del tipo module. La enumeraci´on de los par´ametros del bloque module, es simplemente una enumeraci´on. Si bien colocamos los par´ametros de entrada primero y luego los de salida, debemos declarar esta situaci´on, de forma expl´ıcita, en el c´odigo. As´ı, la segunda l´ınea de nuestro c´odigo, declara como input –es decir, como entradas de nuestro bloque– a todos los par´ametros de nuestra lista entrada. La l´ınea tres, declara expl´ıcitamente los par´ametros de la lista salida, como salidas efectivas de nuestro bloque (output). Recuerden que en Verilog dise˜namos hardware y no software, por lo tanto, input y output, generan hardware de entrada y hardware de salida respectivamente. Debido a ello, las listas de entrada y de salida ser´an llamadas de ahora en m´as como puertos. Finalmente, nuestro bloque termina con la sentencia endmodule. Esta ´ultima sentencia no lleva punto y coma, a diferencia de las restantes. Ahora, c´omo se relaciona el c´odigo de arriba con la Fig. 2? Abajo, se muestra el c´odigo correspon- diente a nuestro bloque Lab Sist Dig.
module Lab_Sist_Dig(A, B, C, clock, M, N); //(1) input [7:0] A, B; //(2) input [3:0] C; //(3) input clock; //(4) output [7:0] M; //(5) output N; //(6) . . . endmodule //(7)
Observen lo siguiente:
Lab_Sist_Dig Laboratorio(.A(X1), .B(X2), .C(X3), .clock(X4), .M(Y1), .N(Y2));
De esta manera, como lo pusimos arriba, podemos cambiar el orden de los puertos, pero al momento de invocar el m´odulo (instanciate en ingl´es), los par´ametros pasar´an apropiadamente. As´ı, el c´odigo de abajo producir´ıa el mismo resultado que el anterior:
Lab_Sist_Dig Laboratorio(.A(X1), .B(X2), .clock(X4), .M(Y1), .N(Y2), .C(X3));
En la escritura del c´odigo, tambi´en es posible agregar comentarios. Les recomiendo el uso de los mismos para permitir mayor claridad y versatilidad a sus desarrollos. Hay dos formas de comentar c´odigo, tal como se muestra abajo:
// las dos barras comentan la linea donde ellas fueron colocadas /* Abre un ambiente de comentarios. Este sistema permite comentar muchas lineas a la vez. El ambiente se cierra con */
Muchos bloques module pueden (y podr´an) contener literales num´ericos. En Verilog, los literales num´ericos son n´umeros del tipo unsigned (sin signo) de 32 bits (por default). Abajo, podemos ver un ejemplo de c´omo definir literales num´ericos.
/Sintaxis general:
wire [2:0] a = 3’b111; //es un numero binario de tres bits wire [4:0] b = 5’d31; //es un numero decimal de 5 bits wire [31:0] c = 32’hdeadbeef //es un numero hexadecimal de 32 bits
Prestemos atenci´on al c´odigo arriba:
Como todo lenguaje de programaci´on, Verilog permite definir constantes en nuestro c´odigo. Para ello, Verilog usa el acento invertido. El c´odigo de abajo muestra un ejemplo de c´omo declarar constantes, que pueden ser usadas durante todo nuestro programa. El tipo de constantes mostradas abajo, se definen fuera del bloque module y pueden ser usadas por cualquier otro m´odulo de nuestro c´odigo.
‘define RED 2’b00 //se define una constante llamada RED, de dos bits (ambos cero) ‘define WHITE 2’b01 //idem, pero de valores diferentes ‘define BLUE 2’b10 //idem //Observar que no hemos usado ";" para separar constantes //la directiva ‘define permite declarar constantes
wire [1:0] color1 = ‘RED; wire [1:0] color2 = ‘WHITE; wire [1:0] color3 = ‘BLUE;
Observen lo siguiente: en el c´odigo de arriba, hemos declarado a color1, como una variable tipo wire (que en este caso es un bus de dos cables), donde los valores de color1, son dados por la constante RED. Tengan en cuenta tambi´en que, para que la asignaci´on de valor sea efectiva, RED, WHITE o BLUE deben estar precedidos por el acento inverso. Cabe destacar que la utilidad de definir variables es para que el programador no se confunda: son ayudas para hacer de su tarea de programaci´on algo mas f´acil. Para quien lea su c´odigo, leer que color1 es RED es m´as claro que leer 2’b00.
Hasta ahora hemos llamado como par´ametros o puertos, a los tipos de datos dentro de un bloque module. En esta subsecci´on –y haciendo uso apropiado del vocabulario– vamos a declarar dos tipos de datos en nuestros m´odulos: wire y register –tambi´en llamados net–, los cuales representan las conecciones internas del circuito asociado a la Fig. 2.
Finalmente, podemos usar la siguiente expresi´on para declarar y asignar (al mismo tiempo) un tipo de dato wire:
wire primer_wire = 1’b0; //se declara y se asigna el valor 0
El otro tipo de dato usado en Verilog es el register, el cual a pesar de su nombre, no implica memoria. Las variables tipo register usualmente denotan variables que est´an del lado izquierdo de un bloque del tipo always (que se ver´a m´as adelante) y en los bloques initial y forever usados solamente en simulaci´on. Declaramos las variables tal como se declara un wire –al inicio de un bloque module–, pero solamente las usamos dentro de un bloque always.
Los bloques always son bloques cuyo comportamiento consiste en funcionar repetidamente (siempre est´a funcionando) de acuerdo a una lista de sensibilidad. Esta lista de sensibilidad es un conjunto de par´ametros (puertos, variables,...). Cuando un par´ametro de la lista de sensibilidad cambia su valor, las sentencias en el bloque always cambiar´an su valor (en un simulador, esto ocurrir´a de manera secuencial). En un bloque always, solo podemos tener variables tipo register en la parte izquierda de cualquier sentencia. Por ejemplo, veamos el siguiente c´odigo:
module bitwise_not(V_in, V_out); input [7:0] V_in; output [7:0] V_out;
reg [7:0] V_out; //declaramos V_out como register
always @(V_in) begin //no lleva ; al final de begin V_out = ~V_in; //asignamos a V_out el negativo de V_in end
endmodule
Observando el c´odigo de arriba, podemos ver que V out se declara como tipo register, pues ser´a usado como parte izquierda dentro del bloque always. Dicho bloque, se lo declara de la siguiente manera: always-espacio-@(< listadesensibilidad >)-espacio-begin, y termina con un end. Adem´as, la negaci´on binaria (tambi´en conocida como complemento a uno, se realiza con el operador ∼. La lista de sensibilidad del ejemplo anterior, est´a compuesta por V in. Si hubieren m´as elementos, se deben separar por operador or –en principio solamente–. S´olo si V in cambia, el c´odigo dentro del bloque always ser´a evaluado.
Como en muchos otros lenguajes, Verilog nos permite generar sentencias del tipo if-else y select-case, las cuales se vuelven de mucha utilidad cuando tenemos que dise˜nar circuitos cuyos comportamientos obedezcan a varias condiciones. A continuaci´on, se muestra un ejemplo:
‘define DOMINGO 3’b ‘define LUNES 3’b ‘define MARTES 3’b ‘define MIERCOLES 3’b ‘define JUEVES 3’b ‘define VIERNES 3’b ‘define SABADO 3’b
module alarma_reloj(dia, hora, minuto}; input [2:0] dia; //es una entrada de tres bits output [4:0] hora; //es una salida de cinco bits output [5:0] minuto; //es una salida de 6 bits
wire [2:0] dia; reg [4:0] hora;//es reg pues estara en un always reg [5:0] minuto; //es reg pues estara en un always
wire semanaDia; //wire usado como variable auxiliar assign semanaDia = (dia <= ‘VIERNES); /Esto significa: si dia es menor o igual a 101, entonces semanaDia es verdadero (1), caso contrario, es falso (0)/
always @(*) begin if (semanaDia) begin hora = 5’d8; minuto = 6’d30; end else begin case (dia) ‘SABADO: {hora,minuto} = {5’d11,6’d15}; //concatenamos la asignacion ‘DOMINGO: {hora,minuto} = {5’d12,6’d45}; default: {hora,minuto} = 11’d0; endcase
always @* begin case (operacion) ‘ADD: resultado = operadorA + operadorB; //suma ‘LESS: resultado = operadorA < operadorB; //es 1 si es verdadero, sino, es 0 ‘EQ: resultado = operadorA == operadorB; //es 1 si es verdadero, sino, es 0 ‘OR: resultado = operadorA | operadorB; //idem ‘AND: resultado = operadorA & operadorB;//idem ‘NOT: resultado = ~operadorA; default: resultado = 0; //vale 0 endcase end
endmodule
Viendo el c´odigo de arriba, podemos determinar los operadores add (+), less than (<), equal (==), or (|), and (&) y not (∼) usados por Verilog. Para invocar el m´odulo ALU desde cualquier otro m´odulo, usamos el s´ımbolo #() dentro de la l´ınea de invocaci´on para modificar su parameter N. Por ejemplo, si en vez de usar una ALU de 32 bits como en el ejemplo anterior, quisieramos una ALU de 16 bits, podr´ıamos escribir:
ALU #(16) alu1(...)
Donde #(16), implica que el par´ametro N tomar´a el valor 16 (si no fuera invocado as´ı, toma el valor 32 por default, seg´un lo escrito en el c´odigo arriba). La etiqueta alu1 es solo figurativa y no tiene mayor importancia en el hardware que dise˜namos. Es una costumbre sana de programaci´on, poner siempre una etiqueta. Adem´as, un par´ametro s´olo debiese ser utilizado dentro del m´odulo donde es declarado.
Generalmente, una vez que hemos programado (o escrito nuestro c´odigo), queremos probarlo en el hardware (mapear nuestro c´odigo en la FPGA). A pesar de nuestro entusiasmo por hacerlo, debemos tener algunos cuidados. Uno de ellos, es la integridad de la FPGA y su vida ´util. Por lo tanto, no podemos mapear nuestro c´odigo en la FPGA millones de veces. Hasta este punto parece il´ogico que sean tantas veces, pero pensemos lo siguiente: si en vez de estar desarrollando una experiencia de nuestro labotario, est´an probando o dise˜nando un robot m´ovil que tiene incorporado como controlador de bajo nivel una FPGA, cada vez que Uds. sinteticen y mapeen su c´odigo en la FPGA, van a querer probarlo para ver si funciona correctamente. Esto implica: encender el robot (consumir sus recursos), disponer de espacio de pruebas y maniobras (consumir recursos); y si adem´as las pruebas salen mal, deben hacer todo
otra vez (consumir recursos). Peor, el robot podr´ıa estrellarse y destruirse (m´as recursos consumidos). Entonces, ¿c´omo debemos proceder? Primero, simulamos. Una vez que han escrito su c´odigo, se debe desarrollar lo que se conoce como testbench, o simplemente test de su c´odigo. Un testbench es un c´odigo aparte (cuando veamos el software que utilizaremos en el curso, les ense˜naremos a hacer testbenches) que invoca a nuestro bloque module (el cual queremos testar). Un testbench NO genera nuevo hardware, sino que es simplemente una forma de simular el comportamiento de nuestro bloque module. Para ello, nuestro testbench debe invocar nuestro m´odulo generando todos los posibles valores de entrada (input) que nuestro m´odulo acepta. Para ver si nuestro c´odigo funciona de acuerdo a nuestras necesidades, monitoreamos las salidas output de nuestro bloque module. Debido a que un testbench no es sintetizable, tenemos m´as maniobrabilidad de c´odigo, y podemos simular algunos eventos que ser´an de suma utilidad para ver si nuestro c´odigo funciona correctamente.
3.10.1 Sentencias delay
Es muy diferente hablar de simulaci´on que de hardware. Cuando creamos un testbench, queremos que las se˜nales que aplicaremos (o est´ımulos) sigan un order determinado. En el hardware, todo el proceso es concurrente. Ahora, simulamos el hardware mediante un programa –secuencial–. Para lograr esto, podemos usar delays. Estos delays, lo que hacen es retardar alg´un evento. Este retardo, se mide en unidades de tiempo. La FPGA que usaremos, tiene un oscilador que le otorga la frecuencia de funcionamiento. Cada per´ıodo de oscilaci´on, es nuestra unidad de tiempo. A menos que se diga lo contrario, no haremos especificaciones, por ahora, acerca de dicha unidad de tiempo. Asumamos entonces que medimos el tiempo por ciclos de reloj. Las sentencias delay se basan en ese concepto. Veamos por ejemplo el siguiente c´odigo:
//Sintaxis general de un delay: #
#5; // ; al final. Es un retardo de 5 ciclos #1000; //es un retardo de 1000 ciclos
#10 $display("ELO 212");
En el c´odigo de arriba, todo se ejecuta de manera secuencial. As´ı, primero tenemos una pausa de 5 ciclos. Al final de esos cinco ciclos, tenemos una nueva pausa de 1000 ciclos; al final de esos 1000+5=1005 ciclos, tenemos una nueva pausa de 10 ciclos. Luego del ciclo n´umero 1015, se ejecuta la sentencia $display(”ELO 212”). Esta sentencia muestra en pantalla la frase ELO 212. Lo que coloquemos entre comillas, es lo que se muestra. Como vemos, todos sucede de manera secuencial.
http://www.doe.carleton.ca/~jknight/97.478/PetervrlK.pdf http://cva.stanford.edu/people/davidbbs/classes/ee108a/... ...winter0607%20labs/ee108a_nham_intro_to_verilog.pdf ALTAMENTE RECOMENDADO
Ir´e puliendo este tutorial a medida que reciba sus feedbacks. Quisiera insistir en el hecho de que lo aprendido en este tutorial, permitir´a programar usando Ver- ilog. Debido a que usamos los productos de Xilinx, pienso que los conceptos aqui aprendidos quedar´an fijos una vez que hayan le´ıdo el tutorial sobre el uso de Xilinx que he preparado.
Profs. Mauricio Sol´ıs y Alejandro Alvi˜na por sus sugerencias. Fabi´an Rubilar por sus sugerencias.