Wykład 5: Symulacja, testy, weryfikacja formalna¶
Data: 07.11.2018
Treść
Symulatory Veriloga¶
Symulator języka Verilog to program bezpośrednio ewaluujący konstrukcje Veriloga (w przeciwieństwie do syntezy, czyli tłumaczenia na sprzęt). Można w nim używać pełnego zbioru funkcjonalności języka Verilog (nie tylko syntezowalnego podzbioru) – symulatory pozwalają na przykład wypisać coś na ekran bądź otwierać pliki na dysku. Symulatorów używa się do przetestowania poprawnego działania układu przed uruchomieniem go na sprzęcie.
Wspomnę tutaj o następujących symulatorach:
Icarus Verilog (znany również jako
iverilog
) – otwarty symulator Veriloga.Verilator – tłumaczy syntezowalny kod Veriloga na kod C++, który można wlinkować do własnego programu. Nie może być używany do uruchamiania zwykłych testów napisanych w Verilogu, za to pozwala nam używać naszego symulowanego układu z poziomu C++. Open source.
XSIM – symulator Xilinxa, wbudowany w ISE. Oprócz Veriloga wspiera VHDL i testowanie zamkniętych logic core’ów. Bardzo nie open source.
Icarus Verilog – użycie¶
a.v
:
module hello;
initial begin
$display("Hello, world!");
end
endmodule
Użycie:
# -s wybiera główny moduł.
$ iverilog a.v -s hello
$ ./a.out
Hello, world!
$
Informacja
Wygenerowany plik a.out
nie jest kodem maszynowym, tylko skryptem
napisanym w reprezentacji pośredniej Icarus Veriloga).
Testy¶
Aby symulacja miała sens, musimy napisać przypadki testowe (tzw. testbench). Przypadek testowy to moduł w (niesyntezowalnym) Verilogu, który używa danego syntezowalnego modułu, który chcemy przetestować. Testowany moduł przyjęło się nazywać DUT (Device Under Test):
module flop(
input wire D,
input wire CLK,
output reg Q
);
initial Q = 0;
always @(posedge CLK)
Q <= D;
endmodule
module testbench;
reg D = 0;
reg CLK = 0;
wire Q;
flop DUT(D, CLK, Q);
initial begin
if (Q !== 0) $display("Err 1");
D = 1;
// #<X> czeka X kroków symulacji.
#1 if (Q !== 0) $display("Err 2");
CLK = 1;
#1 if (Q !== 1) $display("Err 3");
D = 0;
CLK = 0;
#1 if (Q !== 1) $display("Err 4");
D = 0;
CLK = 1;
#1 if (Q !== 0) $display("Err 5");
$finish;
end
endmodule
Aby dostać się do wewnętrznych sygnałów testowanego modułu, można użyć składni
DUT.<nazwa_sygnału>
(narusza to enkapsulację, ale w testach można).
Warto tutaj wspomnieć o dwóch typach porównania w Verilogu: ==
(i jego
negacja !=
) oraz ===
(i negacja !==
). ==
jest syntezowalnym
porównaniem, w którym stany nieokreślone się propagują (0 == X
daje
wynik X
, X == X
daje wynik X
) – jest to porównanie, którego należy
używać zawsze w syntezowalnym kodzie. ===
natomiast jest porównaniem, które
traktuje każdą z 4 możliwych wartości bitu jako niezależną wartość (0 === X
daje wynik 0
, X === X
daje wynik 1
) – nelaży go używać w testach,
by upewnić się, że nasz układ daje odpowiednie wyniki.