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
- Los procedimientos se pueden usar como minimódulos para evitar copiar y pegar código
- Los parámetros (entradas/salidas) de un procedimiento pueden ser señales, variables o constantes
- A diferencia de las funciones, los procedimientos pueden contener declaraciones de espera
Ir al siguiente tutorial »
VHDL
- Declaración de procedimiento:ejemplo de VHDL
- ¿Cómo utilizamos el molibdeno?
- Cómo crear una lista de cadenas en VHDL
- Cómo detener la simulación en un banco de pruebas VHDL
- Cómo crear un controlador PWM en VHDL
- Cómo generar números aleatorios en VHDL
- Cómo usar un procedimiento en un proceso en VHDL
- Cómo usar una función impura en VHDL
- Cómo usar una función en VHDL
- Cómo crear una máquina de estados finitos en VHDL
- Cómo usar una amoladora cortadora