Simulation et testbench¶
Principe du testbench¶
Un testbench est un module Verilog sans ports physiques, destiné uniquement à la simulation. Il instancie le circuit à vérifier (Device Under Test, DUT) et génère des stimuli.
┌──────────────────────────────────────┐
│ Testbench (tb_top.v) │
│ │
│ clk_gen ──────────────────────┐ │
│ rst_seq ──────────────────┐ │ │
│ sig_sim ─────────────┐ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────┐│
│ │ DUT (top_nexys4) ││
│ └──────────────────────┘│
│ │ │
│ monitor ◄────────────┘ │
└──────────────────────────────────────┘
Testbench complet¶
`timescale 1ns/1ps
module tb_top;
// ── Paramètres de simulation ──────────────────────────────
localparam CLK_PERIOD = 10; // 100 MHz → 10 ns
localparam SIG_PERIOD = 50; // signal analogique simulé 20 MHz → 50 ns
localparam N_DIV = 16; // rapport de division
localparam EXPECTED_T = SIG_PERIOD * N_DIV; // 800 ns attendus
// ── Déclarations ──────────────────────────────────────────
reg clk_100mhz;
reg rst_btn;
reg sig_bin_sim; // simule la sortie du comparateur
wire rising_pulse;
wire clk_out;
// ── Horloge système 100 MHz ───────────────────────────────
initial clk_100mhz = 1'b0;
always #(CLK_PERIOD/2) clk_100mhz = ~clk_100mhz;
// ── Signal analogique simulé à 20 MHz ─────────────────────
// (on court-circuite le XADC qui n'est pas simulable directement)
initial sig_bin_sim = 1'b0;
always #(SIG_PERIOD/2) sig_bin_sim = ~sig_bin_sim;
// ── Instanciation du détecteur de front (DUT partiel) ─────
edge_detector u_edge (
.clk (clk_100mhz),
.rst_n (~rst_btn),
.sig_in (sig_bin_sim),
.rising_edge (rising_pulse),
.falling_edge()
);
// ── Instanciation du diviseur (DUT) ───────────────────────
freq_divider #(.N(N_DIV)) u_div (
.clk (clk_100mhz),
.rst_n (~rst_btn),
.rising_pulse (rising_pulse),
.clk_out (clk_out)
);
// ── Séquence de contrôle ──────────────────────────────────
initial begin
rst_btn = 1'b1; // reset actif
#50;
rst_btn = 1'b0; // relâcher le reset
#20000; // simuler 20 µs
$display("[INFO] Fin de simulation à %0t ns", $time);
$finish;
end
// ── Vérification automatique de la période ─────────────────
real t_rise1, t_rise2, measured_T;
initial begin
@(posedge (~rst_btn)); // attendre fin de reset
@(posedge clk_out); // ignorer le 1er front (init)
@(posedge clk_out); t_rise1 = $realtime;
@(posedge clk_out); t_rise2 = $realtime;
measured_T = t_rise2 - t_rise1;
$display("──────────────────────────────────────────");
$display("Période mesurée : %0.1f ns", measured_T);
$display("Période attendue: %0d ns", EXPECTED_T);
if (measured_T == EXPECTED_T)
$display("[PASS] Diviseur ÷%0d correct.", N_DIV);
else
$display("[FAIL] Période incorrecte !");
$display("──────────────────────────────────────────");
end
// ── Dump VCD pour visualisation GTKWave ───────────────────
initial begin
$dumpfile("sim_div_freq.vcd");
$dumpvars(0, tb_top);
end
endmodule
Lancer la simulation dans Vivado¶
Ajouter
tb_top.vvia Add Sources → Add simulation sources.Dans le Flow Navigator : Run Simulation → Run Behavioral Simulation.
Dans la fenêtre Tcl Console, vérifier les messages
[PASS].Dans la fenêtre Waveform, ajouter les signaux
sig_bin_sim,rising_pulseetclk_outpour visualiser le chronogramme.
Résultats attendus en simulation¶
Signal |
Fréquence attendue |
Période attendue |
|---|---|---|
|
20 MHz |
50 ns |
|
20 MHz (1 pulse/période) |
50 ns (durée : 10 ns) |
|
1,25 MHz |
800 ns |
Note
En simulation, le signal analogique est remplacé par un carré parfait. Sur carte réelle avec XADC, la fréquence effective sera plus basse (voir Acquisition analogique — XADC).
See also
Restructuration du dépôt Git pour les recommandations d’organisation du dépôt Git contenant ces fichiers Verilog.