Buscar..


Observaciones

Verilog es un lenguaje de descripción de hardware (HDL) que se utiliza para diseñar, simular y verificar circuitos digitales a un nivel de transferencia de registro o de comportamiento. Es digno de mención por razones que lo distinguen de los lenguajes de programación "tradicionales":

  • Hay dos tipos de asignación, bloqueo y no bloqueo, cada uno con sus propios usos y semántica.
  • Las variables deben declararse como de ancho de bit único o con un ancho explícito.
  • Los diseños son jerárquicos, con la capacidad de instanciar módulos que tienen un comportamiento deseado.
  • En la simulación (no típicamente en la síntesis), wire variables de wire pueden estar en uno de cuatro estados: 0, 1, flotante ( z ) y no definido ( x ).

Versiones

Versión Fecha de lanzamiento
Verilog IEEE-1364-1995 1995-01-01
Verilog IEEE-1364-2001 2001-09-28
Verilog IEEE-1364.1-2002 2002-12-18
Verilog IEEE-1364-2005 2006-04-07
SystemVerilog IEEE-1800-2009 2009-12-11
SystemVerilog IEEE-1800-2012 2013-02-21

Instalación o configuración

Las instrucciones detalladas sobre cómo configurar o instalar Verilog dependen de la herramienta que utilice, ya que hay muchas herramientas de Verilog.

Introducción

Verilog es un lenguaje de descripción de hardware (HDL) utilizado para modelar sistemas electrónicos. Más comúnmente describe un sistema electrónico en el nivel de transferencia de registro (RTL) de abstracción. También se utiliza en la verificación de circuitos analógicos y circuitos de señal mixta. Su estructura y principios principales (como se describe a continuación) están diseñados para describir e implementar con éxito un sistema electrónico.

  • Rigidez
    Un circuito electrónico es una entidad física que tiene una estructura fija y Verilog se adapta para eso. Los módulos (módulo), los puertos (entrada / salida / entrada), las conexiones (cables), los bloques (@always), los registros (reg) están todos fijos en el momento de la compilación. El número de entidades e interconexiones no cambia dinámicamente. Siempre hay un "módulo" en el nivel superior que representa la estructura del chip (para la síntesis), y uno en el nivel del sistema para la verificación.
  • Paralelismo
    Las operaciones simultáneas inherentes en el chip físico se imitan en el lenguaje mediante los bloques always (most commmon), initial y fork / join.
  module top();
  reg r1,r2,r3,r4; // 1-bit registers
    initial
    begin
      r1 <= 0 ;
    end
    initial
    begin
      fork
         r2 <= 0 ;
         r3 <= 0 ;
      join
    end
     always @(r4)
        r4 <= 0 ;
 endmodule

Todas las declaraciones anteriores se ejecutan en paralelo dentro de la misma unidad de tiempo.

  • Sincronización y sincronización
    Verilog admite varias construcciones para describir la naturaleza temporal de los circuitos. Los tiempos y retrasos en los circuitos se pueden implementar en Verilog, por ejemplo, mediante construcciones #delay. De manera similar, Verilog también se adapta a circuitos y componentes síncronos y asíncronos como fracasos, cierres y lógica combinatoria utilizando varias construcciones, por ejemplo, bloques "siempre". Un conjunto de bloques también se puede sincronizar a través de una señal de reloj común o un bloque puede activarse en función de un conjunto específico de entradas.

    #10   ;                 // delay for 10 time units
    always @(posedge clk )  // synchronous 
    always @(sig1 or sig2 ) // combinatorial logic  
    @(posedge event1)       // wait for post edge transition of event1
    wait (signal  == 1)     // wait for signal to be 1
    
  • Incertidumbre
    Verilog soporta algunas de las incertidumbres inherentes a los circuitos electrónicos. "X" se utiliza para representar el estado desconocido del circuito. "Z" se utiliza para representar el estado no impulsado del circuito.

    reg1 = 1'bx;
    reg2 = 1'bz;
    
  • Abstracción
    Verilog apoya el diseño en diferentes niveles de abstracción. El nivel más alto de abstracción para un diseño es el Nivel de transferencia de registro (RTL), el siguiente es el nivel de puerta y el más bajo el nivel de celda (User Define Primitives), siendo la abstracción RTL la más utilizada. Verilog también admite el nivel de comportamiento de abstracción sin tener en cuenta la realización estructural del diseño, que se utiliza principalmente para la verificación.

 // Example of a D flip flop at RTL abstraction
module dff (
 clk    , // Clock Input
 reset  , // Reset input
 d       , // Data Input
 q        // Q output
 );
 //-----------Input Ports---------------
 input d, clk, reset ;

 //-----------Output Ports---------------
 output q;

 reg q;

 always @ ( posedge clk)
 if (~reset) begin
   q <= 1'b0;
 end  else begin
   q <= d;
 end

endmodule


// And gate model based at Gate level abstraction 
module and(input x,input y,output o);

wire  w;
// Two instantiations of the module NAND
nand U1(w,x, y); 
nand U2(o, w, w); 

endmodule

// Gate modeled at Cell-level Abstraction
primitive udp_and(
a, // declare three ports
b,
c 
);
output a;   // Outputs
input b,c;  // Inputs 

// UDP function code here
// A = B & C;
table
 // B  C    : A 
    1  1    : 1;
    0  1    : 0;
    1  0    : 0;
    0  0    : 0;
endtable

endprimitive

Hay tres casos de uso principales para Verilog. Ellos determinan la estructura del código y su interpretación y también determinan los conjuntos de herramientas utilizados. Las tres aplicaciones son necesarias para la implementación exitosa de cualquier diseño de Verilog.

  1. Diseño Físico / Back-end
    Aquí, Verilog se usa para ver principalmente el diseño como una matriz de puertas interconectadas que implementan un diseño lógico. RTL / lógico / Diseño pasa por varios pasos desde la síntesis -> ubicación -> construcción del árbol de reloj -> enrutamiento -> DRC -> LVS -> a la cinta. Los pasos y secuencias precisos varían según la naturaleza exacta de la implementación.
  2. Simulación
    En este caso de uso, el objetivo principal es generar vectores de prueba para validar el diseño según la especificación. El código escrito en este caso de uso no necesita ser sintetizable y permanece dentro de la esfera de verificación. El código aquí se asemeja más a estructuras de software genéricas como para / while / do loops etc.
  3. Diseño
    El diseño implica implementar la especificación de un circuito generalmente en el nivel de abstracción RTL. El código de Verilog se proporciona para la verificación y el código completamente verificado para la implementación física. El código se escribe utilizando solo las construcciones sintetizables de Verilog. Cierto estilo de codificación RTL puede causar una falta de coincidencia entre la simulación y la síntesis y se debe tener cuidado para evitarlos.

Hay dos flujos principales de implementación. También afectarán la forma en que se escribe e implementa el código Verilog. Ciertos estilos de codificación y ciertas estructuras son más adecuados en un flujo sobre el otro.

  • ASIC Flow (circuito integrado específico de la aplicación)
  • Flujo de FPGA (matriz de compuerta programable en campo) - incluye FPGA y CPLD

Hola Mundo

Este ejemplo utiliza el compilador verilog icarus.

Paso 1: Crea un archivo llamado hello.v

module myModule();

initial
  begin
    $display("Hello World!");   // This will display a message
    $finish ; // This causes the simulation to end.  Without, it would go on..and on.
  end

endmodule

Paso 2. Compilamos el archivo .v usando icarus:

>iverilog -o hello.vvp hello.v

El modificador -o asigna un nombre al archivo de objeto de salida. Sin este interruptor, el archivo de salida se llamaría a.out. El hello.v indica el archivo fuente que se compilará. Prácticamente no debe haber salida cuando compila este código fuente, a menos que haya errores.

Paso 3. Ya está listo para simular este programa de verilog de Hello World. Para ello, invoca como tal:

>vvp hello.vvp 
Hello World!
>

Instalación de Icarus Verilog Compiler para Mac OSX Sierra

  1. Instalar Xcode desde la App Store.
  2. Instalar las herramientas de desarrollo de Xcode
> xcode-select --install

Esto proporcionará herramientas básicas de línea de comandos como gcc y make

  1. Instale los puertos Mac https://www.macports.org/install.php

El paquete de instalación OSX Sierra proporcionará un método de código abierto para instalar y actualizar paquetes de software adicionales en la plataforma Mac. Piensa yum o apt-get para Mac.

  1. Instala icarus usando puertos Mac
> sudo port install iverilog
  1. Verificar la instalación desde la línea de comando.
$ iverilog
iverilog: no source files.

Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]
                [-g1995|-g2001|-g2005] [-g<feature>]
                [-D macro[=defn]] [-I includedir] [-M depfile] [-m module]
                [-N file] [-o filename] [-p flag=value]
                [-s topmodule] [-t target] [-T min|typ|max]
                [-W class] [-y dir] [-Y suf] source_file(s)

See the man page for details.
$

Ahora está listo para compilar y simular su primer archivo Verilog en la Mac.

Instale GTKWave para la visualización gráfica de los datos de simulación en Mac OSx Sierra

GTKWave es un paquete de visualización gráfica con todas las funciones que admite varios estándares de almacenamiento de datos gráficos, pero también es compatible con VCD, que es el formato que vvp . Entonces, para recoger GTKWave, tienes un par de opciones

  1. Vaya a http://gtkwave.sourceforge.net/gtkwave.zip y descárguelo. Esta versión suele ser la última.
  2. Si ha instalado MacPorts ( https://www.macports.org/ ), simplemente ejecute sudo port install gtkwave . Esto probablemente querrá instalar en las dependencias a. Tenga en cuenta que este método normalmente le dará una versión anterior. Si no tiene MacPorts instalado, hay un ejemplo de configuración de instalación para hacer esto en esta página. ¡Sí! Necesitará todas las herramientas de desarrollo de xcode, ya que estos métodos le "construirán" un GTKWave desde la fuente.

Cuando finaliza la instalación, se le puede solicitar que seleccione una versión de python. Ya tenía 2.7.10 instalado, así que nunca "seleccioné" uno nuevo.

En este punto, puede iniciar gtkwave desde la línea de comandos con gtkwave . Cuando comience, se le puede pedir que instale o actualice XQuarts. Hazlo En mi caso XQuarts 2.7.11 está instalado.

Nota: en realidad necesitaba reiniciar para obtener XQuarts correctamente, luego tecleé gtkwave nuevo y aparece la aplicación.

En el siguiente ejemplo, crearé dos archivos independientes, un banco de pruebas y un módulo para probar, y usaremos gtkwave para ver el diseño.

Uso de Icarus Verilog y GTKWaves para simular y ver gráficamente un diseño

Este ejemplo utiliza Icarus y GTKWave. Las instrucciones de instalación para esas herramientas en OSx se proporcionan en otra parte de esta página.

Comencemos con el diseño del módulo. Este módulo es una pantalla de BCD a 7 segmentos. He codificado el diseño de una manera obtusa simplemente para darnos algo que se rompe fácilmente y podemos dedicar algún tiempo a arreglarlo gráficamente. Así que tenemos un reloj, reinicio, una entrada de 4 datos que representa un valor BCD y una salida de 7 bits que representa la pantalla de siete segmentos. Cree un archivo llamado bcd_to_7seg.v y coloque la fuente a continuación.

module bcd_to_7seg (
   input clk,
   input reset,
   input [3:0] bcd,
   output [6:0] seven_seg_display

);
   parameter TP = 1;
   reg seg_a;
   reg seg_b;
   reg seg_c;
   reg seg_d;
   reg seg_e;
   reg seg_f;
   reg seg_g;

   
   always @ (posedge clk or posedge reset)
      begin
      if (reset)
         begin
            seg_a <= #TP 1'b0;
            seg_b <= #TP 1'b0;
            seg_c <= #TP 1'b0;
            seg_d <= #TP 1'b0;
            seg_e <= #TP 1'b0;
            seg_f <= #TP 1'b0;
            seg_g <= #TP 1'b0;
         end
      else
         begin
            seg_a <= #TP  ~(bcd == 4'h1 || bcd == 4'h4);
            seg_b <= #TP  bcd < 4'h5 || bcd > 6;
            seg_c <= #TP   bcd != 2;
            seg_d <= #TP   bcd == 0 || bcd[3:1] == 3'b001 || bcd == 5 || bcd == 6 || bcd == 8;
            seg_e <= #TP  bcd == 0 || bcd == 2 || bcd == 6 || bcd == 8;
            seg_f <= #TP  bcd == 0 || bcd == 4 || bcd == 5 || bcd == 6 || bcd > 7;
            seg_g <= #TP  (bcd > 1 && bcd < 7) || (bcd > 7);
         end
    end
 
    assign seven_seg_display = {seg_g,seg_f,seg_e,seg_d,seg_c,seg_b,seg_a};
endmodule

A continuación, necesitamos una prueba para verificar si este módulo está funcionando correctamente. En mi opinión, la declaración del caso en el banco de pruebas es más fácil de leer y más clara en cuanto a lo que hace. Pero no quise poner la misma declaración de caso en el diseño Y en la prueba. Esa es una mala práctica. Más bien, se están utilizando dos diseños independientes para validar uno a otro.

Dentro del código a continuación, notará dos líneas $dumpfile("testbench.vcd"); y $dumpvars(0,testbench); . Estas líneas son las que crean el archivo de salida VCD que se utilizará para realizar un análisis gráfico del diseño. Si los deja afuera, no obtendrá un archivo VCD generado. Cree un archivo llamado testbench.v y coloque la fuente debajo en él.

`timescale 1ns/100ps
module testbench;
reg clk;
reg reset;
reg [31:0] ii;
reg [31:0] error_count;
reg [3:0] bcd;
wire [6:0] seven_seg_display; 
parameter TP = 1;
parameter CLK_HALF_PERIOD = 5;
 
   // assign clk = #CLK_HALF_PERIOD ~clk;  // Create a clock with a period of ten ns
   initial
   begin
     clk = 0;
     #5;
     forever clk = #( CLK_HALF_PERIOD )  ~clk;
   end

   initial
     begin
       $dumpfile("testbench.vcd");
       $dumpvars(0,testbench);
       // clk  = #CLK_HALF_PERIOD ~clk; 
       $display("%0t, Reseting system", $time);
       error_count = 0;
       bcd  = 4'h0;
       reset = #TP 1'b1;
       repeat (30) @ (posedge clk);
       reset  = #TP 1'b0;
       repeat (30) @ (posedge clk);
       $display("%0t, Begin BCD test", $time); // This displays a message


       for (ii = 0; ii < 10; ii = ii + 1)
          begin
          repeat (1) @ (posedge clk);
          bcd  = ii[3:0];
          repeat (1) @ (posedge clk); 
          if (seven_seg_display !== seven_seg_prediction(bcd)) 
             begin
                $display("%0t, ERROR: For BCD %d, module output 0b%07b does not match prediction logic value of 0b%07b.",$time,bcd, seven_seg_display,seven_seg_prediction(bcd));
                error_count = error_count + 1;
             end
          end
       $display("%0t, Test Complete with %d errors", $time, error_count);
       $display("%0t, Test %s", $time, ~|error_count ? "pass." : "fail.");
       $finish ; // This causes the simulation to end.
     end


parameter SEG_A = 7'b0000001;
parameter SEG_B = 7'b0000010;
parameter SEG_C = 7'b0000100;
parameter SEG_D = 7'b0001000;
parameter SEG_E = 7'b0010000;
parameter SEG_F = 7'b0100000;
parameter SEG_G = 7'b1000000;

function [6:0] seven_seg_prediction;
   input [3:0] bcd_in;

   //    +--- A ---+
   //    |         |
   //    F         B
   //    |         |
   //    +--- G ---+
   //    |         |
   //    E         C
   //    |         |
   //    +--- D ---+

   begin
      case (bcd_in)
         4'h0: seven_seg_prediction = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F;
         4'h1: seven_seg_prediction = SEG_B | SEG_C;
         4'h2: seven_seg_prediction = SEG_A | SEG_B | SEG_G | SEG_E | SEG_D;
         4'h3: seven_seg_prediction = SEG_A | SEG_B | SEG_G | SEG_C | SEG_D;
         4'h4: seven_seg_prediction = SEG_F | SEG_G | SEG_B | SEG_C;
         4'h5: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_C | SEG_D;
         4'h6: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_E | SEG_C | SEG_D;
         4'h7: seven_seg_prediction = SEG_A | SEG_B | SEG_C;
         4'h8: seven_seg_prediction = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G;
         4'h9: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_B | SEG_C;
         default: seven_seg_prediction = 7'h0;
      endcase
   end
endfunction


bcd_to_7seg u0_bcd_to_7seg (
.clk               (clk),
.reset             (reset),
.bcd               (bcd),
.seven_seg_display (seven_seg_display)
);


endmodule

Ahora que tenemos dos archivos, un testbench.v y bcd_to_7seg.v, necesitamos compilar, elaborar utilizando Icarus. Para hacer esto:

$ iverilog -o testbench.vvp testbench.v bcd_to_7seg.v

A continuación necesitamos simular

$ vvp testbench.vvp 
LXT2 info: dumpfile testbench.vcd opened for output.
0, Reseting system
6000, Begin BCD test
8000, Test Complete with          0 errors
8000, Test pass. 

En este punto, si desea validar, el archivo realmente se está probando, vaya al archivo bcd_2_7seg.v, mueva parte de la lógica y repita esos dos primeros pasos.

Como ejemplo, cambio la línea seg_c <= #TP bcd != 2; a seg_c <= #TP bcd != 4; . Recompila y simula lo siguiente:

$ iverilog -o testbench.vvp testbench.v bcd_to_7seg.v
$ vvp testbench.vvp 
LXT2 info: dumpfile testbench.vcd opened for output.
0, Reseting system
6000, Begin BCD test
6600, ERROR: For BCD  2, module output 0b1011111 does not match prediction logic value of 0b1011011.
7000, ERROR: For BCD  4, module output 0b1100010 does not match prediction logic value of 0b1100110.
8000, Test Complete with          2 errors
8000, Test fail.
$

Así que ahora, veamos la simulación usando GTKWave. Desde la línea de comando, emita un

gtkwave testbench.vcd &

Cuando aparezca la ventana de GTKWave, verá en la casilla superior izquierda, el nombre del módulo testbench. Pinchalo. Esto revelará los submódulos, tareas y funciones asociadas con ese archivo. Los cables y registros también aparecerán en la casilla inferior izquierda.

Ahora arrastre, clk, bcd, error_count y seven_seg_display en el cuadro de señal al lado de la ventana de forma de onda. Las señales ahora serán trazadas. Error_count le mostrará qué entrada de BCD en particular generó la salida de seven_seg_display incorrecta.

Ahora está listo para solucionar un error de Verilog gráficamente.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow