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

Cómo usar un procedimiento en VHDL

Un procedimiento es un tipo de subprograma en VHDL que puede ayudarnos a evitar la repetición de código. A veces surge la necesidad de realizar operaciones idénticas en varios lugares a lo largo del diseño. Si bien crear un módulo puede ser excesivo para operaciones menores, a menudo lo que desea es un procedimiento.

Los procedimientos se pueden declarar dentro de cualquier región declarativa. El alcance del procedimiento se limitará a donde sea que se declare, arquitectura, paquete o proceso. Cada vez que llame al procedimiento, se comportará como si el código del procedimiento se insertara desde donde se llamó.

Un procedimiento no devuelve un valor como lo hace una función, pero puede devolver valores declarando out o inout señales en la lista de parámetros.

Esta publicación de blog es parte de la serie Tutoriales básicos de VHDL.

La sintaxis básica para crear un procedimiento es:
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 de un procedimiento define sus entradas y salidas, como un minimódulo. Puede ser una señal o una constante, pero a diferencia de un módulo, también puede ser una variable. Puede declarar objetos entre las palabras clave "es" y "comenzar" que solo son válidos dentro del procedimiento. Estos pueden incluir constantes, variables, tipos, subtipos y alias, pero no señales.

A diferencia de las funciones, los procedimientos pueden contener declaraciones de espera. Por lo tanto, a menudo se usan en bancos de prueba como simples BFM para simular interfaces o para verificar la salida del dispositivo bajo prueba (DUT).

Ejercicio

En el tutorial anterior, creamos un módulo de temporizador usando declaraciones If-Then-Else anidadas. Cada nivel de If-Then-Else dentro de otro If-Then-Else agrega complejidad al diseño y se vuelve menos legible. En cada nivel de lógica, básicamente estamos haciendo la misma operación en un conjunto diferente de señales. ¿No hay una mejor manera de hacer esto?

En este video tutorial aprenderemos a crear un procedimiento en VHDL:

El código final para el procedimiento testbench :

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

    -- We're slowing down the clock to speed up simulation time
    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

    -- The Device Under Test (DUT)
    i_Timer : entity work.T19_Timer(rtl)
    generic map(ClockFrequencyHz => ClockFrequencyHz)
    port map (
        Clk     => Clk,
        nRst    => nRst,
        Seconds => Seconds,
        Minutes => Minutes,
        Hours   => Hours);

    -- Process for generating clock
    Clk <= not Clk after ClockPeriod / 2;

    -- Testbench sequence
    process is
    begin
        wait until rising_edge(Clk);
        wait until rising_edge(Clk);

        -- Take the DUT out of reset
        nRst <= '1';

        wait;
    end process;

end architecture;

El código final para el módulo del temporizador usando un procedimiento:

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; -- Negative reset
    Seconds : inout integer;
    Minutes : inout integer;
    Hours   : inout integer);
end entity;

architecture rtl of T19_Timer is

    -- Signal for counting clock periods
    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 the negative reset signal is active
            if nRst = '0' then
                Ticks   <= 0;
                Seconds <= 0;
                Minutes <= 0;
                Hours   <= 0;
            else

                -- Cascade counters
                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 ventana de forma de onda en ModelSim, ampliada en la línea de tiempo donde el Minutes la señal se está envolviendo:

Análisis

Podemos ver en la forma de onda que la envoltura de señales aún funciona como lo hizo en el tutorial anterior. Eso es porque en realidad no hemos cambiado la función en el módulo, solo la forma en que se implementa.

El primer elemento en la lista de parámetros para el IncrementWrap el procedimiento es el Counter señal. Se declara usando la dirección inout para que el procedimiento pueda leer y establecer su valor.

Los elementos segundo y tercero de la lista de parámetros son constantes. Esto significa que los valores que ingrese aquí aparecerán como constantes dentro del procedimiento El WrapValue entrada junto con el Enable entrada determina si el Counter la señal se incrementa o envuelve.

El último elemento en la lista de parámetros es una variable con dirección out . El propósito de esta salida es informar a la persona que llama del procedimiento que envolvió el contador. Lo usamos aquí como un valor de retorno.

En el proceso principal tenemos cuatro llamadas al IncrementWrap procedimiento. Cada una de las llamadas posteriores utiliza el Wrap variable para habilitar el conteo. No habría funcionado si hubiéramos usado una señal en lugar de una variable, porque los valores de la señal solo se actualizan cuando un proceso se duerme. Necesitamos que el valor de salida de una llamada de procedimiento se use como entrada para una llamada en la siguiente línea. Por lo tanto, tiene que ser una variable.

Para llevar

Ir al siguiente tutorial »


VHDL

  1. Declaración de procedimiento:ejemplo de VHDL
  2. ¿Cómo utilizamos el molibdeno?
  3. Cómo crear una lista de cadenas en VHDL
  4. Cómo detener la simulación en un banco de pruebas VHDL
  5. Cómo crear un controlador PWM en VHDL
  6. Cómo generar números aleatorios en VHDL
  7. Cómo usar un procedimiento en un proceso en VHDL
  8. Cómo usar una función impura en VHDL
  9. Cómo usar una función en VHDL
  10. Cómo crear una máquina de estados finitos en VHDL
  11. Cómo usar una amoladora cortadora