Le test change les commandes au front descendant et vérifie aussi au front descendant. Elles sont donc stables avant le prochain front actif et les affectations non bloquantes ont le temps d'être appliquées avant la lecture.
Comprendre un pas de simulation
Plusieurs événements peuvent porter le même temps de simulation. Au front montant :
les blocs sensibles au front sont réveillés ;
le membre droit des affectations non bloquantes est évalué ;
les nouvelles valeurs sont appliquées plus tard dans le même pas de temps.
Un test qui lit une sortie exactement dans la même région que le front peut donc observer l'ancienne valeur. Ajouter des délais arbitraires partout masque le problème sans établir une méthode solide. Il vaut mieux choisir clairement les fronts de stimulation et de vérification.
Affectations dans le testbench
Les signaux de stimulus sont généralement pilotés avec des affectations bloquantes. Les registres du DUT restent décrits avec des affectations non bloquantes. Cette séparation réduit les courses entre le test et le circuit.
Pour comparer des signaux qui peuvent contenir x ou z, === et !== rendent ces valeurs visibles. Avec ==, le résultat de la comparaison peut lui-même devenir inconnu.
Attendre un événement utile
@(posedge i_clk) attend un front. wait(o_done) attend qu'une condition devienne vraie. repeat (N) répète une action un nombre connu de fois. Un délai comme #10 avance d'une durée absolue définie par timescale.
Les attentes liées au protocole sont souvent plus robustes que les délais fixes. Par exemple, attendre o_valid résiste à un changement de latence mieux qu'attendre exactement quatre périodes.
Rendre le test auto-vérifiant
Un test utile connaît le résultat attendu et échoue tout seul. Il doit indiquer au minimum le scénario, la valeur attendue et la valeur reçue.
Les formes d'onde restent utiles pour comprendre une panne, mais elles ne doivent pas être le seul moyen de savoir si cent cas sont passés.
Prévoir les limites
Pour un compteur ou une FIFO, tester seulement quelques valeurs normales ne suffit pas. Il faut aussi couvrir le reset, le rebouclage, le plein, le vide, les demandes simultanées et les commandes maintenues plusieurs cycles.
À retenir
Le testbench crée le temps et les stimuli, il n'est pas synthétisé.
Une affectation non bloquante met à jour sa cible plus tard dans le même pas de simulation.
Stimuler et vérifier sur des fronts bien choisis évite les courses.
=== et !== détectent explicitement x et z.
Un test doit annoncer seul son succès ou son échec.