Construya un temporizador fiable en VHDL: Contar ciclos de reloj hasta horas
En tutoriales anteriores usamos la sentencia wait for para retrasar tiempo en simulación. Sin embargo, wait for no puede emplearse en diseños de producción porque un circuito real no puede recibir instrucciones para pausar. La forma práctica de medir tiempo en un módulo VHDL es contar ciclos de reloj.
Todo diseño digital tiene acceso a una señal de reloj estable que oscila a una frecuencia conocida. Si el reloj corre a 100 MHz, un segundo equivale a 100 millones de ticks de reloj. Contando estos ticks podemos generar fiablemente segundos, minutos, horas y más allá.
Este artículo es parte de la serie Tutoriales Básicos de VHDL.
Implementamos un contador que se incrementa en cada flanco de subida del reloj. Cuando el contador alcanza el valor de la frecuencia del reloj, ha transcurrido un segundo y un contador secundario "Segundos" se incrementa. Un enfoque similar se usa para minutos (incrementar después de 60 segundos) y horas (incrementar después de 60 minutos). Contadores adicionales pueden encadenarse para días, semanas o meses, limitados solo por recursos FPGA/ASIC y el ancho de contador requerido.
Aunque contadores más largos consumen más recursos lógicos, también aumentan el retardo de propagación. La ruta crítica a través de la cadena de contadores debe caber dentro del período de reloj, de lo contrario la síntesis fallará.
Ejercicio: Implementando el temporizador
El siguiente testbench VHDL demuestra un reloj simple de 10 Hz para mantener el tiempo de simulación razonable. El DUT es un temporizador que emite señales Seconds, Minutes y Hours.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity T18_TimerTb is
end entity;
architecture sim of T18_TimerTb is
-- Reloj lento para simulación rápida
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
-- Device Under Test (DUT)
i_Timer : entity work.T18_Timer(rtl)
generic map(ClockFrequencyHz => ClockFrequencyHz)
port map (
Clk => Clk,
nRst => nRst,
Seconds => Seconds,
Minutes => Minutes,
Hours => Hours
);
-- Generador de reloj
Clk <= not Clk after ClockPeriod / 2;
-- Secuencia testbench
process is
begin
wait until rising_edge(Clk);
wait until rising_edge(Clk);
-- Liberar reset
nRst <= '1';
wait;
end process;
end architecture;
A continuación está el módulo temporizador en sí. Cuenta ticks, segundos, minutos y horas, reseteando todos los contadores cuando el reset negativo (nRst) se afirma.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity T18_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 T18_Timer is
-- Contar períodos de reloj
signal Ticks : integer;
begin
process(Clk) is
begin
if rising_edge(Clk) then
if nRst = '0' then
Ticks <= 0;
Seconds <= 0;
Minutes <= 0;
Hours <= 0;
else
if Ticks = ClockFrequencyHz - 1 then
Ticks <= 0;
if Seconds = 59 then
Seconds <= 0;
if Minutes = 59 then
Minutes <= 0;
if Hours = 23 then
Hours <= 0;
else
Hours <= Hours + 1;
end if;
else
Minutes <= Minutes + 1;
end if;
else
Seconds <= Seconds + 1;
end if;
else
Ticks <= Ticks + 1;
end if;
end if;
end if;
end process;
end architecture;
Las formas de onda confirman la operación correcta: Seconds se incrementa cada tick, Minutes después de 60 segundos, y Hours después de 60 minutos.
En simulación ejecutamos una prueba de 50 horas con run 50 hr en ModelSim, usando un reloj de 10 Hz para mantener el tiempo de ejecución manejable. Ajustar la frecuencia del reloj en el testbench es una estrategia común para acelerar la verificación.
En hardware real, la cadena de contadores debe terminar dentro de un período de reloj. A medida que crece el ancho del contador, el retardo de propagación aumenta, potencialmente excediendo el período y causando violaciones de temporización. El límite exacto depende de la familia FPGA/ASIC y la velocidad de reloj.
Conclusiones clave
- La medición de tiempo en VHDL se logra contando ciclos de reloj.
- Reducir la frecuencia del reloj del testbench acelera la simulación sin alterar el diseño.
Proceda al siguiente tutorial para características avanzadas de temporizador.
VHDL
- Creación de listas de cadenas en VHDL: Buenas prácticas y ejemplo
- Creación de un testbench dirigido por Tcl para un módulo VHDL de cerradura por código
- Finalizar elegantemente una simulación de testbench VHDL
- Implementación de un controlador PWM en VHDL: Diseño, simulación y demo en FPGA
- Generación de números aleatorios en VHDL: De uniforme a OSVVM
- Diseño de un búfer circular FIFO robusto en VHDL usando RAM de bloques
- Cómo construir un testbench de auto-comprobación en VHDL: Guía práctica
- Implementación de lista enlazada dinámica en VHDL con tipos protegidos y punteros de acceso
- Aprovechando procedimientos en-proceso para diseños FSM más limpios en VHDL
- Uso de funciones impuras en VHDL: Mejorando legibilidad y mantenibilidad de FSM
- Dominando funciones VHDL: Guía práctica para diseño eficiente