-- Process de génération d'horlogep_clk : processbegin i_clk <= '0'; wait for c_CLK_PERIOD / 2; i_clk <= '1'; wait for c_CLK_PERIOD / 2;end process p_clk;-- Alternative concurrentei_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 isend 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 ( i_clk => i_clk, i_rst => i_rst, o_cnt => o_cnt ); -- Stimuli p_test : process begin -- Reset actif pendant 3 cycles i_rst <= '1'; wait for 3 * c_CLK_PERIOD; assert unsigned(o_cnt) = 0 report "Reset raté" severity error; -- Démarrage comptage i_rst <= '0'; wait for 5 * c_CLK_PERIOD; assert unsigned(o_cnt) = 5 report "Comptage incorrect" severity error; -- Attendre l'overflow (16 cycles total = 0) wait for 11 * c_CLK_PERIOD; assert unsigned(o_cnt) = 0 report "Overflow incorrect" severity error; report "Testbench terminé avec succès" severity note; wait; end process p_test;end architecture tb;
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 tbprocedure check_slv( constant i_name : in string; constant i_observed : in std_logic_vector; constant i_expected : in std_logic_vector) isbegin 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 for avant assert
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" puis wait; ou finish;