Comment utiliser les constantes et la carte générique en VHDL
La création de modules est un excellent moyen de réutiliser le code, mais vous avez souvent besoin du même module avec de plus petites variations tout au long de votre conception. C'est à cela que servent les génériques et la carte générique. Il vous permet de rendre certaines parties du module configurables au moment de la compilation.
Les constantes sont utilisées lorsque nous voulons éviter de taper la même valeur encore et encore. Ils peuvent être utilisés pour définir les largeurs de bits des vecteurs de signal au moment de la compilation, et ils peuvent même être également mappés sur des constantes génériques. Les constantes peuvent être utilisées à la place des signaux et des variables n'importe où dans le code, mais leurs valeurs ne peuvent pas être modifiées après la compilation.
Cet article de blog fait partie de la série de didacticiels VHDL de base.
Dans le tutoriel précédent, nous avons créé un module multiplexeur à 4 entrées avec une largeur de bus de 8 bits. Mais que se passe-t-il si nous avons également besoin d'un MUX similaire avec une largeur de bus différente ? La seule solution est-elle de copier-coller le code dans un nouveau module, et de changer les chiffres ?
Heureusement, non.
Il est possible de créer des constantes en VHDL en utilisant cette syntaxe :constant <constant_name> : <type> := <value>;
Les constantes peuvent être déclarées avec des signaux dans la partie déclarative d'un fichier VHDL, ou elles peuvent être déclarées avec des variables dans un processus.
Les constantes peuvent être passées dans un module via l'entité en utilisant le generic
mot-clé. La syntaxe pour créer une entité pour un module qui accepte les constantes génériques est :entity <entity_name> is
generic(
<entity_constant_name> : <type> [:= default_value];
...
);
port(
<entity_signal_name> : in|out|inout <type>;
...
);
end entity;
La syntaxe pour instancier un module générique dans un autre fichier VHDL est :<label> : entity <library_name>.<entity_name>(<architecture_name>)
generic map(
<entity_constant_name> => <value_or_constant>,
...
)
port map(
<entity_signal_name> => <local_signal_name>,
...
);
Exercice
Dans ce tutoriel vidéo, nous allons apprendre à créer et instancier un module avec des constantes génériques en VHDL :
Le code final pour le testbench MUX générique :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T16_GenericMapTb is end entity; architecture sim of T16_GenericMapTb is constant DataWidth : integer := 8; signal Sig1 : signed(DataWidth-1 downto 0) := x"AA"; signal Sig2 : signed(DataWidth-1 downto 0) := x"BB"; signal Sig3 : signed(DataWidth-1 downto 0) := x"CC"; signal Sig4 : signed(DataWidth-1 downto 0) := x"DD"; signal Sel : signed(1 downto 0) := (others => '0'); signal Output : signed(DataWidth-1 downto 0); begin -- An Instance of T16_GenericMux with architecture rtl i_Mux1 : entity work.T16_GenericMux(rtl) generic map(DataWidth => DataWidth) port map( Sel => Sel, Sig1 => Sig1, Sig2 => Sig2, Sig3 => Sig3, Sig4 => Sig4, Output => Output); -- Testbench process process is begin wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= "UU"; wait; end process; end architecture;
Le code final pour le module MUX générique :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T16_GenericMux is generic(DataWidth : integer); port( -- Inputs Sig1 : in signed(DataWidth-1 downto 0); Sig2 : in signed(DataWidth-1 downto 0); Sig3 : in signed(DataWidth-1 downto 0); Sig4 : in signed(DataWidth-1 downto 0); Sel : in signed(1 downto 0); -- Outputs Output : out signed(DataWidth-1 downto 0)); end entity; architecture rtl of T16_GenericMux is begin process(Sel, Sig1, Sig2, Sig3, Sig4) is begin case Sel is when "00" => Output <= Sig1; when "01" => Output <= Sig2; when "10" => Output <= Sig3; when "11" => Output <= Sig4; when others => -- 'U', 'X', '-', etc. Output <= (others => 'X'); end case; end process; end architecture;
La fenêtre de forme d'onde dans ModelSim après avoir appuyé sur run et zoomé sur la timeline :
Analyse
Nous avons créé un module MUX avec une largeur de bus configurable. Désormais, la largeur du bus est spécifiée à un seul endroit, dans le fichier testbench. Nous pouvons facilement le changer pour créer un MUX avec une largeur de bus différente.
Si nous comparons la forme d'onde à celle du tutoriel précédent, nous pouvons voir que le comportement est identique. C'est parce que nous n'avons pas du tout changé le comportement du code.
À emporter
- Les constantes peuvent être utilisées pour éviter de coder en dur des valeurs à plusieurs endroits
- Les génériques peuvent être utilisés pour rendre les modules plus adaptables
Aller au tutoriel suivant »
VHDL
- Comment utiliser une procédure dans un processus en VHDL
- Comment utiliser une fonction impure en VHDL
- Comment utiliser une fonction en VHDL
- Comment utiliser une procédure en VHDL
- Comment utiliser les constantes et la carte générique en VHDL
- Comment utiliser l'instanciation de Port Map dans VHDL
- Comment utiliser une instruction Case-When en VHDL
- Comment installer un simulateur et un éditeur VHDL gratuitement
- Microcontrôleur PIC18 :qu'est-ce que c'est et comment l'utiliser