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

Comment utiliser une procédure en VHDL

Une procédure est un type de sous-programme en VHDL qui peut nous aider à éviter de répéter du code. Parfois, le besoin se fait sentir d'effectuer des opérations identiques à plusieurs endroits tout au long de la conception. Bien que la création d'un module puisse être exagérée pour des opérations mineures, une procédure est souvent ce que vous voulez.

Les procédures peuvent être déclarées dans n'importe quelle région déclarative. La portée de la procédure sera limitée à l'endroit où elle est déclarée, architecture, package ou processus. Chaque fois que vous appelez la procédure, elle se comporte comme si le code de la procédure avait été inséré à l'endroit d'où elle a été appelée.

Une procédure ne renvoie pas une valeur comme le fait une fonction, mais vous pouvez renvoyer des valeurs en déclarant out ou inout signaux dans la liste des paramètres.

Cet article de blog fait partie de la série de didacticiels VHDL de base.

La syntaxe de base pour créer une procédure est :
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 des paramètres d'une procédure définit ses entrées et ses sorties, un peu comme un mini-module. Il peut s'agir d'un signal ou d'une constante, mais contrairement à un module, il peut également s'agir d'une variable. Vous pouvez déclarer des objets entre les mots clés "is" et "begin" qui ne sont valides qu'à l'intérieur de la procédure. Ceux-ci peuvent inclure des constantes, des variables, des types, des sous-types et des alias, mais pas des signaux.

Contrairement aux fonctions, les procédures peuvent contenir des instructions d'attente. Par conséquent, ils sont souvent utilisés dans des bancs de test comme de simples BFM pour simuler des interfaces ou pour vérifier la sortie de l'appareil sous test (DUT).

Exercice

Dans le didacticiel précédent, nous avons créé un module de minuterie à l'aide d'instructions imbriquées If-Then-Else. Chaque niveau de If-Then-Else à l'intérieur d'un autre If-Then-Else ajoute de la complexité à la conception et devient moins lisible. À chaque niveau de logique, nous effectuons essentiellement la même opération sur un ensemble de signaux différent. N'y a-t-il pas une meilleure façon de procéder ?

Dans ce tutoriel vidéo, nous allons apprendre à créer une procédure en VHDL :

Le code final de la procédure 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;

Le code final pour le module de la minuterie à l'aide d'une procédure :

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 fenêtre de forme d'onde dans ModelSim, zoomée sur la timeline où le Minutes le signal est en train de s'envelopper :

Analyse

Nous pouvons voir sur la forme d'onde que l'enveloppement des signaux fonctionne toujours comme dans le didacticiel précédent. C'est parce que nous n'avons pas réellement changé la fonction sur le module, seulement la façon dont elle est implémentée.

Le premier élément de la liste des paramètres pour le IncrementWrap la procédure est le Counter signal. Il est déclaré en utilisant la direction inout pour que la procédure puisse à la fois lire et définir sa valeur.

Les deuxième et troisième éléments de la liste des paramètres sont des constantes. Cela signifie que les valeurs que vous mettez ici apparaîtront comme des constantes à l'intérieur de la procédure. Le WrapValue saisie avec le Enable l'entrée détermine si le Counter le signal est incrémenté ou encapsulé.

Le dernier élément de la liste des paramètres est une variable avec la direction out . Le but de cette sortie est d'informer l'appelant de la procédure que le compteur a enveloppée. Nous l'utilisons ici un peu comme une valeur de retour.

Dans le processus principal, nous avons quatre appels au IncrementWrap procédure. Chacun des appels suivants utilise le Wrap variable pour activer le comptage. Cela n'aurait pas fonctionné si nous avions utilisé un signal au lieu d'une variable, car les valeurs de signal ne sont mises à jour que lorsqu'un processus se met en veille. Nous avons besoin que la valeur de sortie d'un appel de procédure soit utilisée comme entrée pour un appel sur la ligne suivante. Il doit donc s'agir d'une variable.

À emporter

Aller au tutoriel suivant »


VHDL

  1. Instruction de procédure - Exemple VHDL
  2. Comment utilisons-nous le molybdène?
  3. Comment créer une liste de chaînes en VHDL
  4. Comment arrêter la simulation dans un testbench VHDL
  5. Comment créer un contrôleur PWM en VHDL
  6. Comment générer des nombres aléatoires en VHDL
  7. Comment utiliser une procédure dans un processus en VHDL
  8. Comment utiliser une fonction en VHDL
  9. Comment utiliser une meuleuse de coupe