Menu

$dumpfile i $dumpvars w Verilogu: przebiegi VCD

Jak dodać do testbencha zapis przebiegów VCD: $dumpfile, $dumpvars, wybór zakresu i jak obejrzeć wynikowy plik w GTKWave albo w edytorze w przeglądarce.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Przebieg, którego naprawdę potrzebujesz

$display wypisuje tekst. To wystarcza do szybkiego sprawdzenia, ale gdy debugujesz licznik z problemem czasowym albo zablokowaną maszynę stanów, potrzebujesz obrazu: sygnałów narysowanych jako napięcia w czasie, z przewijaniem, powiększaniem i kursorem, który możesz postawić przy dowolnej zmianie.

Takim obrazem jest plik VCD ("value change dump"), format tekstowy ustandaryzowany przez IEEE już w pierwotnej specyfikacji Veriloga. Każdy współczesny symulator potrafi go zapisać, a każda współczesna przeglądarka przebiegów potrafi go odczytać. Koszt jego utworzenia to dwie linie w testbenchu.

Dwie linie

W bloku initial (zwykle tym samym, który zawiera pobudzenie) dodaj:

$dumpfile("dump.vcd");
$dumpvars(0, test);
  • $dumpfile nadaje nazwę plikowi wyjściowemu. Podaj dowolną ścieżkę. Jeśli nie zawiera katalogu, plik trafi do katalogu roboczego symulatora.
  • $dumpvars(0, test) oznacza "zapisuj każdy sygnał w zakresie test i w każdym podzakresie, rekurencyjnie, bez limitu głębokości".

To cała konfiguracja. Uruchom symulację, a dostaniesz plik dump.vcd, który otworzysz w GTKWave albo w zakładce Waveform edytora w przeglądarce.

Kompletny przykład

Uruchom go. Zakładka Waveform pokazuje teraz trzy sygnały, clk, reset i count, narysowane przez cały czas symulacji. Możesz postawić kursor w dowolnym punkcie i odczytać wartości sygnałów w tej chwili. Możesz też zaznaczyć fragment, żeby powiększyć jeden cykl zegara.

Co robi pierwszy argument $dumpvars

$dumpvars(depth, scope) przechodzi przez scope i każdą zawartą w nim podinstancję, zapisując sygnały do głębokości depth poziomów. Możliwe wartości głębokości:

  • 0: bez limitu. Zapisywany jest każdy sygnał w scope i we wszystkich zagnieżdżonych podmodułach.
  • 1: tylko sygnały zadeklarowane bezpośrednio w scope. Podmoduły nie są zapisywane.
  • 2: scope plus jeden poziom podmodułów.
  • N: scope plus N-1 poziomów podmodułów.

W praktyce prawie każdy testbench używa $dumpvars(0, test). Zapisanie wszystkiego jest tanie (VCD przechowuje tylko zmiany, a nie stany ustalone), a w połowie debugowania nie chcesz odkryć, że potrzebny sygnał nie został zapisany.

Jeśli projekt jest naprawdę duży i plik VCD robi się zbyt wielki, możesz zapisywać wybiórczo:

$dumpvars(0, dut.inner_module);     // just the interesting sub-module
$dumpvars(0, dut.regs);             // just the register file

$dumpvars możesz wywołać kilka razy, żeby zebrać kilka zakresów.

Zapis wybranych sygnałów

$dumpvars może też przyjąć listę konkretnych sygnałów zamiast całego zakresu:

$dumpvars(0, test.clk, test.reset, dut.count);

To zapisuje tylko te trzy sygnały. Przydaje się, gdy projekt jest ogromny, a interesuje cię tylko kilka sygnałów. W małych projektach prościej jest zapisać wszystko.

Sterowanie zapisem w trakcie symulacji

Z $dumpvars współpracują jeszcze dwa zadania:

  • $dumpoff: wstrzymuje zapis. Kolejne zmiany nie trafiają do VCD.
  • $dumpon: wznawia zapis.
initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, test);

    // ... interesting region ...

    #1000 $dumpoff;
    // ... long boring region we don't want in the VCD ...
    #5000 $dumpon;

    // ... another interesting region ...
end

W ten sposób pomijasz nudny fragment długiego testu typu "działa przez milion cykli" i nie tworzysz pliku VCD o rozmiarze 5 GB.

Oglądanie wyniku

Są dwa główne sposoby:

W edytorze w przeglądarce

Edytor na tej stronie wyświetla pliki VCD bezpośrednio. Uruchom symulację i przejdź do zakładki Waveform. Sygnały pojawią się z hierarchią w jednej części i przesuwanym kursorem w drugiej. Kliknij w dowolnym miejscu przebiegu, żeby postawić kursor: pokaże on wartości sygnałów w tej chwili jako małe etykiety obok nazwy każdego sygnału.

W GTKWave

Jeśli uruchamiasz symulację lokalnie (iverilog -o sim test.v, a potem vvp sim), otwórz wynikowy plik VCD poleceniem:

gtkwave dump.vcd

GTKWave wczytuje plik, pokazuje drzewo zakresów i czeka, aż przeciągniesz sygnały do obszaru przebiegów. Kliknij prawym przyciskiem wielobitowy sygnał, żeby zmienić format wyświetlania (binarny, szesnastkowy, dziesiętny, analogowy). Pole wyszukiwania na dole pozwala przeskoczyć do konkretnych chwil albo zmian sygnałów.

Typowe wzorce

Mały pomocnik testbencha

Większość plików testbenchy zaczyna się dokładnie od tego bloku. Możesz go skrócić, łącząc wszystko w jednym bloku initial:

initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, test);

    // ... stimulus ...

    $finish;
end

Zapis warunkowy

W środowisku testowym, w którym wyjście VCD ma powstawać tylko dla nieudanych testów:

initial begin
    if (DUMP_VCD) begin
        $dumpfile("dump.vcd");
        $dumpvars(0, test);
    end
    // ... stimulus ...
end

DUMP_VCD byłby tu parameter ustawianym z linii poleceń albo definiowanym zależnie od trybu testu. Oszczędza to miejsce na dysku w zestawach testów regresyjnych.

Zapis pamięci

Pamięci (tablice rozpakowane) nie są domyślnie zapisywane przez $dumpvars, bo mogą być ogromne. Jeśli ich potrzebujesz, użyj jawnie $dumpvars(0, dut.memory) albo w niektórych symulatorach $dumpmem.

Typowe błędy

Pusty plik VCD. Brakuje $dumpfile albo $dumpvars albo symulacja wywołała $finish, zanim zmienił się jakikolwiek sygnał. Uruchom ją na co najmniej kilka jednostek czasu po konfiguracji.

Brak sygnałów na przebiegu. Przekazany zakres ich nie obejmował. $dumpvars(0, dut) zapisuje tylko to, co jest wewnątrz dut. Jeśli testbench steruje sygnałami na poziomie test, nie pojawią się one. Zawsze zapisuj od zakresu testbencha: $dumpvars(0, test).

Plik VCD jest ogromny. Długa symulacja z szybko zmieniającymi się szerokimi sygnałami daje mnóstwo linii VCD. Trzy rozwiązania: zapisuj węższy zakres, otocz nudne fragmenty przez $dumpoff/$dumpon albo przejdź na bardziej zwarty format, taki jak FST (obsługują go zarówno iverilog, jak i GTKWave przez flagi -fst).

Co dalej

Ostatni artykuł w tym rozdziale, Timescale i opóźnienia, wyjaśnia dyrektywę \timescalei to, jak#delay` przekłada się na rzeczywisty czas. Potem masz za sobą całą dokumentację od początku do końca.

Najczęściej zadawane pytania

Czym jest plik VCD w Verilogu?

VCD to skrót od Value Change Dump, czyli tekstowego formatu zapisującego każdą zmianę sygnału w trakcie symulacji. Symulator zapisuje początkową wartość każdego sygnału w chwili 0, a potem każdą zmianę razem ze znacznikiem czasu. Przeglądarki przebiegów, takie jak GTKWave, wczytują ten plik i rysują go jako graficzny wykres czasowy, który można przewijać i powiększać.

Jak wygenerować plik VCD w Verilogu?

Dodaj dwa zadania systemowe w bloku initial testbencha: $dumpfile("dump.vcd"); nadaje nazwę plikowi wyjściowemu, a $dumpvars(0, top_module); zapisuje każdy sygnał w top_module i niżej. Po zakończeniu symulacji dostaniesz plik dump.vcd, który otworzysz w dowolnej przeglądarce przebiegów.

Co oznacza $dumpvars(0, ...) w Verilogu?

$dumpvars(depth, instance) zapisuje sygnały, zaczynając od instance i schodząc rekurencyjnie na głębokość depth poziomów. $dumpvars(0, test) oznacza 'wszystkie sygnały w zakresie test i w każdym podzakresie, rekurencyjnie'. Głębokość 0 jest specjalna i oznacza brak limitu. $dumpvars(1, test) zapisałoby tylko sygnały bezpośrednio w test, bez żadnych podmodułów.

Dlaczego mój plik VCD w Verilogu jest pusty?

Trzy prawdopodobne przyczyny: w ogóle brakuje wywołania $dumpfile/$dumpvars, symulacja doszła do $finish, zanim zmienił się jakikolwiek sygnał (uruchom ją na co najmniej kilka jednostek czasu po wywołaniu zapisu), albo zakres przekazany do $dumpvars nie pasuje do faktycznej hierarchii. Minimalna działająca sekwencja to $dumpfile("dump.vcd"); $dumpvars(0, test); #10; $finish;.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ