Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial programming >> Verilog

Compilación condicional en Verilog: `ifdef explicado

Verilog soporta algunas directivas de compilador que esencialmente dirigen al compilador a tratar el código de cierta manera. Por ejemplo, una porción del código puede representar una implementación de cierta característica y debería haber alguna forma de no incluir el código en el diseño si la característica no se usa.

Esto se puede resolver con compilación condicional donde el diseñador puede envolver el código dentro de directivas de compilador que le dicen al compilador si incluir o excluir el código para compilación cuando la bandera nombrada dada está establecida.

Sintaxis

La compilación condicional se puede lograr con las palabras clave `ifdef y `ifndef de Verilog. Estas palabras clave pueden aparecer en cualquier lugar en el diseño y pueden anidarse una dentro de la otra.

La palabra clave `ifdef simplemente le dice al compilador que incluya la pieza de código hasta el siguiente `else o `endif si el macro dado llamado FLAG está definido usando una directiva `define.

// Estilo #1: Solo `ifdef simple
`ifdef <FLAG>
  // Declaraciones
`endif

// Estilo #2: `ifdef con parte `else
`ifdef <FLAG>
  // Declaraciones
`else
  // Declaraciones
`endif

// Estilo #3: `ifdef con ifdefs adicionales
`ifdef <FLAG1>
  // Declaraciones
`elsif <FLAG2>
  // Declaraciones
`elsif <FLAG3>
  // Declaraciones
`else
  // Declaraciones
`endif

La palabra clave `ifndef simplemente le dice al compilador que incluya la pieza de código hasta el siguiente `else o `endif si el macro dado llamado FLAG no está definido usando una directiva `define.

Ejemplo de diseño con `ifdef

module my_design (
  input clk, d,
  `ifdef INCLUDE_RSTN
  input rstn,
  `endif
  output reg q
);
  always @ (posedge clk) begin
    `ifdef INCLUDE_RSTN
    if (!rstn) begin
      q <= 0;
    end else
    `endif
    begin
      q <= d;
    end
  end
endmodule

Testbench

module tb;
  reg clk, d, rstn;
  wire q;
  reg [3:0] delay;
  my_design u0 (
    .clk(clk),
    .d(d),
    `ifdef INCLUDE_RSTN
    .rstn(rstn),
    `endif
    .q(q)
  );
  always #10 clk = ~clk;
  initial begin
    integer i;
    {d, rstn, clk} <= 0;
    #20 rstn <= 1;
    for (i = 0; i < 20; i=i+1) begin
      delay = $random;
      #(delay) d <= $random;
    end
    #20 $finish;
  end
endmodule

Tenga en cuenta que por defecto, rstn no se incluirá durante la compilación del diseño y por tanto no aparecerá en la lista de puertos. Sin embargo, si un macro llamado INCLUDE_RSTN se define en cualquier archivo Verilog que sea parte de la lista de compilación de archivos o se pasa por línea de comandos al compilador, rstn se incluirá en la compilación y el diseño lo tendrá.

Experimente agregando y quitando +define+INCLUDE_RSTN de 'Compile & Run Options' en el panel izquierdo para conocer la diferencia.

Ejemplo de Verilog `ifdef `elsif

El siguiente ejemplo tiene dos declaraciones display dentro de ámbitos `ifdef separados que no tienen una parte `else por defecto. Así que esto significa que por defecto nada se mostrará. Si se define el macro MACRO1 o MACRO2, el mensaje display correspondiente se incluye y se mostrará durante la simulación.

module tb;
  initial begin
    `ifdef MACRO1
      $display ("Esto es MACRO1");
    `elsif MACRO2
      $display ("Esto es MACRO2");
    `endif
  end
endmodule
# Sin macros definidos
ncsim> run
ncsim: *W,RNQUIE: Simulation is complete.

# Con +define+MACRO1
ncsim> run
Esto es MACRO1
ncsim: *W,RNQUIE: Simulation is complete.

# Con +define+MACRO2
ncsim> run
Esto es MACRO2
ncsim: *W,RNQUIE: Simulation is complete.

Ejemplo de Verilog `ifndef `elsif

El mismo código se puede escribir con `ifndef y los resultados serán justo lo opuesto.

module tb;
  initial begin
    `ifndef MACRO1
      $display ("Esto es MACRO1");
    `elsif MACRO2
      $display ("Esto es MACRO2");
    `endif
  end
endmodule
# Sin macros definidos
ncsim> run
Esto es MACRO1
ncsim: *W,RNQUIE: Simulation is complete.

# Con +define+MACRO1
ncsim> run
ncsim: *W,RNQUIE: Simulation is complete.

# Con +define+MACRO2
ncsim> run
Esto es MACRO1
ncsim: *W,RNQUIE: Simulation is complete.

# Con +define+MACRO1 +define+MACRO2
ncsim> run
Esto es MACRO2
ncsim: *W,RNQUIE: Simulation is complete.

Ejemplo de Verilog `ifdef anidado

`ifdef y sus variantes pueden anidarse una dentro de la otra para crear formas complejas de inclusión y exclusión de código con macros definidas.

module tb;
  initial begin
    `ifdef FLAG
      $display ("FLAG está definido");
      `ifdef NEST1_A
        $display ("FLAG y NEST1_A están definidos");
        `ifdef NEST2
          $display ("FLAG, NEST1_A y NEST2 están definidos");
        `endif
      `elsif NEST1_B
        $display ("FLAG y NEST1_B están definidos");
        `ifndef WHITE
          $display ("FLAG y NEST1_B están definidos, pero WHITE no");
        `else
          $display ("FLAG, NEST1_B y WHITE están definidos");
        `endif
      `else
        $display ("Solo FLAG está definido");
      `endif
    `else
      $display ("FLAG no está definido");
    `endif
  end
endmodule
# Sin definir ningún macro
ncsim> run
FLAG no está definido
ncsim: *W,RNQUIE: Simulation is complete.

# Con +define+FLAG +define+NEST1_B
ncsim> run
FLAG está definido
FLAG y NEST1_B están definidos
FLAG y NEST1_B están definidos, pero WHITE no
ncsim: *W,RNQUIE: Simulation is complete.

# Con +define+FLAG +define+NEST1_B +define+WHITE
ncsim> run
FLAG está definido
FLAG y NEST1_B están definidos
FLAG, NEST1_B y WHITE están definidos
ncsim: *W,RNQUIE: Simulation is complete.

# Con +define+FLAG
ncsim> run
FLAG está definido
Solo FLAG está definido
ncsim: *W,RNQUIE: Simulation is complete.

# Con +define+WHITE
ncsim> run
FLAG no está definido
ncsim: *W,RNQUIE: Simulation is complete.

# Con +define+NEST1_A
ncsim> run
FLAG no está definido
ncsim: *W,RNQUIE: Simulation is complete.

Tenga en cuenta que mientras el macro padre no esté definido, la definición de cualquier otro macro anidado dentro de él no se compila. Por ejemplo, definiciones de NEST1_A o WHITE sin FLAG no hacen que el compilador recoja el código anidado.

Verilog

  1. Dominar Verilog: Tutorial completo para diseño de circuitos digitales
  2. Dominar la concatenación en Verilog: Guía práctica
  3. Comprender las asignaciones en Verilog: tipos, sintaxis y mejores prácticas
  4. Bloqueante vs. No bloqueante en Verilog: Diferencias clave explicadas
  5. Dominar las funciones en Verilog para diseño RTL eficiente
  6. Comprender las Tasks en Verilog: Funciones vs Tasks, sintaxis y uso
  7. Generador de reloj en Verilog: Guía de diseño e implementación
  8. Dominar las tareas de visualización en Verilog: Depuración y registro eficientes
  9. Dominar las funciones matemáticas en Verilog para diseño de hardware eficiente
  10. Dominar $timeformat en Verilog: Control de precisión y visualización
  11. Comprender e imprimir timescales de Verilog en cualquier alcance