Construire un testbench auto-vérifiant
Générer une horloge, appliquer des cas, calculer le résultat attendu et arrêter la simulation sur une vraie erreur.
Un test qui décide seul
Un testbench auto-vérifiant ne demande pas de lire toutes les formes d'onde. Il applique une entrée, calcule ou récupère la valeur attendue, puis compare automatiquement la sortie du DUT.
Les formes d'onde restent utiles pour diagnostiquer un échec, mais pas pour décider manuellement si chaque test est passé.
module add_sat_tb;
timeunit 1ns;
timeprecision 1ps;
logic clk = 1'b0;
logic [7:0] a, b;
logic [7:0] result;
int unsigned checks;
always #5ns clk = ~clk;
add_sat dut (
.i_a(a),
.i_b(b),
.o_result(result)
);
function automatic logic [7:0] reference_add(
input logic [7:0] lhs,
input logic [7:0] rhs
);
logic [8:0] wide;
wide = {1'b0, lhs} + {1'b0, rhs};
return wide[8] ? 8'hFF : wide[7:0];
endfunction
task automatic check_case(
input logic [7:0] lhs,
input logic [7:0] rhs
);
logic [7:0] expected;
a = lhs;
b = rhs;
#1ns;
expected = reference_add(lhs, rhs);
assert (result === expected)
else $fatal(1, "a=%0d b=%0d got=%0d expected=%0d",
lhs, rhs, result, expected);
checks++;
endtask
initial begin
check_case(0, 0);
check_case(10, 20);
check_case(200, 100);
check_case(255, 255);
$display("PASS: %0d checks", checks);
$finish;
end
endmoduleComparer avec le bon opérateur
=== compare aussi X et Z. Dans un contrôle de résultat, il évite qu'une inconnue produise elle-même un résultat de comparaison inconnu et passe inaperçue dans une condition mal écrite.
Une politique utile consiste à refuser tout X inattendu sur les sorties contrôlées. Si une inconnue est autorisée par le protocole, elle doit être traitée explicitement.
Respecter le moment d'échantillonnage
Le petit délai #1ns convient ici à une sortie purement combinatoire dans un testbench. Pour un DUT synchrone, le test doit appliquer les entrées avant le front prévu puis observer la sortie dans une région de simulation qui évite les courses.
Un clocking block peut définir les décalages d'application et d'échantillonnage. À défaut, une convention stricte entre front d'application et front de lecture est nécessaire.
Messages utiles et bilan
Un échec doit indiquer le scénario, la valeur reçue et la valeur attendue. Un compteur de contrôles et un message final empêchent une simulation vide d'être prise pour un succès.
Pour une campagne plus grande, éviter $fatal au premier écart peut être utile afin de collecter plusieurs erreurs. Il faut alors compter les échecs et terminer avec un statut non nul si le compteur n'est pas zéro.
À retenir
- Le testbench calcule et contrôle les résultats sans lecture manuelle des formes d'onde.
===repère clairement les valeurs inconnues.- Le moment d'application et d'échantillonnage doit être défini.
- Les messages d'erreur doivent permettre de reproduire le cas.
- Un bilan final distingue une vraie réussite d'une simulation qui n'a rien testé.
📝 Tester mes connaissances - Quiz du chapitre