Testbenches et Simulations
Écrire des testbenches VHDL pour vérifier le comportement de vos circuits avant synthèse.
Qu'est-ce qu'un testbench ?
Un testbench (TB) est un fichier VHDL de simulation qui :
- Instancie le composant sous test (DUT - Device Under Test)
- Génère les stimuli (signaux d'entrée)
- Observe et vérifie les sorties
Un testbench n'a pas de ports - c'est un environnement fermé.
entity tb_mux4to1 is
-- Pas de port !
end entity tb_mux4to1;Structure type d'un testbench
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity tb_mux4to1 is
end entity tb_mux4to1;
architecture tb of tb_mux4to1 is
-- Constantes de simulation
constant c_CLK_PERIOD : time := 10 ns; -- 100 MHz
-- Signaux pour connecter au DUT
signal w_d0, w_d1, w_d2, w_d3 : std_logic := '0';
signal w_sel : std_logic_vector(1 downto 0) := "00";
signal w_y : std_logic;
begin
-- Instanciation du DUT
DUT : entity work.mux4to1
port map (
i_d0 =>
Génération d'horloge
-- Process de génération d'horloge
p_clk : process
begin
i_clk <= '0';
wait for c_CLK_PERIOD / 2;
i_clk <= '1';
wait for c_CLK_PERIOD / 2;
end process p_clk;
-- Alternative concurrente
i_clk <= not i_clk after c_CLK_PERIOD / 2;Testbench complet pour circuit séquentiel
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity tb_counter is
end entity tb_counter;
architecture tb of tb_counter is
constant c_CLK_PERIOD : time := 10 ns;
signal i_clk : std_logic := '0';
signal i_rst : std_logic := '1';
signal o_cnt : std_logic_vector(3 downto 0);
begin
-- Génération horloge
i_clk <= not i_clk after c_CLK_PERIOD / 2;
-- DUT
DUT : entity work.counter_4bit
port map
Instructions de simulation utiles
| Instruction | Utilisation |
|---|---|
wait for 10 ns; | Attendre une durée fixe |
wait until rising_edge(i_clk); | Attendre un front d'horloge |
wait until i_valid = '1'; | Attendre une condition |
wait; | Arrêter la simulation |
assert condition report "msg" severity level; | Vérification |
Niveaux de sévérité
| Niveau | Effet |
|---|---|
note | Message informatif |
warning | Avertissement, simulation continue |
error | Erreur, simulation peut continuer |
failure | Arrêt immédiat de la simulation |
Factoriser les vérifications
Quand un testbench grandit, il vaut mieux éviter de recopier la même assertion partout. Une petite procédure locale rend les messages plus réguliers.
Déclaration (dans la zone déclarative de l'architecture du testbench, avant le begin, au même endroit que les constantes et signaux de simulation) :
-- Avant le begin de l'architecture tb
procedure check_slv(
constant i_name : in string;
constant i_observed : in std_logic_vector;
constant i_expected : in std_logic_vector
) is
begin
assert i_observed = i_expected
report i_name
& " attendu=0x" & to_hstring(i_expected)
& " obtenu=0x" & to_hstring(i_observed)
severity error;
end procedure check_slv;Utilisation (dans un process de test, après le begin de l'architecture) :
wait until rising_edge(i_clk);
check_slv("compteur apres reset", o_cnt, x"0");Le testbench reste simple à lire : les stimuli décrivent le scénario, les procédures de vérification décrivent les règles attendues. Si la procédure doit être partagée entre plusieurs testbenches, elle peut ensuite être déplacée dans un package.
Fin de simulation avec std.env
Avec VHDL-2008, std.env.finish permet de terminer proprement une simulation quand le scénario est terminé.
library STD;
use STD.ENV.ALL;
-- ...
report "Testbench termine avec succes" severity note;
finish;wait; reste acceptable pour un petit testbench. finish est plus clair quand la simulation est lancée automatiquement par un script ou une CI.
Bonnes pratiques
- Nommer les assertions : message clair pour identifier l'échec
- Vérifier après stabilisation : attendre
wait foravantassert - Tester les cas limites : valeurs min/max, transitions d'états
- Séparer stimuli et vérification : process distincts pour clarté
- Fin explicite : terminer par
report "... succès"puiswait;oufinish;
📝 Tester mes connaissances - Quiz du chapitre