Een self-checking testbench in VHDL bouwen – Een praktische gids
Een self-checking testbench is een VHDL-programma dat de correctheid van een device under test (DUT) verifieert zonder handmatige inspectie. Eenmaal uitgevoerd, rapporteert het automatisch een OK of Failed-status, wat het een essentieel hulpmiddel maakt voor betrouwbare VHDL-ontwikkeling.
Elke VHDL-module zou een bijbehorende self-checking testbench moeten hebben. Dit zorgt ervoor dat elke wijziging – of het nu de DUT zelf is, een submodule of een interface – niet onopgemerkt regressies introduceert. Een goed geteste testbench is de eerste verdedigingslinie tegen subtiele bugs.
Het Device Under Test
We gebruiken een eenvoudige maar illustratieve DUT: een binaire-naar-Gray-code converter. Hieronder staat de volledige RTL-implementatie.
library ieee; use ieee.std_logic_1164.all; entity gray_converter is port ( bin : in std_logic_vector; gray : out std_logic_vector ); end gray_converter; architecture rtl of gray_converter is begin process(bin) is begin gray(gray'high) <= bin(bin'high); for i in bin'high - 1 downto bin'low loop gray(i) <= bin(i + 1) xor bin(i); end loop; end process; end architecture;
Gray-code is een binaire codering waarbij tussen opeenvolgende waarden slechts één bit verandert, wat de foutkans in seriële communicatie en digitale tellers minimaliseert. De onderstaande tabel toont de mapping voor 4-bits waarden.
| Decimaal | Binair | Gray |
|---|---|---|
| 0 | 0000 | 0000 |
| 1 | 0001 | 0001 |
| 2 | 0010 | 0011 |
| 3 | 0011 | 0010 |
| 4 | 0100 | 0110 |
| 5 | 0101 | 0111 |
| 6 | 0110 | 0101 |
| 7 | 0111 | 0100 |
| 8 | 1000 | 1100 |
| 9 | 1001 | 1101 |
| 10 | 1010 | 1111 |
| 11 | 1011 | 1110 |
| 12 | 1100 | 1010 |
| 13 | 1101 | 1011 |
| 14 | 1110 | 1001 |
| 15 | 1111 | 1000 |
Het testbench-skelet
Hieronder staat een minimale testbench die de DUT instantieert en de benodigde signalen declareert. Let op de opname van std.env.finish, een VHDL-2008-functie die de simulatie netjes beëindigt.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use std.env.finish; entity gray_converter_tb is end gray_converter_tb; architecture sim of gray_converter_tb is signal bin : std_logic_vector(3 downto 0) := (others => '0'); signal gray : std_logic_vector(3 downto 0); DUT : entity work.gray_converter(rtl) port map ( bin => bin, gray => gray ); end architecture;
Als je dit bestand compileert in een VHDL-2008-compatibele simulator zoals ModelSim, moet je wellicht de taalversie van het bestand op 2008 zetten. In ModelSim: rechtermuisklik op het bestand, kies Properties → VHDL → Use 1076-2008.
Uitputtende invoer genereren
De volgende stap is het produceren van een complete sweep van alle mogelijke 4-bits waarden. Een uitputtende test is te verkiezen omdat het garandeert dat elk hoekgeval getest wordt.
PROC_SEQUENCE : process begin -- Itereer over elke 4-bits waarde for i in 0 to 2**bin'length - 1 loop bin <= std_logic_vector(to_unsigned(i, bin'length)); wait for 10 ns; end loop; -- Terug naar beginstoestand bin <= (others => '0'); wait for 10 ns; report "Test: OK"; finish; end process;
De 10-ns vertraging is willekeurig; elke positieve waarde volstaat omdat de DUT puur combinationeel is. De laatste finish-instructie beëindigt de simulatie netjes.
De DUT-output verifiëren
Alleen "Test: OK" printen zou zinloos zijn als de output foutief is. Om correctheid af te dwingen, vergelijken we de Gray-output van de DUT met de fundamentele Gray-code-eigenschap: opeenvolgende outputs mogen precies één bit verschillen.
PROC_CHECKER : process variable prev : std_logic_vector(gray'range); variable count : integer; begin wait on bin; prev := gray; -- Laat combinationele logica oplossen wait for 1 ns; count := 0; for i in gray'range loop if gray(i) /= prev(i) then count := count + 1; end if; end loop; assert count = 1 report integer'image(count) & " bits changed, should have been 1" severity failure; end process;
Dit proces monitor veranderingen op bin, vangt de vorige Gray-output, wacht op propagatie, telt verschillende bits en assert dat de telling precies één is. Als de assertie faalt, stopt de simulator onmiddellijk, waardoor het "Test: OK"-bericht niet verschijnt.
De testbench draaien
In ModelSim start je de simulatie en voert run -all uit. Een succesvolle run eindigt met:
VSIM 1> run -all # ** Note: Test: OK # Time: 170 ns Iteration: 0 Instance: /gray_converter_tb
De robuustheid van de testbench testen
Om te bevestigen dat de checker fouten detecteert, introduceer tijdelijk een fout in de DUT – bijvoorbeeld forceer gray(3) naar nul.
process(bin) is begin gray(gray'high) <= bin(bin'high); for i in bin'high - 1 downto bin'low loop gray(i) <= bin(i + 1) xor bin(i); end loop; -- Emuleer een stuck-at-zero fault gray(3) <= '0'; end process;
De testbench draait nu en activeert de assertiefout, met het exacte aantal bits dat veranderde:
VSIM 2> run -all # ** Failure: 0 bits changed, should have been 1 # Time: 81 ns Iteration: 0 Process: /gray_converter_tb/PROC_CHECKER File: gray_converter_tb.vhd # Break in Process PROC_CHECKER at ray_converter_tb.vhd line 61
Aan de slag met self-checking testbenches
Maak het een gewoonte om voor elke VHDL-module een self-checking testbench te schrijven. Ze besparen tijd door regressies vroegtijdig op te sporen en bieden een duidelijk ontwerpintent. Hoewel testbenches niet synthetiseerbaar hoeven te zijn, moeten ze duidelijk, onderhoudbaar zijn en de nieuwste VHDL-constructen gebruiken voor leesbaarheid en efficiëntie.
Voor dieper leren, overweeg geavanceerde cursussen die de volledige ontwerpflow dekken – van specificatie tot FPGA-prototype – met nadruk op rigoureuze verificatiepraktijken.
Bijgewerkt 12 oktober 2020: Ik heb de VHDL- en FPGA-cursus voltooid. Klik op de afbeelding hieronder voor meer informatie.
Lees meer over de Dot Matrix VHDL- en FPGA-cursus hier!
Opent:
Nog te bepalen.
VHDL
- Frictieloze gebruikerservaringen creëren: Een UX-design blauwdruk
- Bouw Uw Eerste AWS CloudFormation Template – Een Praktische Gids
- Een Cloud Center of Excellence Bouwen: Strategieën Voor Succesvolle Migratie En Klantsucces
- Een Strategisch Cloud-adoptieplan Bouwen
- Mens-Centrische Slimme Steden Bouwen: Een Strategisch Blauwdruk
- Dynamische string-lijsten in VHDL: Best Practices & Voorbeeld
- Een Tcl-gedreven testbench maken voor een VHDL code-lock module
- Een VHDL-testbench netjes beëindigen: methoden en best practices
- Een PWM-controller implementeren in VHDL: Ontwerp, Simulatie en FPGA-demo
- Een dynamische gelinkte lijst in VHDL implementeren met protected types en access pointers
- Een Array van Objecten in Java aanmaken: Stap-voor-stap gids