www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Probleme mit undefinierten Bits in STD_LOGIC Vektoren


Autor: Klaus Kanone (yildi)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Ich habe ein großes Problem, das mich schon seit Tagen an den Rande der 
Verzweiflung bringt. Es geht um ein Spiel, welches in VHDL umgesetzt 
werden sollte und so funktionieren soll:

- Über 4 Schalter (ZIEL) ist vor Spielbeginn ein Testmuster einzustellen
- Nach Betätigung der RESET-taste beginnt das Spiel, d.h. mittels 
Pseudozufallsgenerator werden an 4 Leuchtdioden (MUSTERLED) verschiedene 
Muster ausgegeben.
- Beim visuellen Erkennen des Testmusters (ZIEL) müssen die beiden 
Spieler ihren prellfreien Taster betätigen (BUTTON_1 und BUTTON_2)
- Drückt man zu früh wird ein Fehlersignal ausgegebe und das Spiel 
unterbrochen. ANdernfalls wird ein Timer gestartet, um die verstrichende 
Zeit zwischen der Darstellung des Testmusters und der Betätigung des 
Tasters in Balkenform (ZEITBALKENLED) anzuzeigen.

Soweit die Aufgabenstellung (erstmal mit 4 Bit Mustern). Daraus habe ich 
dann einen Autoamtengraphen entwickelt (im Anhang zu sehen). Danach 
haben wir dann das VHDL Programm geschrieben. Eigentlich funktioniert es 
auch schon, bzw. hat es teilweise mal kurz. Nur eben sehr 
unzuverlässig.. es macht was es will.. ganz unbeschreiblich und 
unberechenbar. Also auf dem richtigen Weg scheinen wir zu sein. Probleme 
treten seltsamerweise immer auf, wenn wir zum Beispiel die 
ZEITBALKENLEDs anmachen, die zur Zeit im Quelltext auskommentiert sind. 
So wie das Programm nun aussieht, läuft es auch, nur müssen, um zum 
Beispiel einen Fehler erkennen zu lassen noch mehr LEDs angemacht 
werden. Nur wenn wir das machen funktioniert kaum noch was. So. Also 
habe ich den Quelltext mal in ModelSim simuliert, jedenfalls die 
allerersten Takte des Spiels. Und schon da ist zu erkennen, dass in der 
wave Ansicht (angehängter Screenshot) Vektoren teilweise rot 
gekennzeichnet werden. Setzen wir Status zum Beispiel: STATUS <= "0110"; 
ist in der Simulation STATUS = 0XX0, wobei X ja ein undefinierter 
Zustand ist. Das gleiche Problem ist auch Beim Vetor ZAEHLER zu sehen. 
AUch wenn ausgerechnet diese beiden Vektoren uns keine merkbaren 
Probleme gemacht haben, denke ich, dass die Ursache unserer Probleme an 
ähnlicher Problematik liegt. Ich hatte testweise die typen der Vektoren 
von STD_LOGIC_VECTOR mal auf BIT_VECTOR geändert. In dem Fall zeigt die 
Simulation dann gar keine Veränderung der Bits an.. sie bleiben alle 
immer auf 0.

Es gilt also herauszufinden, wieso die Bits, die wir eigentlich auf 1 
gesetzt haben undefiniert X sind. Ich habe am Anfang des Programms schon 
sehr viel rumprobiert, aber nichts verändern können. Deshalb frage ich 
nun hier, ob vielleicht einer auf den ersten Blick schon ein 
grundlegenden Denkfehler oder was auch immer entdeckt. Über jede 
erdenkliche Hilfe wäre ich sehr sehr dankbar !! :)

Hier der VHDL-Code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity SPIEL is
    port ( TAKT : in STD_LOGIC;
           RESET : in STD_LOGIC;
        BUTTON_1 : in STD_LOGIC;
        BUTTON_2 : in STD_LOGIC;
        ZIEL : in STD_LOGIC_VECTOR(4 downto 1);
        SIEGERLED : out bit_vector(8 downto 1);
        MUSTERLED : out STD_LOGIC_VECTOR(4 downto 1);
        ZEITBALKENLED : out STD_LOGIC_VECTOR(16 downto 1);
        STATUS : out STD_LOGIC_VECTOR(4 downto 1)
          );
end SPIEL;

architecture ASPIEL of SPIEL is
  type STATE_TYPE is (VORBEREITUNG, SPIEL, ZAEHLEN, FEHLER, AUSWERTUNG_1, AUSWERTUNG_2, P1, P2, P3);
  signal STATE, NEXT_STATE : STATE_TYPE;

  signal EINGANG : STD_LOGIC;
  signal AUSGANG : STD_LOGIC;
  signal ZUFALL : STD_LOGIC_VECTOR(4 downto 1) := "0000";
  signal ZAEHLER :  STD_LOGIC_VECTOR(10 downto 1) := "0000000000";
  signal TIMER : STD_LOGIC_VECTOR(10 downto 1) := "0000000000";

begin

  process(TAKT)
    begin
      if TAKT'event and TAKT='1' then
        STATE <= NEXT_STATE;

       ZAEHLER <= ZAEHLER + 1;
       if (ZAEHLER = "1111101000" and STATE = SPIEL) then
         ZAEHLER <= "0000000000";
         ZUFALL(4) <= ZUFALL(3);
         ZUFALL(3) <= ZUFALL(2);
         ZUFALL(2) <= ZUFALL(1) xor AUSGANG;
         ZUFALL(1) <= EINGANG xor AUSGANG;
         AUSGANG <= ZUFALL(4);
       end if;

       if (STATE = VORBEREITUNG) then
         ZUFALL <= "0000";
        ZAEHLER <= "0000000000";
        EINGANG <= '1';
        AUSGANG <= '0';
        TIMER <= "0000000000";
       end if;

       if (STATE = ZAEHLEN) then
         TIMER <= TIMER + 1;
       end if;

      end if;
  end process;

  process(STATE, RESET, BUTTON_1, BUTTON_2, ZUFALL, ZIEL, TIMER)
    begin

    case STATE is

    ------------------------------------------------------------------

      when VORBEREITUNG   =>  STATUS <= "1000";

        SIEGERLED <= "00000000";
        MUSTERLED <= "0000";
        ZEITBALKENLED <= "0000000000000000";

        if (RESET = '0') then NEXT_STATE <= P1; end if;
        if (RESET = '1') then NEXT_STATE <= VORBEREITUNG; end if;

    ------------------------------------------------------------------

      when P1          =>  STATUS <= "1111";

        if (RESET = '0') then NEXT_STATE <= P1; end if;
        if (RESET = '1') then NEXT_STATE <= SPIEL; end if;

    ------------------------------------------------------------------

      when SPIEL        =>  STATUS <= "0100";

        if (RESET = '0') then NEXT_STATE <= P2; end if;
        if (RESET = '1') then NEXT_STATE <= SPIEL; end if;

        MUSTERLED <= ZUFALL;

        if (ZUFALL = ZIEL) then
          NEXT_STATE <= ZAEHLEN;
        end if;

        if (BUTTON_1 = '0') then NEXT_STATE <= AUSWERTUNG_1; end if;
        if (BUTTON_2 = '0') then NEXT_STATE <= AUSWERTUNG_2; end if;

    ------------------------------------------------------------------

      when ZAEHLEN      =>  STATUS <= "0010";

        if (TIMER = "1111101000") then
          NEXT_STATE <= FEHLER;
        end if;

        if (BUTTON_1 = '0') then NEXT_STATE <= AUSWERTUNG_1; end if;
        if (BUTTON_2 = '0') then NEXT_STATE <= AUSWERTUNG_2; end if;

    ------------------------------------------------------------------

      when P2          =>  STATUS <= "1111";

        if (RESET = '0') then  NEXT_STATE <= P2; end if;
        if (RESET = '1') then  NEXT_STATE <= VORBEREITUNG; end if;

    ------------------------------------------------------------------

      when FEHLER        =>  STATUS <= "0001";

--          SIEGERLED <= "11111111";
--          ZEITBALKENLED <= "1111111111111111";

        if (RESET = '0') then NEXT_STATE <= P3; end if;
        if (RESET = '1') then NEXT_STATE <= FEHLER; end if;

    ------------------------------------------------------------------

      when AUSWERTUNG_1    =>  STATUS <= "0001";

--        if TIMER > 31 then
--          ZEITBALKENLED(1) <= '1';
--        end if;
--        if TIMER > 31+63 then
--          ZEITBALKENLED(2) <= '1';
--        end if;
--        if TIMER > 31+63*2 then
--          ZEITBALKENLED(3) <= '1';
--        end if;
--        if TIMER > 31+63*3 then
--          ZEITBALKENLED(4) <= '1';
--        end if;
--        if TIMER > 31+63*4 then
--          ZEITBALKENLED(5) <= '1';
--        end if;
--        if TIMER > 31+63*5 then
--          ZEITBALKENLED(6) <= '1';
--        end if;
--        if TIMER > 31+63*6 then
--          ZEITBALKENLED(7) <= '1';
--        end if;
--        if TIMER > 31+63*7 then
--          ZEITBALKENLED(8) <= '1';
--        end if;
--        if TIMER > 31+63*8 then
--          ZEITBALKENLED(9) <= '1';
--        end if;
--        if TIMER > 31+63*9 then
--          ZEITBALKENLED(10) <= '1';
--        end if;
--        if TIMER > 31+63*10 then
--          ZEITBALKENLED(11) <= '1';
--        end if;
--        if TIMER > 31+63*11 then
--          ZEITBALKENLED(12) <= '1';
--        end if;
--        if TIMER > 31+63*12 then
--          ZEITBALKENLED(13) <= '1';
--        end if;
--        if TIMER > 31+63*13 then
--          ZEITBALKENLED(14) <= '1';
--        end if;
--        if TIMER > 31+63*14 then
--          ZEITBALKENLED(15) <= '1';
--        end if;
--        if TIMER > 31+63*15 then
--          ZEITBALKENLED(16) <= '1';
--        end if;

        if (TIMER = "0000000000") then
          SIEGERLED <= "00001111";
        else
          SIEGERLED <= "11110000";
        end if;

        if (RESET = '0') then NEXT_STATE <= P3; end if;
        if (RESET = '1') then NEXT_STATE <= AUSWERTUNG_1; end if;

    ------------------------------------------------------------------

      when AUSWERTUNG_2    =>  STATUS <= "0001";

--        if TIMER > 31 then
--          ZEITBALKENLED(1) <= '1';
--        end if;
--        if TIMER > 31+63 then
--          ZEITBALKENLED(2) <= '1';
--        end if;
--        if TIMER > 31+63*2 then
--          ZEITBALKENLED(3) <= '1';
--        end if;
--        if TIMER > 31+63*3 then
--          ZEITBALKENLED(4) <= '1';
--        end if;
--        if TIMER > 31+63*4 then
--          ZEITBALKENLED(5) <= '1';
--        end if;
--        if TIMER > 31+63*5 then
--          ZEITBALKENLED(6) <= '1';
--        end if;
--        if TIMER > 31+63*6 then
--          ZEITBALKENLED(7) <= '1';
--        end if;
--        if TIMER > 31+63*7 then
--          ZEITBALKENLED(8) <= '1';
--        end if;
--        if TIMER > 31+63*8 then
--          ZEITBALKENLED(9) <= '1';
--        end if;
--        if TIMER > 31+63*9 then
--          ZEITBALKENLED(10) <= '1';
--        end if;
--        if TIMER > 31+63*10 then
--          ZEITBALKENLED(11) <= '1';
--        end if;
--        if TIMER > 31+63*11 then
--          ZEITBALKENLED(12) <= '1';
--        end if;
--        if TIMER > 31+63*12 then
--          ZEITBALKENLED(13) <= '1';
--        end if;
--        if TIMER > 31+63*13 then
--          ZEITBALKENLED(14) <= '1';
--        end if;
--        if TIMER > 31+63*14 then
--          ZEITBALKENLED(15) <= '1';
--        end if;
--        if TIMER > 31+63*15 then
--          ZEITBALKENLED(16) <= '1';
--        end if;

        if (TIMER = "0000000000") then
          SIEGERLED <= "11110000";
        else
          SIEGERLED <= "00001111";
        end if;

        if (RESET = '0') then NEXT_STATE <= P3; end if;
        if (RESET = '1') then NEXT_STATE <= AUSWERTUNG_2; end if;

    ------------------------------------------------------------------

      when P3          =>  STATUS <= "1111";
        if (RESET = '0') then NEXT_STATE <= P3; end if;
        if (RESET = '1') then NEXT_STATE <= VORBEREITUNG; end if;

    ------------------------------------------------------------------

    end case;

  end process;

end ASPIEL;


Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Es gilt also herauszufinden, wieso die Bits, die wir eigentlich auf 1
> gesetzt haben undefiniert X sind.
Setzt du STATUS und ZAEHLER in der TB auf '0'?
Das darfst du nicht, weil es ja Ausgäng deines Moduls sind...

Autor: Klaus Kanone (yildi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist denn TB ?
STATUS setze ich erst in den Zuständen auf einen Wert. Und ZAEHLER ist 
doch aber gar kein Ausgang

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Phillip D. schrieb:
> Was ist denn TB ?
Eine TB = Testbench ist ein VHDL-Modell, das dein Spiel ansteuert.
Wie erzeugst du deine Stimulidaten (TAKT, BUTTON...)?

> STATUS setze ich erst in den Zuständen auf einen Wert. Und ZAEHLER ist
> doch aber gar kein Ausgang
Ich habe das mal mit einer simplen Testbench ausprobiert, das scheint 
besser zu gehen (sieh Anhang).


BTW: Nimm den bit_vector wieder aus dem Port raus...

Autor: Klaus Kanone (yildi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah okay, das scheint bei Ihnen ja zu funktionieren. Ich hatte bislang 
eine *.do Datei die ich dann ausführen konnte. Sie hatte den folgenden 
Inhalt.

vsim work.SPIEL
restart
view wave
radix bin

force takt 0 0, 1 500us -r 1000us
force reset 1
force button_1 1
force button_2 1
force ziel "0110"
force siegerled "00000000"
force musterled "0000"
force zeitbalkenled "0000000000000000"
force status "0000"
force eingang 1
force ausgang 0
force zufall "0000"
force zaehler "0000000000"
force timer "000000000000000"

run 5ms

force reset 0
run 5ms
force reset 1
run 5ms
force zaehler "1111101000"
run 20ms

Ich werde es nun aber mal auf die Art versuchen, wie Sie es gemacht 
haben.. Ich meld mich dann wieder ;-)

Autor: Klaus Kanone (yildi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So nun bekomme ich in meiner Simulation auch eine einwandfreie wave 
Grafik. Alles funktioniert so wie es soll :) Allerdings habe ich im 
eigentlichen Quelltext ja nichts geändert, sondern nur die Simulation 
angepasst. Ich denke nicht, dass es nun in der Realität funktionieren 
wird, das kann ich aber allerdings erst Montag wieder im Labor 
austesten. Sowiet schonmal vielen Dank! Falls doch noch jemand eine Idee 
hat, was falsch sein könnte... das wäre super :)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.