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

Utilisation des procédures en VHDL : Simplifiez votre design avec du code réutilisable

En VHDL, les procédures sont des sous-programmes qui permettent aux concepteurs d'éviter les blocs de code répétitifs. Quand la même opération est nécessaire à plusieurs endroits, créer un module complet peut être excessif. Une procédure offre une solution légère et réutilisable.

Les procédures peuvent être déclarées dans n'importe quelle région déclarative - architecture, package ou processus - et leur portée est limitée à cette région. Quand elles sont invoquées, le corps de la procédure est exécuté comme si son code était écrit sur place, vous donnant les avantages de la modularité sans la surcharge d'un composant séparé.

Contrairement aux fonctions, les procédures ne retournent pas de valeur directement. Cependant, vous pouvez renvoyer des valeurs en déclarant des signaux out ou inout dans la liste de paramètres, permettant effectivement à la procédure d'agir comme un petit module avec entrées et sorties.

Cet article fait partie de la série Tutoriels VHDL de Base.

La syntaxe canonique pour définir une procédure est illustrée ci-dessous :

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 liste de paramètres définit les entrées et sorties de la procédure - un peu comme un mini-module. Les paramètres peuvent être des signaux, des variables ou des constantes. À l'intérieur de la procédure, vous pouvez déclarer des objets additionnels (constantes, variables, types, sous-types, alias) qui sont valides seulement dans ce bloc ; les signaux ne peuvent pas être déclarés localement.

Puisque les procédures peuvent contenir des instructions wait, elles sont particulièrement utiles dans les testbench - par exemple, comme drivers BFM simples ou pour vérifier les sorties du DUT.

Exercice

Dans le tutoriel précédent, un module minuteur a été construit en utilisant des instructions if-then-else profondément imbriquées. Chaque niveau imbriqué ajoutait de la complexité et réduisait la lisibilité, même si la même opération était effectuée sur différents ensembles de signaux. Une meilleure approche est d'encapsuler la logique répétitive dans une procédure.

Le tutoriel vidéo suivant guide la création d'une procédure VHDL :

Exemple : Minuteur basé sur procédure

Le code du testbench reste inchangé, sauf pour l'ajout d'un appel de procédure pour piloter le DUT :

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
  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
  i_Timer : entity work.T19_Timer(rtl)
    generic map(ClockFrequencyHz => ClockFrequencyHz)
    port map (
      Clk => Clk,
      nRst => nRst,
      Seconds => Seconds,
      Minutes => Minutes,
      Hours => Hours
    );
    
  Clk <= not Clk after ClockPeriod / 2;
  
  process is
  begin
    wait until rising_edge(Clk);
    wait until rising_edge(Clk);
    nRst <= '1';
    wait;
  end process;
end architecture;

Le module minuteur lui-même exploite maintenant une procédure pour l'incrémentation du compteur :

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; -- Reset négatif
    Seconds : inout integer;
    Minutes : inout integer;
    Hours : inout integer
  );
end entity;

architecture rtl of T19_Timer is
  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 nRst = '0' then
        Ticks <= 0;
        Seconds <= 0;
        Minutes <= 0;
        Hours <= 0;
      else
        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 forme d'onde ci-dessous confirme que le compteur de minutes se réinitialise correctement quand le minuteur atteint 60 minutes :

Utilisation des procédures en VHDL : Simplifiez votre design avec du code réutilisable

Analyse

D'après la forme d'onde, nous voyons que la fonctionnalité de retour à zéro se comporte identiquement à l'implémentation originale avec if imbriqués. Le changement est purement structurel - pas de changement à la logique sous-jacente.

Le premier paramètre, Counter, est un signal inout, permettant à la procédure de lire et mettre à jour sa valeur. Le second et troisième paramètres, WrapValue et Enable, sont des constantes ; ils sont traités comme des constantes à la compilation à l'intérieur de la procédure.

Le paramètre final, Wrapped, est une variable déclarée comme out. Elle sert de pseudo valeur de retour, indiquant si le compteur s'est réinitialisé lors de cet appel.

Dans le processus principal, quatre appels successifs à IncrementWrap font cascader les compteurs. La variable Wrap de l'appel précédent alimente l'entrée Enable de l'appel suivant. L'utilisation d'une variable est essentielle ici car les mises à jour de signaux ne sont visibles qu'après que le processus se suspende ; une variable fournit un flux de données procédural immédiat.

Utilisation des procédures en VHDL : Simplifiez votre design avec du code réutilisable

À retenir

Passez au tutoriel suivant »

VHDL

  1. Exemple de procédure VHDL : incrémenter un std_logic_vector
  2. Comment le molybdène façonne l'industrie moderne : usages, avantages et dynamiques d'approvisionnement
  3. Créer des listes de chaînes en VHDL : Bonnes pratiques et exemple
  4. Terminer proprement une simulation de banc de test VHDL
  5. Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA
  6. Générer des nombres aléatoires en VHDL : De l'uniforme à OSVVM
  7. Exploiter les procédures in-process pour un design FSM VHDL plus propre
  8. Maîtriser les fonctions VHDL : Guide pratique pour un design efficace
  9. Maîtriser les techniques de la rectifieuse d'outils : guide pratique