Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> VHDL

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

Passez au tutoriel suivant pour des fonctionnalités de minuteur avancées.

VHDL

  1. Créer des listes de chaînes en VHDL : Bonnes pratiques et exemple
  2. Créer un banc de test piloté par Tcl pour un module verrou code VHDL
  3. Terminer proprement une simulation de banc de test VHDL
  4. Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA
  5. Générer des nombres aléatoires en VHDL : De l'uniforme à OSVVM
  6. Conception d'un tampon circulaire VHDL robuste en mémoire bloc
  7. Comment construire un testbench auto-vérifiant en VHDL - Guide pratique
  8. Implémentation d'une liste chainée dynamique en VHDL avec types protégés et pointeurs d'accès
  9. Exploiter les procédures in-process pour un design FSM VHDL plus propre