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

Dominar el alcance de referencia jerárquica en Verilog: Evitar colisiones de nombres en módulos y bloques

La mayoría de los lenguajes de programación tienen una característica llamada alcance (scope) que define la visibilidad de ciertas secciones de código a variables y métodos. El alcance define un espacio de nombres para evitar colisiones entre diferentes nombres de objetos dentro del mismo espacio de nombres.

Verilog define un nuevo alcance para módulos, funciones, tasks, bloques nombrados y bloques generate.

module tb;
  reg signal;
  // Otra variable no puede declararse con
  // un nombre ya existente en el mismo alcance
  reg signal;
  // Sin embargo, el nombre 'signal' puede reutilizarse dentro
  // de una task porque pertenece a un alcance diferente.
  task display();
    reg signal = 1;
    $display("signal = %0b", signal);
  endtask
endmodule

Un identificador, como un nombre de señal, puede usarse para declarar solo un tipo de elemento en un alcance dado. Esto significa que dos variables de diferentes o mismos tipos de datos no pueden tener el mismo nombre, o una task y una variable del mismo nombre, o incluso una red e instancia de puerta con el mismo nombre en el mismo alcance.

Cada identificador en Verilog tiene un nombre de ruta jerárquica único, donde cada instancia de módulo, task, function o bloque nombrado begin end o fork join define un nuevo nivel o alcance.

Ejemplo de referencia jerárquica

module tb;
  // Crear dos instancias de diferentes módulos A y B
  A uA();
  B uB();

  // Crear un bloque nombrado que declara una señal e
  // imprime el valor a 10ns desde inicio de simulación
  initial begin : TB_INITIAL
    reg signal;
    #10 $display("signal=%0d", signal);
  end

  // Intentaremos acceder a otros alcances usando referencias
  // jerárquicas desde este bloque initial
  initial begin
    TB_INITIAL.signal = 0;
    uA.display();
    uB.B_INITIAL.B_INITIAL_BLOCK1.b_signal_1 = 1;
    uB.B_INITIAL.B_INITIAL_BLOCK2.b_signal_2 = 0;
  end
endmodule
module A;
  task display();
    $display("Hola, esto es A");
  endtask
endmodule

module B;
  initial begin : B_INITIAL
    #50;
    begin : B_INITIAL_BLOCK1
      reg b_signal_1;
      #10 $display("signal_1=%0d", b_signal_1);
    end
    #50;
    begin : B_INITIAL_BLOCK2
      reg b_signal_2;
      #10 $display("signal_2=%0d", b_signal_2);
    end
  end
endmodule
xcelium> run
Hola, esto es A
TB signal=0
signal_1=1
signal_2=0
xmsim: *W,RNQUIE: Simulation is complete.

Referencia de nombre hacia arriba

Un módulo de nivel inferior puede referenciar elementos en un módulo por encima de él en la jerarquía. Por ejemplo, signal en el bloque TB_INITIAL sería visible desde la task display en A.

module A;
  task display();
    $display("Hola, esto es A");
    // Referencia hacia arriba, TB_INITIAL es visible en este módulo
    #5 TB_INITIAL.signal = 1;
  endtask
endmodule

Tenga en cuenta que TB signal ahora es 1 en lugar de 0, debido al cambio de referencia hacia arriba hecho a la signal por el módulo A.

xcelium> run
Hola, esto es A
TB signal=1
signal_1=1
signal_2=0
xmsim: *W,RNQUIE: Simulation is complete.

Aquí hay otro ejemplo con múltiples módulos anidados y el nodo hoja puede acceder directamente a miembros de nodos superiores a través de referencia jerárquica hacia arriba.

module tb;
  A a();
  function display();
    $display("Hola, esto es TB");
  endfunction
endmodule

module A;
  B b();
  function display();
    $display("Hola, esto es A");
  endfunction
endmodule

module B;
  C c();
  function display();
    $display("Hola, esto es B");
  endfunction
endmodule

module C;
  D d();
  function display();
    $display("Hola, esto es C");
  endfunction
endmodule

module D;
  initial begin
    a.display(); // o A.display()
    b.display(); // o B.display()
    c.display(); // o C.display()
    a.b.c.display();
  end
endmodule
xcelium> run
Hola, esto es A
Hola, esto es B
Hola, esto es C
Hola, esto es C
xmsim: *W,RNQUIE: Simulation is complete.

Cuando el compilador encuentra b.display(),

  1. Busca en el alcance actual dentro del módulo D para ver si b está definido. Si no existe, busca el nombre en el alcance envolvente y sube hasta alcanzar el alcance del módulo. Si el nombre aún no se encuentra, pasa al siguiente paso.
  2. Busca en el alcance más externo del módulo padre y si no se encuentra, sigue subiendo en la jerarquía.

Verilog

  1. Dominar Verilog: Tutorial completo para diseño de circuitos digitales
  2. Dominar la concatenación en Verilog: Guía práctica
  3. Verilog Esencial: Resumen conciso
  4. Comprender las asignaciones en Verilog: tipos, sintaxis y mejores prácticas
  5. Bloqueante vs. No bloqueante en Verilog: Diferencias clave explicadas
  6. Dominar las funciones en Verilog para diseño RTL eficiente
  7. Comprender las Tasks en Verilog: Funciones vs Tasks, sintaxis y uso
  8. Dominar el alcance de referencia jerárquica en Verilog: Evitar colisiones de nombres en módulos y bloques
  9. Generador de reloj en Verilog: Guía de diseño e implementación
  10. Dominar las tareas de visualización en Verilog: Depuración y registro eficientes
  11. Dominar las funciones matemáticas en Verilog para diseño de hardware eficiente