Créer un banc de test piloté par Tcl pour un module verrou code VHDL
La plupart des simulateurs VHDL exposent le Tool Command Language (Tcl) comme interface de script principale. Lorsque vous tapez une commande dans la console du simulateur, vous utilisez Tcl, et vous pouvez aussi écrire des scripts qui pilotent et observent votre conception VHDL.
Cet article vous guide dans la construction d'un banc de test auto-vérifiant qui utilise Tcl — plutôt que VHDL — pour vérifier le comportement d'un simple module verrou code. Le résultat est un harnais de test clair, maintenable, qui peut être exécuté, modifié et réutilisé sans recompiler le VHDL.
Voir aussi :
Téléchargez le code et les fichiers de projet ModelSim ci-dessous.
Le DUT : Un module verrou code en VHDL
Avant de plonger dans le banc de test, passons en revue le Device Under Test (DUT). Le module émule un verrou simple qui ouvre un coffre-fort quand la bonne séquence numérique est entrée sur un clavier numérique.
Bien que beaucoup appellent un tel dispositif un « combination lock », le terme correct est « permutation lock » — l'ordre des chiffres importe. Pour la clarté, nous l'appellerons code lock tout au long.

L'illustration ci-dessus montre un coffre-fort d'hôtel typique. Pour simplifier, notre conception utilise seulement des touches numériques et omet les boutons CLEAR et LOCK.
Comment fonctionne le module verrou code
Le verrou commence dans un état verrouillé. Quand un utilisateur entre quatre chiffres consécutifs qui correspondent au PIN secret, le verrou s'ouvre. Entrer une séquence incorrecte reverrouille le dispositif. Ce comportement est implémenté comme un détecteur de séquence simple en VHDL.
La forme d'onde illustre le timing du module. En plus de l'horloge et du reset, le module accepte deux entrées : input_digit (un entier 0–9) et input_enable (un std_logic). Le DUT échantillonne le chiffre sur un front montant d'horloge quand enable est haut.
La seule sortie est unlock, un std_logic qui passe à haut seulement quand les quatre chiffres consécutifs correspondent au PIN correct. Dans cet exemple, le code secret est 1234.
L'entité
La définition d'entité suivante code en dur le PIN secret via des génériques. Chaque générique est un entier dans l'intervalle 0–9, représentant un chiffre BCD (Binary Coded Decimal).
entity code_lock is generic (pin0, pin1, pin2, pin3 : integer range 0 to 9); port ( clk : in std_logic; rst : in std_logic; input_digit : in integer range 0 to 9; input_enable : in std_logic; unlock : out std_logic ); end code_lock;
La région déclarative
Le module utilise un seul signal interne — un registre à décalage 4 bits qui stocke les derniers chiffres entrés. Nous permettons au registre de contenir des valeurs de –1 à 9. La valeur spéciale –1 est utilisée pour l'état de reset, assurant qu'un PIN de 0000 ne déverrouille pas le verrou par défaut.
type pins_type is array (0 to 3) of integer range -1 to 9; signal pins : pins_type;
L'implémentation
L'architecture inclut une affectation combinatoire qui met unlock à haut quand le registre à décalage correspond aux valeurs de PIN génériques. Comme pins est horlogé, unlock change seulement sur un front montant d'horloge.
unlock <= '1' when pins = (pin3, pin2, pin1, pin0) else '0';
Le processus suivant implémente le registre à décalage. Au reset, toutes les entrées sont mises à –1. Quand input_enable est haut sur un front montant, le chiffre courant est stocké en position 0, et les chiffres précédents décalent vers la droite.
PINS_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then pins <= (others => -1); else if input_enable = '1' then pins(0) <= input_digit; pins(1 to 3) <= pins(0 to 2); end if; end if; end if; end process;
Le banc de test VHDL
Même si nous utiliserons Tcl pour la logique de vérification, nous avons toujours besoin d'un banc de test VHDL de base pour générer les signaux d'horloge et de reset. Voici le fichier complet du banc de test VHDL.
library ieee; use ieee.std_logic_1164.all; entity code_lock_tb is end code_lock_tb; architecture sim of code_lock_tb is constant clk_hz : integer := 100e6; constant clock_period : time := 1 sec / clk_hz; signal clk : std_logic := '1'; signal rst : std_logic := '1'; signal input_digit : integer range 0 to 9; signal input_enable : std_logic := '0'; signal unlock : std_logic; begin clk <= not clk after clock_period; DUT : entity work.code_lock(rtl) generic map (1,2,3,4) port map ( clk => clk, rst => rst, input_digit => input_digit, input_enable => input_enable, unlock => unlock ); end architecture;
Le banc de test Tcl
Voici un script Tcl qui s'exécute dans ModelSim. Si vous utilisez Vivado ou un autre simulateur, de légers ajustements seront nécessaires, car certaines commandes sont spécifiques au simulateur. Reportez-vous au ModelSim Command Reference Manual pour les détails.
Téléchargez le projet exemple en utilisant le formulaire ci-dessous.
Utilisation d'un espace de noms
L'encapsulation du script dans un espace de noms empêche les conflits accidentels avec les variables globales. Tout le code Tcl réside dans l'espace de noms codelocktb.
namespace eval ::codelocktb { # Tout le code Tcl ici }
Initialisation de la simulation
Nous démarrons la simulation avec vsim et chargeons le fichier de forme d'onde s'il existe.
# Charger la simulation vsim work.code_lock_tb # Charger la forme d'onde if {[file exists wave.do]} { do wave.do }
Importation des valeurs VHDL dans Tcl
En utilisant la commande examine de ModelSim, nous lisons la constante clock_period et les génériques PIN. L'extrait suivant extrait la valeur numérique et l'unité de temps.
variable clockPeriod [examine clock_period] variable clockPeriod [string trim $clockPeriod "{}"] variable timeUnits [lindex $clockPeriod 1] variable clockPeriod [lindex $clockPeriod 0] variable pinCode [examine dut.pin0 dut.pin1 dut.pin2 dut.pin3]
Nous initialisons aussi une variable errorCount pour suivre les échecs.
variable errorCount 0
Affichage avec horodatage
La commande echo affiche les messages dans la console ModelSim sur toutes les plateformes. La procédure suivante préfixe chaque message avec le temps de simulation courant.
proc printMsg { msg } { global now variable timeUnits echo $now $timeUnits: $msg }
Exécution pour un nombre spécifié de cycles d'horloge
Puisque le DUT est sensible à l'horloge, nous avançons le temps par multiples de la période d'horloge.
proc runClockCycles { count } { variable clockPeriod variable timeUnits set t [expr {$clockPeriod * $count}] run $t $timeUnits }
Vérification des valeurs de signaux
La procédure checkSignal compare un signal VHDL à une valeur attendue, signalant une erreur s'ils diffèrent.
proc checkSignal { signalName expectedVal } { variable errorCount set val [examine $signalName] if {$val != $expectedVal} { printMsg "ERROR: $signalName=$val (expected=$expectedVal)" incr errorCount } }
Simulation de l'entrée du PIN
Cette procédure pilote les entrées du DUT pour simuler un utilisateur entrant un PIN à 4 chiffres. Elle vérifie la sortie unlock une fois que les quatre chiffres ont été appliqués.
proc tryPin { digits } { variable pinCode set pinStatus "incorrect" if { $digits == $pinCode } { set pinStatus "correct" } printMsg "Entering $pinStatus PIN code: $digits" foreach i $digits { force input_digit $i -deposit force input_enable 1 -deposit runClockCycles 1 force input_enable 0 -deposit runClockCycles 1 } if { $pinStatus == "correct" } { checkSignal unlock 1 } else { checkSignal unlock 0 } }
Séquence de test et rapport de résultats
Après une brève période d'initialisation, le script libère le reset et exécute plusieurs cas de test : deux cas limites (0000 et 9999), le PIN correct, et la séquence de PIN inversée. Il rapporte ensuite le résultat global.
runClockCycles 10 force rst '0' -deposit runClockCycles 1 printMsg "Checking reset value" checkSignal unlock 0 tryPin {0 0 0 0} tryPin {9 9 9 9} tryPin $pinCode tryPin [lreverse $pinCode] if { $errorCount == 0 } { printMsg "Test: OK" } else { printMsg "Test: Failure ($errorCount errors)" }
Exécution du banc de test
Exécutez le script avec la commande suivante dans ModelSim :
source code_lock/code_lock_tb.tcl
Une exécution réussie produit une sortie similaire à la suivante, avec des horodatages précédant chaque message.
VSIM> source code_lock/code_lock_tb.tcl # vsim # 110 ns: Checking reset value # 110 ns: Entering incorrect PIN code: 0 0 0 0 # 190 ns: Entering incorrect PIN code: 9 9 9 9 # 270 ns: Entering correct PIN code: 1 2 3 4 # 350 ns: Entering incorrect PIN code: 4 3 2 1 # 430 ns: Test: OK
Si le DUT contient un défaut (par ex., une faute de frappe dans l'affectation unlock), le script signale l'échec et le compte d'erreurs.
VSIM> source code_lock/code_lock_tb.tcl # vsim # 110 ns: Checking reset value # 110 ns: Entering incorrect PIN code: 0 0 0 0 # 190 ns: Entering incorrect PIN code: 9 9 9 9 # 270 ns: Entering correct PIN code: 1 2 3 4 # 350 ns: ERROR: unlock=0 (expected=1) # 350 ns: Entering incorrect PIN code: 4 3 2 1 # 430 ns: Test: Failure (1 errors)
Réflexions finales
Tout au long de ma carrière, j'ai écrit de nombreux bancs de test basés sur Tcl. Ils offrent des avantages uniques : tests interactifs, capacité de modifier le harnais de test sans recompiler, et une couche de vérification supplémentaire qui protège contre les bogues tant dans la conception que dans le banc de test.
Cependant, il y a des compromis. Les scripts Tcl s'exécutent nettement plus lentement que les bancs de test VHDL purs, et le langage peut être fragile — les erreurs sont difficiles à attraper tôt, et le débogage est moins intuitif que dans des langages de plus haut niveau comme Python.
Malgré ces inconvénients, Tcl reste le langage de colle de facto pour l'outillage FPGA et la simulation. Si vous travaillez avec Xilinx Vivado, Intel Quartus ou Mentor Graphics Questa, maîtriser Tcl portera ses fruits. N'hésitez pas à partager vos expériences dans les commentaires ci-dessous.
VHDL
- Créer des listes de chaînes en VHDL : Bonnes pratiques et exemple
- Terminer proprement une simulation de banc de test VHDL
- Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA
- Conception d'un tampon circulaire VHDL robuste en mémoire bloc
- Améliorer la vérification matérielle avec un testbench interactif basé sur Tcl
- Comment construire un testbench auto-vérifiant en VHDL - Guide pratique
- Implémentation d'une liste chainée dynamique en VHDL avec types protégés et pointeurs d'accès
- Maîtriser les fonctions VHDL : Guide pratique pour un design efficace
- Installation gratuite d'un simulateur et éditeur VHDL : guide étudiant