Hallo zusammen,
folgendes Problem bei dem ich über jede Hilfe dankbar bin:
Für ein Hochschulprojekt soll eine Stoppuhr auf einem Xilinx Artix-7
(Board: Digilent Nexys 4 DDR) realisiert werden. Die Uhr soll 3 Modi
haben: Normal (Nach Stopp neustarten), Addition (Nach Stopp bei
Zwischenstand weiterlaufen) und Split (Bei Stopp läuft die Uhr im
Hintergrund weiter).
Der Systemtakt liegt bei 100MHz und wird durch zählen bis 1'000'000 auf
eine Hundertstel Sekunde heruntergebrochen.
Mein Problem: Wenn ich den Frequenzteiler bis 10'000'000 zählen lasse
(kleinste Einheit Zehntel-Sekunde) funktionieren alle Modi wie sie
sollen. Lasse ich den Frequenzteiler korrekterweise bis 1'000'000 zählen
(kleinste Einheit Hundertstel-Sekunde) startet die Uhr auch im
Additions- oder Split-Modus nach einem Stopp wieder von Null.
Habe bisher hauptsächlich in C++ programmiert und noch relativ wenig
Erfahrung mit parallelen Abläufen. Vielleicht liegt der Fehler hier!?
Die meines Erachtens relevanten Code-Schnipsel poste ich direkt hier,
der vollständige Code hängt an.
Vielen Dank für eure Hilfe!!
Modi durchschalten
Hab jetzt den Code noch nicht angeschaut.
Aber siehst du das Verhalten in der Simulation oder nur nach der
Synthese im FPGA.
Ich frage deshalb um zu klären, ob der Code auf logische Fehler oder
ungünstige Konstrukte untersucht werden muss, die bei der Synthese Ärger
machen können.
Der HundertstelTakt ist doch eigentlich ein Enable-"Tick". Bist sicher,
dass diese drei Bedingungen zeitlich immer so zusammenfallen, wie
vorgesehen? (Der Tick dauert nur einen Takt).
Im Code sehe ich nicht, wo der UhrUeberlauf gesetzt wird (ausser als
Initialisierung) - warum also überhaupt abfragen?
Und dann noch in Zustand E:
1
UhrStart<='1';
2
UhrStopp<='1';
Ist das so gewollt?
Für die Simulation wäre es wohl einfacher, die Überlaufbedingung der
Hundertsteltakt-Generierung per GENERIC einstellbar zu machen. Die
Simulation kann dann z.B. einen Faktor 1000 schneller laufen als auf dem
FPGA.
Stefan H. schrieb:> Vielleicht liegt der Fehler hier!?
Wenn ich diese Abhängigkeit von der Taktfrequenz höre und sowas sehe,
dann weiß ich, was zu ändern ist:
1
ifreset='0'orUhrZuruecksetzen='1'then
2
ZaehlerSekundenHundertstel<=0;
3
ZaehlerSekundenHundertstelUeberlauf<='0';
4
elsifrising_edge(takt)then
Das ist ein asynchroner kombinatorischer Reset. Der funktioniert in
Gedanken und in der Simulation tadellos. Aber in der Realität hast du da
beliebige Probleme mit irgendwelchen Spikes und Glitches, die jedesmal
entstehen, wenn irgendwas im Prozess FOLGEZUSTANDSBERECHNUNG_UHR
passiert. Sowas läuft in der Realität niemals zuverlässig. Du hast
Glück, dass du den Fehler dauernd hast, und nicht nur 1x pro Stunde...
;-)
Mach aus diesem asynchronen Reset einen synchronen Reset indem du ihn
ausschließlich im getakteten Teil deiner Prozesse abfrägst!
Das ist übrigens kein "könnte" oder "sollte", sondern ein "muss".
Insgesamt scheint die Beschreibung, naja, sagen wir mal auf maximale
"Lines of Code" optimiert nach dem Motto "Viel hilft viel". Aber das
kommt natürlich auch von der m.E. umständlichen 2-Prozess-Schreibweise.
Dazu das:
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html
Aber das hängt natürlich leider auch vom Lehrer, dessen Bücher und
seinen Vorlieben ab...
Zudem reichen bei einem synchronen Prozess der Reset (wenn für die
Funktion überhaupt nötig!) und der Takt in der Sensitivliste. Denn der
Simulator (und nur der schert sich überhaupt um diese Liste, dem
Synthesizer ist die schnuppe) berechnet bei einer Änderung eines der
Signale darin den betroffenen Prozess neu.
Nachdem in diesem Prozess also das mit dem fehlerhaften asynchronen
UhrZuruecksetzen korrigiert ist, seht da nur noch:
Lothar M. schrieb:> Und die Entprellung kannst du mitsamt der Flankenerkenn statt mit einer> FSM auch einfach mit einem Schieberegister machen
Eine mögliche Umsetzung mit einem Schieberegister und Bedenken, ob das
so, wie im obigen Code mit der FSM derzeit umgesetzt, überhaupt
funktioniert, ist im
Beitrag "Re: Ampelsteuerungsprogramm" zu
sehen... ;-)