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

Uso de procedimientos en VHDL: Simplifique su diseño con código reutilizable

En VHDL, los procedimientos son subprogramas que permiten a los diseñadores evitar bloques de código repetitivos. Cuando la misma operación se necesita en múltiples lugares, crear un módulo completo puede ser excesivo. Un procedimiento ofrece una solución ligera y reutilizable.

Los procedimientos pueden declararse en cualquier región declarativa —arquitectura, paquete o proceso— y su ámbito se limita a esa región. Cuando se invocan, el cuerpo del procedimiento se ejecuta como si su código estuviera escrito en su lugar, dándole los beneficios de modularidad sin la sobrecarga de un componente separado.

A diferencia de las funciones, los procedimientos no retornan un valor directamente. Sin embargo, puede pasar valores de vuelta declarando señales out o inout en la lista de parámetros, permitiendo efectivamente que el procedimiento actúe como un mini-módulo con entradas y salidas.

Este post es parte de la serie Tutoriales Básicos de VHDL.

La sintaxis canónica para definir un procedimiento se ilustra a continuación:

procedure <procedure_name> (
  signal|variable|constant <name1> : in|out|inout <type>;
  signal|variable|constant <name2> : in|out|inout <type>;
  ...
) is
  <declarations_for_use_within_the_procedure>
begin
  <code_performed_by_the_procedure_here>
end procedure;

La lista de parámetros define las entradas y salidas del procedimiento —muy parecido a un mini-módulo. Los parámetros pueden ser señales, variables o constantes. Dentro del procedimiento puede declarar objetos adicionales (constantes, variables, tipos, subtipos, alias) que son válidos solo dentro de ese bloque; no se pueden declarar señales localmente.

Debido a que los procedimientos pueden contener sentencias wait, son especialmente útiles en testbenches —por ejemplo, como conductores BFM simples o para verificar salidas del DUT.

Ejercicio

En el tutorial anterior, se construyó un módulo temporizador usando sentencias if-then-else profundamente anidadas. Cada nivel anidado añadía complejidad y reducía la legibilidad, aunque la misma operación se realizaba en diferentes conjuntos de señales. Un mejor enfoque es encapsular la lógica repetitiva dentro de un procedimiento.

El siguiente tutorial en video recorre la creación de un procedimiento VHDL:

Ejemplo: Temporizador basado en procedimiento

El código del testbench permanece sin cambios, excepto por la adición de una llamada a procedimiento para conducir el DUT:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity T19_ProcedureTb is
end entity;

architecture sim of T19_ProcedureTb is
  constant ClockFrequencyHz : integer := 10; -- 10 Hz
  constant ClockPeriod : time := 1000 ms / ClockFrequencyHz;
  signal Clk : std_logic := '1';
  signal nRst : std_logic := '0';
  signal Seconds : integer;
  signal Minutes : integer;
  signal Hours : integer;
begin
  i_Timer : entity work.T19_Timer(rtl)
    generic map(ClockFrequencyHz => ClockFrequencyHz)
    port map (
      Clk     => Clk,
      nRst    => nRst,
      Seconds => Seconds,
      Minutes => Minutes,
      Hours   => Hours
    );
  Clk <= not Clk after ClockPeriod / 2;
  process is
  begin
    wait until rising_edge(Clk);
    wait until rising_edge(Clk);
    nRst <= '1';
    wait;
  end process;
end architecture;

El módulo temporizador en sí ahora aprovecha un procedimiento para incrementar contadores:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity T19_Timer is
  generic(ClockFrequencyHz : integer);
  port(
    Clk     : in  std_logic;
    nRst    : in  std_logic; -- Reset negativo
    Seconds : inout integer;
    Minutes : inout integer;
    Hours   : inout integer
  );
end entity;

architecture rtl of T19_Timer is
  signal Ticks : integer;
  
  procedure IncrementWrap(
    signal Counter   : inout integer;
    constant WrapValue : in integer;
    constant Enable  : in boolean;
    variable Wrapped : out boolean
  ) is
  begin
    Wrapped := false;
    if Enable then
      if Counter = WrapValue - 1 then
        Wrapped := true;
        Counter <= 0;
      else
        Counter <= Counter + 1;
      end if;
    end if;
  end procedure;
  
begin
  process(Clk) is
    variable Wrap : boolean;
  begin
    if rising_edge(Clk) then
      if nRst = '0' then
        Ticks   <= 0;
        Seconds <= 0;
        Minutes <= 0;
        Hours   <= 0;
      else
        IncrementWrap(Ticks,   ClockFrequencyHz, true,  Wrap);
        IncrementWrap(Seconds, 60,               Wrap, Wrap);
        IncrementWrap(Minutes, 60,               Wrap, Wrap);
        IncrementWrap(Hours,   24,               Wrap, Wrap);
      end if;
    end if;
  end process;
end architecture;

La forma de onda siguiente confirma que el contador de minutos hace wrap correctamente cuando el temporizador alcanza 60 minutos:

Uso de procedimientos en VHDL: Simplifique su diseño con código reutilizable

Análisis

Desde la forma de onda vemos que la funcionalidad de wrap se comporta idénticamente a la implementación original con if anidados. El cambio es puramente estructural —sin cambio en la lógica subyacente.

El primer parámetro, Counter, es una señal inout, permitiendo al procedimiento leer y actualizar su valor. El segundo y tercer parámetros, WrapValue y Enable, son constantes; se tratan como constantes en tiempo de compilación dentro del procedimiento.

El parámetro final, Wrapped, es una variable declarada como out. Sirve como un valor de retorno pseudo, indicando si el contador hizo wrap durante esa llamada.

En el proceso principal, cuatro llamadas sucesivas a IncrementWrap cascadan los contadores. La variable Wrap de la llamada anterior alimenta la entrada Enable de la siguiente llamada. Usar una variable es esencial aquí porque las actualizaciones de señal solo son visibles después de que el proceso se suspende; una variable proporciona flujo de datos procedimental inmediato.

Uso de procedimientos en VHDL: Simplifique su diseño con código reutilizable

Conclusión

Proceda al siguiente tutorial »

VHDL

  1. Dominando las Técnicas de Afiladora de Herramientas: Guía Práctica
  2. Cómo el molibdeno moldea la industria moderna: usos, beneficios y dinámica de suministro
  3. Ejemplo de procedimiento VHDL: Incrementando un vector Standard Logic
  4. Creación de listas de cadenas en VHDL: Buenas prácticas y ejemplo
  5. Finalizar elegantemente una simulación de testbench VHDL
  6. Implementación de un controlador PWM en VHDL: Diseño, simulación y demo en FPGA
  7. Generación de números aleatorios en VHDL: De uniforme a OSVVM
  8. Aprovechando procedimientos en-proceso para diseños FSM más limpios en VHDL
  9. Uso de funciones impuras en VHDL: Mejorando legibilidad y mantenibilidad de FSM
  10. Dominando funciones VHDL: Guía práctica para diseño eficiente
  11. Diseño de máquina de estados finitos en VHDL: Ejemplo práctico de semáforo