Construire un minuteur fiable en VHDL : Compter les cycles d'horloge jusqu'aux heures
Dans les tutoriels précédents, nous avons utilisé l'instruction wait for pour retarder le temps en simulation. Cependant, wait for ne peut pas être employé dans les designs de production car un vrai circuit ne peut pas être instruit de faire une pause. La façon pratique de mesurer le temps dans un module VHDL est de compter les cycles d'horloge.
Chaque design numérique a accès à un signal d'horloge stable qui oscille à une fréquence connue. Si l'horloge tourne à 100 MHz, une seconde équivaut à 100 millions de ticks d'horloge. En comptant ces ticks, nous pouvons générer de manière fiable des secondes, minutes, heures, et au-delà.
Cet article fait partie de la série Tutoriels VHDL de Base.
Nous implémentons un compteur qui s'incrémente à chaque front montant de l'horloge. Quand le compteur atteint la valeur de la fréquence d'horloge, une seconde s'est écoulée et un second compteur "Secondes" est incrémenté. Une approche similaire est utilisée pour les minutes (incrémentation après 60 secondes) et les heures (incrémentation après 60 minutes). Des compteurs additionnels peuvent être chainés pour les jours, semaines ou mois, limités seulement par les ressources FPGA/ASIC et la largeur de compteur requise.
Bien que les compteurs plus longs consomment plus de ressources logiques, ils augmentent aussi le délai de propagation. Le chemin critique à travers la chaîne de compteurs doit tenir dans la période d'horloge, sinon la synthèse échouera.
Exercice : Implémentation du minuteur
Le testbench VHDL suivant démontre une horloge simple 10 Hz pour garder le temps de simulation raisonnable. Le DUT est un minuteur qui sort les signaux Seconds, Minutes et 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
-- Horloge lente pour simulation rapide
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
);
-- Générateur d'horloge
Clk <= not Clk after ClockPeriod / 2;
-- Séquence de testbench
process is
begin
wait until rising_edge(Clk);
wait until rising_edge(Clk);
-- Relâcher le reset
nRst <= '1';
wait;
end process;
end architecture;
Voici le module minuteur lui-même. Il compte les ticks, secondes, minutes et heures, réinitialisant tous les compteurs quand le reset négatif (nRst) est activé.
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 négatif
Seconds : inout integer;
Minutes : inout integer;
Hours : inout integer
);
end entity;
architecture rtl of T18_Timer is
-- Compter les périodes d'horloge
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;
Les formes d'onde confirment le bon fonctionnement : Seconds s'incrémente à chaque tick, Minutes après 60 secondes, et Hours après 60 minutes.
En simulation, nous avons exécuté un test de 50 heures avec run 50 hr dans ModelSim, en utilisant une horloge 10 Hz pour garder le temps d'exécution gérable. Ajuster la fréquence d'horloge dans le testbench est une stratégie courante pour accélérer la vérification.
En matériel réel, la chaîne de compteurs doit se terminer dans une période d'horloge. Au fur et à mesure que la largeur du compteur augmente, le délai de propagation augmente, pouvant potentiellement dépasser la période et causer des violations de timing. La limite exacte dépend de la famille FPGA/ASIC et de la vitesse d'horloge.
Points clés à retenir
- La mesure du temps en VHDL est réalisée en comptant les cycles d'horloge.
- Baisser la fréquence d'horloge du testbench accélère la simulation sans altérer le design.
Passez au tutoriel suivant pour des fonctionnalités de minuteur avancées.
VHDL
- Créer des listes de chaînes en VHDL : Bonnes pratiques et exemple
- Créer un banc de test piloté par Tcl pour un module verrou code VHDL
- Terminer proprement une simulation de banc de test VHDL
- Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA
- Générer des nombres aléatoires en VHDL : De l'uniforme à OSVVM
- Conception d'un tampon circulaire VHDL robuste en mémoire bloc
- Comment construire un testbench auto-vérifiant en VHDL - Guide pratique
- Implémentation d'une liste chainée dynamique en VHDL avec types protégés et pointeurs d'accès
- Exploiter les procédures in-process pour un design FSM VHDL plus propre