Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> VHDL

Stimulusbestand gelezen in testbench met TEXTIO

Het lezen van signaalwaarden uit een bestand is een alternatieve manier om stimuli te genereren voor het apparaat dat wordt getest (DUT). De volgorde en timing van de testbank zijn hard gecodeerd in een stimulusbestand dat regel voor regel door de VHDL-testbank wordt gelezen. Hierdoor kunt u eenvoudig het patroon van de golfvorm die u aan het testobject wilt toevoegen, wijzigen.

Soms heb je een heel specifiek testpatroon of opeenvolging van gebeurtenissen waar je je DUT doorheen wilt laten gaan. U kunt dit bereiken door in een ASCII-bestand de signaalwaarden op te geven die elk signaal moet hebben, evenals de relatieve simulatietijd waarop ze moeten veranderen. De rol van de VHDL-testbank in een dergelijke strategie is om de gegevens uit het stimulusbestand te lezen en de waarden op het juiste moment toe te passen op de DUT-ingangen.

Dit artikel is het tweede in een serie over bestandstoegang in VHDL. We hebben in de vorige blogpost gekeken hoe je hexadecimale, octale en binaire waarden uit een bestand kunt lezen, ga terug en lees het als je meer wilt weten over het lezen uit een bestand met behulp van de TEXTIO bibliotheek in VHDL.

Deze blogpost maakt deel uit van een serie over het gebruik van de TEXTIO-bibliotheek in VHDL. Lees hier de andere artikelen:

Hoe RAM vanuit een bestand te initialiseren met TEXTIO

BMP-bestand bitmapafbeelding gelezen met TEXTIO

De testcase

Het voorbeeld DUT is een multiplexer met 4 ingangen (MUX) uit een van mijn eerdere blogposts. Het is een standaard, asynchrone 4-naar-1 MUX met een databreedte van één byte. Hoe het werkt, is niet belangrijk voor dit artikel, omdat we de uitvoer niet gaan controleren, het is alleen voor demonstratiedoeleinden.

De entiteit van de MUX wordt hieronder getoond.

entity mux_4 is
  port(
    -- Data in
    din_0 : in unsigned(7 downto 0);
    din_1 : in unsigned(7 downto 0);
    din_2 : in unsigned(7 downto 0);
    din_3 : in unsigned(7 downto 0);

    -- Selector
    sel  : in unsigned(1 downto 0);

    -- Data out
    dout : out unsigned(7 downto 0));
end entity;

Na het importeren van de benodigde pakketten bovenaan het VHDL-bestand, gaan we verder met het declareren van de ingangssignalen die we gaan verbinden met de DUT. Zoals je kunt zien in de onderstaande lijst, zijn het blauwdrukken van de MUX-entiteitsverklaring.

signal din_0 : unsigned(7 downto 0);
signal din_1 : unsigned(7 downto 0);
signal din_2 : unsigned(7 downto 0);
signal din_3 : unsigned(7 downto 0);
signal sel  : unsigned(1 downto 0);
signal dout : unsigned(7 downto 0);

We gebruiken de entiteitsinstantiatiemethode om een ​​instantie van de MUX te maken met het label "DUT" bovenaan de architectuurregio van onze testbench. De entiteitsignalen zijn verbonden met de lokale testbanksignalen met dezelfde namen, zoals weergegeven in de onderstaande code.

DUT: entity work.mux_4(rtl)
port map (
    din_0 => din_0,
    din_1 => din_1,
    din_2 => din_2,
    din_3 => din_3,
    sel  => sel,
    dout => dout
);

Het stimulusbestand

Een stimulusbestand kan veel verschillende formaten hebben, de hier gepresenteerde is slechts een voorbeeld dat ik uit mijn hoofd bedacht tijdens het schrijven van dit artikel. Desalniettemin, als je begrijpt hoe ik het heb gemaakt, zou je het moeten kunnen aanpassen aan je behoeften.

De onderstaande lijst toont het volledige stimulusbestand dat in dit voorbeeld wordt gebruikt.

# Column description:
# wait_time | sel | din_0 | din_1 | din_2 | din3 # Optional console printout

0 ns 0 AA BB CC DD # Setting initial values
10 ns 1 AA BB CC DD # Testing by changing the selector signal
10 ns 2 AA BB CC DD
10 ns 3 AA BB CC DD
10 ns 3 A1 B1 C1 D1 # Testing by changing all data inputs
10 ns 3 A2 B2 C2 D2
10 ns 3 A3 B3 C3 D3
10 ns 3 00 00 00 D2 # Changing all unselected inputs
10 ns 3 01 02 03 D2
10 ns 3 11 22 33 D2
1 ns 0 CC DD EE FF # Changing all inputs fast
1 ns 1 DD EE FF CC
1 ns 2 EE FF CC DD
1 ns 3 FF CC DD EE
10 ns 0 00 00 00 00 # Simulation stop

Laten we de opmerkingen voorlopig negeren, dat zijn degenen die in het groen zijn gemarkeerd, altijd beginnend met een '#'-teken. Elke lijn vertegenwoordigt één tijdstap in de simulatie. Er zijn zes kolommen met opdrachten op elke regel, eigenlijk zeven kolommen tekst, maar de eerste twee kolommen behoren tot hetzelfde gegevensitem.

Tekstkolommen één en twee beschrijven een tijdswaarde, hoe lang de simulator op die regel moet pauzeren voordat de waarden worden toegepast die in de andere kolommen worden vermeld. De absolute simulatietijd wanneer de opdracht wordt uitgevoerd, is dus relatief aan de gebeurtenis beschreven door de vorige regel. We gebruiken slechts 0, 1 of 10 nanoseconden, maar het kan van alles zijn, 1000 nanoseconden of 1000 uur (1000 hr ) trouwens.

De overige vijf tekstkolommen beschrijven de signaalwaarden die van toepassing zijn op de DUT-ingangen. Ze worden gegeven als hexadecimale letterlijke waarden en de volgorde van het signaal is sel , din_0 , din_1 , din_2 , en tot slot din_3 .

Nu, over naar de opmerkingen. Er zijn twee soorten opmerkingen; opmerkingen met één regel en opmerkingen met naloop. Ze zullen door onze testbench anders worden behandeld. Opmerkingen van één regel, zoals die bovenaan het bestand, worden genegeerd. Aan de andere kant zullen lopende opmerkingen naar de simulatorconsole worden afgedrukt. We kunnen ze gebruiken om ons aanwijzingen te geven over wat er gebeurt terwijl de simulatie draait.

Het stimulusbestand lezen in VHDL

VHDL is niet de beste taal voor tekstverwerking, maar het doet zijn werk. De ondersteuning voor dynamische strings is beperkt en het ontbreekt aan gemaksroutines voor bijvoorbeeld het strippen of overslaan van witruimte. Om het onszelf gemakkelijker te maken, gaan we ervan uit dat het stimulusbestand mooi is geschreven. Laten we er goed op letten dat er altijd één spatie is tussen tekstelementen en één spatie tussen het '#'-teken en de commentaartekst. Ook geen extra voorloop- of volgspaties ergens in het stimulusbestand.

PROC_SEQUENCER : process
  file text_file : text open read_mode is "stimulus.txt";
  variable text_line : line;
  variable ok : boolean;
  variable char : character;
  variable wait_time : time;
  variable selector : sel'subtype;
  variable data : dout'subtype;
begin

Het declaratieve gebied van de PROC_SEQUENCER procedure staat hierboven. Eerst verklaren we de speciale file object, een VHDL-bestandshandlertype. Vervolgens declareren we een variabele van het type line . Dit is gewoon een toegangstype tot een string, een pointer naar een dynamisch toegewezen stringobject. De ok variabele van het Booleaanse type is om te controleren of de leesbewerkingen succesvol zijn. Ten slotte declareren we de vier variabelen char , wait_time , selector , en data . Deze variabelen zijn voor het extraheren van de gegevens uit elke kolom uit elke regel tekst.

  while not endfile(text_file) loop

    readline(text_file, text_line);

    -- Skip empty lines and single-line comments
    if text_line.all'length = 0 or text_line.all(1) = '#' then
      next;
    end if;

In de procestekst gaan we rechtstreeks naar een while-lus die elke regel tekst in het stimulusbestand herhaalt. De readline procedure wijst een nieuwe regel tekst toe aan de text_line variabele bij elke iteratie van deze lus. Na het lezen van de regel controleren we of de regel leeg is of dat het eerste teken '#' is, in dat geval gaan we direct naar de volgende regel met behulp van de next sleutelwoord om een ​​iteratie van de lus over te slaan. Let op:we gebruiken text_line.all om toegang te krijgen tot de string in de line voorwerp.

    read(text_line, wait_time, ok);
    assert ok
      report "Read 'wait_time' failed for line: " & text_line.all
      severity failure;

    hread(text_line, selector, ok);
    assert ok
      report "Read 'sel' failed for line: " & text_line.all
      severity failure;
    sel <= selector;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_0' failed for line: " & text_line.all
      severity failure;
    din_0 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_1' failed for line: " & text_line.all
      severity failure;
    din_1 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_2' failed for line: " & text_line.all
      severity failure;
    din_2 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_3' failed for line: " & text_line.all
      severity failure;
    din_3 <= data;

Hierna volgen een aantal reads van de text_line object. De read en hread procedure-aanroepen slaan voorloopspaties over zodat we geen dummy-lezingen hoeven te doen om de interne leesstartpositie binnen de text_line te verplaatsen object. We hadden de assert-statements kunnen weglaten, maar ik wil dat de simulatie stopt als lezen mislukt. In ModelSim stopt de simulatie in ieder geval niet automatisch wanneer dit gebeurt. We wijzen elke succesvol gelezen variabele toe aan het relevante DUT-signaal, behalve de wait_time variabele die geen corresponderende DUT-invoer heeft.

    wait for wait_time;

Na het toewijzen van de signaalwaarden wachten we op de opgegeven tijd. Als u op de wait-instructie drukt, worden de geplande signaalwaarden effectief met dezelfde deltacyclus.

    -- Print trailing comment to console, if any
    read(text_line, char, ok); -- Skip expected newline
    read(text_line, char, ok);
    if char = '#' then
      read(text_line, char, ok); -- Skip expected newline
      report text_line.all;
    end if;

  end loop;

  finish;

end process;

Ten slotte, wanneer het programma ontwaakt uit de wait-statement, zoeken we naar een extra commentaar op de text_line object. Elke opmerking wordt naar de console afgedrukt met behulp van de rapportverklaring nadat we het '#'-teken en de volgende witruimte hebben verwijderd met behulp van dummy-lezingen.

Nadat de laatste regel tekst uit het stimulusbestand is verwerkt, wordt de while-lus beëindigd. Er is een VHDL-2008 finish trefwoord aan het einde van het proces dat verantwoordelijk is voor het stoppen van de testbench.

De uitvoer

De voorbeeldtestbench drukt de onderstaande tekst af naar de simulatorconsole wanneer deze wordt uitgevoerd in ModelSim. We kunnen zien dat de opmerkingen afkomstig zijn uit het stimulusbestand. De afgedrukte tijdwaarden zijn de geaccumuleerde simulatietijden op basis van de vertragingen van nanoseconden die zijn opgegeven in het stimulusbestand.


# ** Note: Setting initial values
#    Time: 0 ns  Iteration: 1  Instance: /file_stim_tb
# ** Note: Testing by changing the selector signal
#    Time: 10 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Testing by changing all data inputs
#    Time: 40 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Changing all unselected inputs
#    Time: 70 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Changing all inputs fast
#    Time: 91 ns  Iteration: 0  Instance: /file_stim_tbf
# ** Note: Simulation stop
#    Time: 104 ns  Iteration: 0  Instance: /file_stim_tb
# Break in Process PROC_SEQUENCER at file_stim_tb.vhd line 98

De golfvorm voor de simulatie wordt hieronder weergegeven. Het toont een visuele weergave van hoe de waarden uit ons stimulusbestand worden toegepast op de signalen op de gespecificeerde simulatietijden.

Laatste gedachten

Het lezen van testbankprikkels uit bestand kan voordelig zijn als je een heel specifiek testpatroon hebt dat je moet toepassen. De hele testbench hoeft niet door het tekstbestand te worden aangestuurd, dit voorbeeld is alleen bedoeld om de mogelijkheden van bestandstoegang in VHDL te laten zien.

Een ding dat we echter niet hebben besproken, is het controleren van de DUT-uitgangen. Onze voorbeeldtestbench controleert de outputs helemaal niet. Je zou het DUT-gedrag kunnen verifiëren zoals je zou doen in een volledige VHDL-testbench, bijvoorbeeld door een gedragsmodel te gebruiken om mee te vergelijken. Of u kunt de code en het stimulusbestand wijzigen om de verwachte uitvoerwaarden op te nemen. Welke strategie u ook kiest, zorg ervoor dat u een zelfcontrolerende testbank maakt en vertrouw niet op het handmatig controleren van de golfvorm.


VHDL

  1. C# met behulp van
  2. C Bestandsverwerking
  3. Java-bestandsklasse
  4. Digitale handtekeningen gebruiken voor gegevensintegriteitscontrole in Linux
  5. Hoe RAM vanuit een bestand te initialiseren met TEXTIO
  6. Hoe maak je een zelfcontrolerende testbank aan
  7. Java BufferedReader:hoe een bestand in Java te lezen met voorbeeld
  8. Python JSON:coderen (dumps), decoderen (laden) &JSON-bestand lezen
  9. Verilog File IO-bewerkingen
  10. C - Koptekstbestanden
  11. Wat is een driehoekig bestand?