Introducción al Icarus Verilog en Windows

⚠️ Nota importante

Este artículo tiene más de un año. La tecnología evoluciona rápido, por lo que algunos contenidos o instrucciones pueden estar desactualizados. Recuerda buscar información reciente y actualizada.

Basado en el artículo Getting started with Icarus Verilog on Windows de codeitdown.com

Icarus Verilog es un compilador Verilog bajo estándar IEEE-1364 que tiene como meta usuarios Linux pero funciona casi tan bien en Windows. Es liviano, gratuito e incluye una máquina virtual que simula el diseño. Este tutorial incluye el proceso de descarga, instalación y utilización del Icarus Verilog para escribir un programa simple, compilarlo, simularlo y dar un vistazo a los resultados de esta simulación diagrama de temporización. No es necesario un conocimiento previo en Verilog, pero es recomendada experiencia previa en programación.

Instalando Icarus Verilog

Descargue la última versión estable del programa en: http://bleyer.org/icarus/

Instalar Verilog es tan fácil como instalar cualquier programa en Windows. Solo siga las indicaciones asegurándose de marcar la casilla de GTK Wave (Instalación completa) y "Add Executables to Windows Path". En este momento debería poder usar la línea de comandos. En Windows 7/8 oprima la tecla "Windows" y escriba "cmd" para abrir el símbolo del sistema. Solo digite "iverilog" y debería recibir un mensaje diciendo: “iverilog: no source files” y algunas instrucciones. Digite “gtkwave” y la interfaz gráfica de usuario se abrirá. Este programa es usado para visualizar los resultados de simulación gráficamente en un diagrama de tiempo.

Si estos comandos no funcionan, pero la instalación fue exitosa, es posible que los ejecutables no fueran agregados a la ruta de Windows. Deberá realizar este proceso manualemnte.

Escribiendo un programa sencillo.

Ahora, usted está preparado para escribir el primer programa. Para este tutorial, vamos a esribir una descripción del Flip Flop tipo D que es un módulo de que trabaja como un "D flip-flop". Al mismo tiempo aprenderá algunos conceptos básicos de Verilog.También escribirá un módulo de prueba para reproducir el siguiente diagrama:

fftiming

Los programas Verilog están separados en módulos, que son bloques funcionales que tienen entradas, salidas y lógica interna. Puede pensar en ellas como los bloques en un bloque de diagramas de circuito, pero en este caso, funcionan. Hay dos tipos de módulos Verilog: módulos de comportamiento y módulos estructurales. Ambos pueden tener el mismo comportamiento, pero son escritos de diferente manera como verá a continuación.

Para el programa Flip-Flop son usados tres módulos distintos: el módulo Flip-Flop, módulos de pruebas y el módulo de banco de pruebas. Los último dos, son módulos que necesitará en casi todos los diseños con el fin de probar un circuito.

Módulo Flip-Flop

Represneta un Flip-Flop tipo D simple. Recibe una señal de reloj y una señal D como entradas y Q y QN como salidas. Las salidad pueden variar en el flanco positivo del reloj. El código para este módulo es:

//el módulo dff representa un Flip-Flop tipo D

module dff(d,clk,q,qn);

    inputd,clk;

    outputq,qn;

    regq,qn;

    //Inicia las salidas Flip-Flop

    initial beginq=0;qn=1;end

    //Cambia la salida en un flanco positivo en el reloj

    always@(posedge clk)

    begin

        q<=d;

        qn<=!d;

    end

endmodule

De este código, podemos observar la estructura básica de todo módulo Verilog. Empieza con una declaración: module dff (d, clk, q, qn); y termina con endmodule. La declaración establece el nombre del módulo así como sus salidas y entradas. Es importante declarar cuales variables son entradas y cuales son salidas usado "input" y "output".

La variables en Verilog son "wires" o "regs". Un cable, como uno de la vida real, no tiene memoria. Así, estas variables no retienen sus valores por sí mismas. La palabra clave "reg" le da a las variables la habilidad de conservar sus valores después de que son asignados, claro, hasta que este sea cambiado. Queremos ese comportamiento para las salidas, por lo que "q" y "qn" serán definidas como "regs". Sí usamos una variable "wire" la salida nunca será vista por otros bloques porque perdería el valor inmediatamente después de asignado. No es necesario definir las otras variables como "wires" porque todas son cables por defecto.

La forma en que la lógica interna de un módulo es escrita depende de sí es un módulo de comportamiento o uno estructural. El módulo Flip-Flop es un ejemplo de código de comportamiento. Es decir, usted describe el comportamiento que el módulo debe tener. Para esto, use los bloques "initial" y "always". El código contenido en un bloque "initial" es ejecutado una sola vez cuando el Flip-Flop es creado. En el ejemplo es usado para definir inicialmente que q=0 y qn=1. En Verilog, por defecto, las variables son indefinidas, no son cero, no son uno, solo están representadas por una x. Si no utilizamos este bloque "initial" q y qn serían dejadas indefinidas hasta que sean asignadas por primera vez.

El código dentro de un bloque "always" es ejecutado cuando se cumple cierta condición. En este caso, cuando el reloj tiene un flanco positivo, q y qn son reasignadas. Esto describe por completo la lógica Flip-Flop. Como puede ver, cuando no se cumple la condición, Verilog mantiene los valores de salida.

Como regla de oro, cuando escriba un módulo comportacional, defina las salidas como "wires".

Verilog tiene tiene estructuras como: while, if-else, case, for y repeat como en la mayoría de los lenguajes de programación. Esto le asistirá en la escritura de su código de comportamiento. Por ejemplo, reemplazar el módulo "Always" flip-flop por:

always@(clk)

    begin

        if(clk==1)

        begin

            q<=d;

            qn<=!d;

        end

    end

produce extactamente el mismo comportamiento. Algunas cosas cambiaron. Ahora, la condición "siempre" es always @ (clk) en lugar de always @(posedge clk. Esto significa que el bloque "always" es ejecutado cada vez que clk cambia su valor, en el extremo positivo o negativo. Un bloque "always" puede ser ejecutado  por cualquier número de variables. Por ejemplo, @(clk or d) lo lanzaría cuando clk o d cambiaran. Esto es utilizado en lógica combinacional donde la salida es recalculada siempre que un entrada cambie. De vuelta al ejemplo: sí clk ==1 entonces, el extremo es positivo. Podemos revisar eso usando una declaración "if". Note que agregar las palabras "begin" y "end" es necesario cuando cualquier bloque tenga más de una instrucción. Sí es omitida para la declaración "if", la segunda instrucción: qn <=!d será ejecutada siempre. Es decir, estas palabras actual como llaves o corchetes en muchos lenguajes de programación. 

Módulo de pruebas

Este módulo prueba el flip-flop generando la señal D y del reloj del diagrama de tiempo y vaciando las señales Q y QN del flip-flop.

//El módulo de prueba envía una señal periódica al flip-flop

module tester(q,qn,clk,d);

    inputq,qn;

    output clk,d;

    reg clk,d;

    //Corre la prueba una vez

    initial

    begin

        clk=0;

        // Descarga los resultados de la simulación a ff.cvd

        $dumpfile("dff.vcd");

        $dumpvars;

        //Genera una señal de entrada d

           d=0;#9 d=1; #1 d=0; #1 d=1; #2 d=0; #1 d=1; #12 d=0;

        #1 d=1; #2 d=0; #1 d=1; #1 d=0; #1 d=1; #1 d=0; # 7 d=1;

        #8 $finish;

    end

    //Genera una señal periódica del reloj

    always

    begin

        #4 clk=!clk;

    end

endmodule

Este módulo también es de comportamiento porque tenemos los bloques "initial" y "always". Estos son algunos nuevos conceptos que aparecen en este código. Los comandos $dumpfile y $dumpvars le dicen al simulador (más sobre esto adelante) que registre las variables del módulo a un archivo en específico, en este caso dff.vcd. ¿Que hacen los #s? Estos sirven para retrasar la siguiente instrucción una cantidad de tiempo dada.Por ejemplo, #4 clk=!clk; "clk" cambia cuantro unidades de tiempo (desde 0 a 1) dentro de un bloque "always" produciendo una onda cuadrada. La unidad de tiempo es un segundo, por defecto.

Sin utilizar estos "retrasos", no hay forma en que el programa funcione. Esta es la forma de controlar el tiempo en el diseño. Puede agregar retardos a cualquier instrucción. Por ejemplo, usted puede  modelar el retraso en el flip-flop agregando #s a su bloque "always". Ahora es fácil entender como d=0; #9 d=1; #1 d=0; #1 d=1 ... producen la señal que queremos.

Finalmente, el comando $finish le dice al simulador que detenga la simulación una vez que la señal D es generada. Si este comando es omitido, la simulación continuará indefinidamente porque esta vez el bloque "always" no tiene condición como el el módulo flip-flop.

Módulo Testbench 

Es módulo, conecta el módulo de pruebas con el módulo flip-flop.

module testbench;

    wire clk,d,q,qn;

    dff ff1(d,clk,q,qn);

    tester tst1(q,qn,clk,d);

endmodule

 Es el más sencillo de los módulos, pero es muy diferente. Esta vez, se trata de un código de estructura, eso significa que define la estructura de un circuito. Es como describir el diagrama del circuito. En este caso, el circuito final es simplemente el flip-flop conectado al módulo de pruebas. Para crear un flip-flop use dff ff1(d,clk,q,qn);. Primero va al nombre del módulo, seguido del nombre de la parte, que puede ser casi que cualquier cadena, seguido por los cables (dentro del paréntesis) que conectan con el módulo. Esto debería seguir la orden en la declaración del módulo. En un módulo estructural usamos cables, los regs no son necesarios porque están definidos dentros de los diferentes módulos. 

Compilando y simulando

Copie y pegue los módulos dentro de un archivo de texto, el orden no importa. Llame al archivo "dff.v" . La extensión ".v" es estándar para los archivos de Verilog, pero no es requerida por el compilador. Para compilar, abra el símbolo del sistema en la ubicación donde guardó el archivo. Una manera rápida de arbir una consola en cualquier directorio es sosteniendo la techa "Shift" y haciendo clic derecho y eligiendo "Abrir línea de comandos de Windows aquí". Digite: iverilog -odffdff.v

"-o" le dice a Icarus Verilog que guarde la salida en el archivo elegido. Entonces, la salida es guardada en dff. Este archivo no es ejecutable. Tiene que ser ejecutado utilizando vvp, el simulador de Icarus Verilog que es el que realmente produce la simulación de resultados, los ceros y unos para cada una de las variables en función de tiempo. Para correr la simulación digite: vvp dff.

Esto es lo que produce el archivo dff.vcd con todos los resultados de simulación. Sin embargo, si abre este archivo con el editor de texto se dará cuenta de que no es sencillo de entender. Para generar un diagrama fácilmente entendible de este archivo, se utiliza GTKWave.

GTKWave cuenta con interfaz gráfica. Para abrirlo, presione la tecla de Windows y digite "gtkwave". Luego, haga clic en "File" --> "Open New Tab" y elija el archivo fdd.vcd. Ahora, debe agregar las variables para verlas en su diagrama de tiempo. Haga clic en "testbench" a la izquierda y seleccione todas las variables usando Control o Shift e insertándolas.

Si todo sale bien, usted debería obtener un diagrama igual al del inicio del tutorial:

simulation2-640x264

Cuando prueba sus programas tendrá que ir al proceso de compilación-simulación-carga cada cierta cantidad de minutos. Recuerde que puede usar las flechas de arriba/abajo en la consola para acceder los comandos pasados y compilar/simular. En GTKWave use File --> Reload Waveform para recargar el archivo .vcd y actualizar los diagramas sin necesidad de recargarlos. Usando estos pasos, el proceso debería tomarle unos pocos segundos.

Fundador
Seguidor de Jesús. Escribo artículos en mi tiempo libre sobre temas de tecnología que me interesan.