Guten Vormittag,
ich habe versucht, einen Impulszähler zu realisieren, sprich:
Man drückt einen Taster, dann soll sich der Wert auf insg. zwei
7-Segment-Anzeigen um 1 erhöhen.
Wow, das muss echt einfach sein -dachte ich.
Jetzt hab ich jedoch das Problem, dass beim Drücken des Tasters der
Zähler immer woanders landet , d.h. mal wird "07". mal "23" usw.
angezeigt, obwohl von "00" gestartet wurde.
Ich will aber, dass der Wert sich immer nur um 1 erhöht. Wieso es nicht
so passiert, weiß ich nicht genau aber ich habe eine Vermutung:
Ich habe einen 50Mhz Takt, d.h. der Prozess wahrscheinlich wird viel zu
oft aufgerufen. Der Taster bleibt ja paar Millisekunden oder so
gedrückt, deswegen wird zu oft hochgezählt.
Ist das richtig so? Kann ich das Problem lösen, indem ich den Takt von
50Mhz auf zb 2Hz reduziere?
Maximilian L. schrieb:> Ich habe einen 50Mhz Takt, d.h. der Prozess wahrscheinlich wird viel zu> oft aufgerufen. Der Taster bleibt ja paar Millisekunden oder so> gedrückt, deswegen wird zu oft hochgezählt.
Kommt drauf an, wie deine Beschreibung aussieht...
> Ist das richtig so? Kann ich das Problem lösen, indem ich den Takt von> 50Mhz auf zb 2Hz reduziere?
Vermutlich ja, das ist aber völliger Murks.
Der richtige Weg ist es, den Taster zu entprellen und eine
Flankenerkennung drauf zu setzen. Es gibt hier im Forum zig Diskussionen
dazu.
> Ich habe einen 50Mhz Takt, d.h. der Prozess wahrscheinlich wird viel zu> oft aufgerufen.
In der Hardware wird da nirgends irgendein "Prozess aufgerufen". Sondern
es wird deine Hardwarebeschreibung vom Synthesizer in Flipflops und LUTs
übersetzt, dann vom Placer platziert, vom Router verdrahtet und vom
BitGen in einen Bitstrom umgewandelt, der dann ins FPGA geladen wird.
Sieh dir also mal den RTL-Schaltplan an, dann siehst du, was der
Synthesizer gemacht hat und kannst kontrollieren, ob das dem entspricht,
was du eigentlich beschreiben wollstest.
Da fehlen wohl zwei Vorgänge in deinem unbekannten VHDL-Code:
1. Signal vom Taster entprellen
z.B. mit einem Zähler, der losläuft, sobald der Taster gedrückt ist und
zurückgesetzt wird, sobald der Taster nicht gedrückt ist.
Bei einem bestimmten Zählerstand (höchstwertiges Bit nehmen!) stoppt der
Zähler und dieses Stop-Signal ist das entprellte.
2. Entprelltes Signal differenzieren
mit Gatter über ein FlipFlop, so daß 1 geliefert wird, solange am FF
Input das Signal 1 ist, am FF Output aber noch 0.
Dieses Signal als CE für deinen Zähler und das funktioniert.
Danke soweit.
Ich denke ich mache es folgendermaßen:
Ich werde einfach die vier möglichen Tasterzustände abfragen.
Diese Lösung scheint mir am einfachsten.
Orientiert habe ich mich hier
https://www.mikrocontroller.net/articles/Entprellung ab
"Flankenerkennung".
Alles klar,
haben Sie noch einen Tipp wie weit der Verzögerungszähler bei 50MHz
zählen sollte?
Ich schätze einfach mal aus dem Bauch: bis 25.000.000 -> dann sollte
ein Drücken jede halbe Sekunde funktionieren, oder?
Maximilian L. schrieb:> Ich schätze einfach mal aus dem Bauch: bis 25.000.000 -> dann sollte> ein Drücken jede halbe Sekunde funktionieren, oder?
Ein Taster, der eine halbe Sekunde braucht, "fühlt" sich nicht gut an.
Er lässt sich nur sehr holprig bedienen.
Und zudem prellt kein halbwegs funktionierender Taster für eine halbe
Sekunde. Ich würde da bestenfalls 50ms ansetzen.
> wie weit der Verzögerungszähler bei 50MHz zählen sollte?
Also muss der Zähler 50ms/20ns = 2_500_000 Schritte zählen und somit von
0 bis 2499999 laufen.
Ich bin leider gescheitert das richtig umzusetzen. Vielleicht hat jemand
Lust sich den Code mal anzusehen und den Fehler zu finden.
Der Impulszähler springt weiterhin um zu viele Schritte nach vorne...
Die beigefügte Beschreibung dürfte sich überhaupt nicht synthetisieren
lassen, da das Signal V_BT überhaupt nicht existiert. Zudem wurde auch
nicht Lothars Hinweis beachtet, dass Eingangssignale einsynchronisiert
werden müssen; dies ist um so wichtiger, weil der Wert von BT(1) an
mehreren Stellen verwendet wird.
Duke Scarring schrieb:> Jetzt wäre der richtige Zeitpunkt eine Testbench aufzusetzen und sich> das Verhalten des Codes mal im Simulator anzuschauen.
Wobei sich da natürlich sofort die Frage stellt: hat jemand mal paar
schöne Modelle von prellenden Tastern zur Hand, mit der man die
Testbench bestücken kann?
Ist das irgendwie sowas?
Andreas S. schrieb:> Die beigefügte Beschreibung dürfte sich überhaupt nicht synthetisieren> lassen, da das Signal V_BT überhaupt nicht existiert. Zudem wurde auch> nicht Lothars Hinweis beachtet, dass Eingangssignale einsynchronisiert> werden müssen; dies ist um so wichtiger, weil der Wert von BT(1) an> mehreren Stellen verwendet wird.
Stimmt, dieses "V_" gehört da nicht hin. Beim Testlauf hatte ich das da
noch nicht stehen. Mein Fehler
Maximilian L. schrieb:> Ich hab sowas leider nicht
Deswegen musst Du Testbench ja auch selbst erstellen. Möglicherweise
besitzt Dein FPGA-Entwicklungswerkzeug sogar die Möglichkeit, zu einem
HDL-Quelltext auf Knopfdruck den Rumpf der zugehörigen Testbench zu
erstellen.
Danke euch,
ich bin jetzt soweit, dass ich den Taster einsynchronisiert habe , und
zwar durch 2 Flip Flops. Jetzt sollte es sehr unwahrscheinlich zum
metastabilen Zustand kommen
Jörg W. schrieb:> Ist das irgendwie sowas?
Ich habe gerade kein Bild von 'echtem' Prellen da, das sieht i.d.R. noch
viel wilder aus, aber für die Simulation kann man das gelten lassen.
Maximilian L. schrieb:> ich bin jetzt soweit, dass ich den Taster einsynchronisiert habe , und> zwar durch 2 Flip Flops. Jetzt sollte es sehr unwahrscheinlich zum> metastabilen Zustand kommen
In Deinem Quellcode hast Du nach wie vor einen nicht einsynchronisierten
Reset, den Du zudem noch als asynchronen Reset eines getakteten
Prozesses verwendest. Schlimmer geht es kaum. Zwar werden in Deinem
konkreten Projekt mögliche Probleme nur sehr, sehr selten auftreten, und
wenn sie auftreten, dass nur so kurzzeitig, dass Du sie vermutlich nicht
einmal bemerken könntest, aber trotzdem ist das ganze nicht sauber.
Vielen Dank, das habe ich außer Acht gelassen. Da der Reset hier nicht
wirklich notwendig ist, werde ich ihn ganz weglassen.
Im Anhang der verbesserte Code ohne den Reset
Duke Scarring schrieb:> Jörg W. schrieb:>> Ist das irgendwie sowas?> Ich habe gerade kein Bild von 'echtem' Prellen da, das sieht i.d.R. noch> viel wilder aus, aber für die Simulation kann man das gelten lassen.
Da fällt mir doch gerade ein: habe vor längerer Zeit mal ein paar
Dreh-Encoder am Logic Analyzer aufgezeichnet. Habe mal von zweien die
Daten in eine VHDL-Testbench umgewandelt. Falls jemand also real
prellende Kontakte haben oder seine Encoder-Entprellung mit realen Daten
simulieren möchte: hier sind sie. ;-)
(Für einen einfachen Kontakt nimmt man einfach eine Spur eines der
Encoder, oder schneidet sich nur ein paar Teile aus dem Code aus.)
Maximilian L. schrieb:> ich bin jetzt soweit, dass ich den Taster einsynchronisiert habe , und> zwar durch 2 Flip Flops. Jetzt sollte es sehr unwahrscheinlich zum> metastabilen Zustand kommen
Bei einer Taktfrequenz von 50MHz gibt es absolut keine relevanten
metastabilen Zustände. Heutige Flipflops schaffen es locker, sich
innerhalb von 2..3ns zu "beruhigen". Deshalb muss das Thema
"Metastabilität" bei Taktfrequenzen bis zu 300MHz überhaupt nicht in
Betracht gezogen werden.
Warum man trotzdem einsynchronisieren muss? Das steht in aller
Ausführlichkeit im Link, den ich zum Thema "FSM mit asynchronem Eingang"
weiter oben schon gepostet habe. Das, was dort besprochen wird, hat
wiederum überhaupt nichts mit Metastabilität zu tun. Und solche Fehler
können und werden auch schon bei niedrigsten Taktfrequenzen passieren.
Maximilian L. schrieb:> Im Anhang der verbesserte Code ohne den Reset
In einem getakteten Prozess kommt nach dem getakteten Block nicht noch
irgendwelcher kombinatorischer Klimbim, von dem ohnehin keines der
Signale in der Sensitivliste auftaucht. Eine derart unvollständige
Sensitivliste sorgt zuverlässig dafür, dass die Simulation nicht zur
Hardware passt. Der Synthesizer sagt dir das auch, wenn du die Infos und
Warnungen mal genau anschaust.
> if ... and taster_old='0' then
taster_old ist immer '0'...
Danke für die Info, dass der kombinatorische Kram vor/nach den Prozess
gehört.
Ich werde den kombinatorischen Kram wahrscheinlich dann einfach in ein
Untermodul packen.
Ist das Vorhandensein des kombinatorischen Klimbims denn auch wirklich
ein Problem, dass für die Fehlfunktion sorgt? Also ist das der Grund
wieso der
Zähler beim Drücken des Tasters zu weit hochzählt? Das könnte ich mir
nämlich nicht vorstellen.
Oder liegt das ernsthafte Problem hier "taster_old ist immer '0'..."?
Sorry für die ganzen Nachfragen, der Einstieg in VHDL fällt mir wegen
der ganzen anderen Programmiersprachen etwas schwierig.
Maximilian L. schrieb:> Ich werde den kombinatorischen Kram wahrscheinlich dann einfach in ein> Untermodul packen.
Sieh dir an, wie man das nebenläufig (concurrent) beschreibt. Und wenn
du einem 7 bit breiten Vektor ein 7 Bit breiten Wert zuweist, dann
brauchst du keinen Range angeben:
Und wenn du nicht jedem Signal noch den Namen "out" oder "output" gibst,
obwohl es kein FPGA-Ausgang ist und unnötige Zwischensignale weglässt,
dann wird das Ganze noch lesbarer.
1
seg4<="1000000"wheneiner=0else
2
"1111001"wheneiner=1else
3
:
4
"0000000"whendigit=8else
5
"0010000";
6
7
seg5<="1000000"whenzehner=0else
8
"1111001"whenzehner=1else
9
:
10
"0000000"whenzehner=8else
11
"0010000";
> Oder liegt das ernsthafte Problem hier "taster_old ist immer '0'..."?
Mit einer Simulation findest du das in kurzer Zeit heraus.
> Oder liegt das ernsthafte Problem hier "taster_old ist immer '0'..."?
So hast du es geschrieben:
1
ifrising_edge(clk)then
2
iftaster_deb='1'andtaster_old='0'then
3
impulscounter<=impulscounter+1;
Weil hier aber taster_old mit '0' initialisiert ist und niemals geändert
wird, zählt der Zähler alle 20ns hoch, so lange der Taster gedrückt ist.
Du kannst es z.B. so machen:
1
process
2
begin
3
waituntilrising_edge(clk);
4
ff1_out<=BT(1);
5
ff2_out<=ff1_out;--ff2_out ist nun zu verwenden
6
taster_old<=taster_deb;
7
endprocess;
Allerdings könnte man den ganzen Zirkus ohne Prozesse auch wesentlich
kompakter schreiben:
1
signalbtsr:std_logic_vector[1downto0]:="00";-- Schieberegister für BT(1)
taster_old<=taster_debwhenrising_edge(clk);-- für Flankenerkennung
6
:
7
:
8
--Entprellen
9
processbegin
10
waituntilrising_edge(clk);
11
ifbtsr(1)=taster_debthendebcnt<=0;
12
elsedebcnt<=debcnt+1;
13
endif;
14
15
if(debcnt=2499999)thentaster_deb<=btsr(1);
16
endif;
17
endprocess;
> Ist das Vorhandensein des kombinatorischen Klimbims denn auch wirklich> ein Problem, dass für die Fehlfunktion sorgt? Also ist das der Grund> wieso der Zähler beim Drücken des Tasters zu weit hochzählt?
Nein. Allerdings ist deine Simulation falsch und passt nicht zur
Hardware. Sowas bringt dich jetzt schon (zeig mal deine Simulation) und
später bei größeren Designs erst recht in ernstliche Schwierigkeiten.
> Oder liegt das ernsthafte Problem hier "taster_old ist immer '0'..."?
Mit einer Simulation findest du das in kurzer Zeit heraus.
--> Genau darin lag das Problem. Danke für die ganzen Tipps, ich werde
mal meinen Code schöner gestalten.
Maximilian L. schrieb:> Danke für die ganzen Tipps, ich werde> mal meinen Code schöner gestalten.
Das ist auch wichtig, aber vorher kommt die Testbench.
Im Anhang mal ein Gerüst, wie das auschauen könnte.
Duke