Ich entwerfe eine Tastatur in VHDL. Alles funktioniert gut, wenn nur eine einzige Taste gedrückt wird. Ich scanne jede Spalte auf einen Tastendruck in einer Zustandsmaschine und wenn keine Taste gedrückt wird, wechsle pin4pin6pin7pin2 = "0000"
ich in den nächsten Zustand, um die nächste Spalte zu scannen. Also setze ich die Spalten pin3pin1pin5
nacheinander auf "001"
, "010"
und "100"
.
Beim Scannen pin3pin1pin5
wird "001"
dann pin4pin6pin7pin2
einfach "0100"
"9" gedrückt. Ich deklariere in VHDL pin4pin6pin7pin2
als Eingabe- und pin3pin1pin5
als Ausgabeports. Wenn ich gleichzeitig 6 und 9 drücke pin6
und . Die erste gedrückte Taste wird gelesen, die zweite wird ignoriert. Wenn ich gleichzeitig 3 und 7 drücke, gewinnt der erste, der mit wenigen ms vor Gewinnen gedrückt wurde, und die erste Taste wird gelesen, die zweite Taste wird ignoriert, und sind .pin7
high
pin2
pin4
high
Hier ist der knifflige Teil. Wenn ich gleichzeitig 4 und 6 drücke, erwarte ich pin7
zu sein, high
aber es wird low
und pin4pin6pin7pin2 = "0000"
, was ich nicht verstehe, wie und warum. Da "0000"
erkannt wird, dass keine Taste gedrückt wurde, springt die Zustandsmaschine von Zustand zu Zustand. Während man 4 und 6 hält, wenn man mehrmals drückt und 4 verlässt, wird es als mehrmals gedrückte 6 erkannt, was ein großer Fehler ist . Ich würde mich freuen, wenn Sie mir beim Debuggen helfen könnten!
Dasselbe passiert mit "1" und "2", dasselbe mit "7" und "8", nur für die Tasten in derselben Reihe. Da dies ein laufendes Projekt ist, kann ich meinen VHDL-Code nicht online stellen :( Ich würde mich freuen, wenn Sie mir Tipps geben könnten, um dies zu überwinden!
Unten, ich lade meinen Code nicht auf das Board hoch, es wird kein Code ausgeführt. Beim Anschließen Pin5
an Masse schaltet ein einzelnes Drücken auf 1,2,4,5,7,8,*,0 die Pin3
LED nicht ein, aber wenn ich gleichzeitig 6 und dann 4 drücke, ist die Pin3
LED an und die Pin7
LED ist immer noch an, aber Wenn mein Code ausgeführt wird, passiert dies nicht. Vielleicht habe ich etwas falsch angeschlossen und zum Glück Pin7
ist es an, ich weiß es nicht ...
Nachfolgend finden Sie die Schaltpläne der Tastaturplatine:
Die kurze Antwort:
Kehre deine Logik um. Treiben Sie die Spaltenauswahlleitungen mit Open-Drain- (oder Open-Collector-) Logik, wobei die ausgewählte Spalte nach unten gezogen wird und die nicht ausgewählten Spalten floaten. Wenn Sie sich eine Zeile ansehen, wird ein Tastendruck durch eine „0“ erkannt. Nicht gedrückte Tasten werden durch eine „1“ erkannt.
Nun die Einzelheiten:
Wie EEIgenuity betont, führt das Drücken von 2 Tasten in derselben Reihe zu einem Kurzschluss zwischen den entsprechenden Spalten. Dieses (und andere Probleme mit mehreren Tastendrücken) wird normalerweise in einer Tastaturmatrix überwunden, indem eine Diode in Reihe mit jedem Schalter hinzugefügt wird.
Da das Hinzufügen von Dioden für Sie keine Option ist, müssen Sie die Ausgänge Ihrer inaktiven Spaltenauswahlen floaten, um zu vermeiden, dass Sie versuchen, sie auf die entgegengesetzte Polarität als Ihre aktive Spaltenauswahl zu treiben. Dies geschieht mit Open-Drain-Logik. Wenn Ihre Spaltenauswahl direkt an ein CPLD oder FPGA gebunden ist, sollten Sie dies in Ihrem VHDL-Code erreichen können.
Das Foto in Ihrer Frage zeigt, dass Sie in jeder Spalte und jeder Zeile einen Pullup-Widerstand haben. Die Klimmzüge an den Säulen sind unnötig, werden aber nichts schaden. Die Pull-Ups in jeder Reihe stellen einen hohen Zustand sicher, sofern sie nicht durch den Open-Drain-Treiber an den Spaltenauswahlen (durch einen geschlossenen Schalter) nach unten gezogen werden.
Ich musste einige Annahmen über Ihre Schaltung treffen, da Sie keinen vollständigen Schaltplan oder Ihren VHDL-Code bereitgestellt haben. Du sagst
wenn keine Taste gedrückt wird, das ist die Bedingung pin4pin6pin7pin2 = "0000"
Auf dem von Ihnen bereitgestellten Foto werden jedoch Pull-up-Widerstände angezeigt. Dies impliziert, dass Sie bereits irgendwo eine logische Inversion haben, möglicherweise in Ihrem VHDL-Code oder (weniger wahrscheinlich) Invertern zwischen Ihren Zeilen und Ihrem Logikgerät (CPLD oder FPGA).
Bearbeiten:
Gemäß Ihrem Kommentar verwenden Sie in Ihren Beschreibungen eine negative Logik: "0000" zeigt an, dass alle vier Pins hoch sind usw. Dies ist der Fall, vorausgesetzt, die Spaltenauswahl- und Zeilensignale gehen direkt von Anschluss 2 in Ihrem Schaltplan zum FPGA Befolgen Sie meine obigen Anweisungen, indem Sie Open-Drain-Logik für die Spaltenauswahlausgänge in Ihrem FPGA verwenden.
Ich bin kein VHDL-Experte, aber ich habe das von Xilinx gefunden :
Leiten Sie den Open-Drain-Puffer mithilfe des folgenden Codes ab:
VHDL:
daut <= 'Z' wenn din='1' sonst '0';
Beachten Sie auch, dass in Ihrem Schaltplan alle LEDs rückwärts verdrahtet sind. Die Anoden gehen zu den Strombegrenzungswiderständen und die Kathoden gehen zu den Signalleitungen. Die LEDs leuchten, wenn die Signalleitungen auf Low gezogen werden.
pin4pin6pin7pin2 = "0000"
damit, dass es eigentlich keinen Tastendruck gibt 1111
. In meiner Frage sollten 1s 0 sein, 0s sollten 1s sein, ich habe versucht, die Frage ein wenig zu verschlüsseln, entschuldigen Sie das, wenn es zu Missverständnissen geführt hat ...out <= 'pin3' when din='1' else '0';
pin3_internal
wird wahrscheinlich ein Ausgabeport sein, und es ist nicht möglich, Ausgabeports in VHDL zu lesen. Und was ist "Z"? Ein Bitsignal? Ich verstehe diesen when
Fall nicht, der normale, den ich kenne, ist wie folgt:output <= in0 WHEN "00",
pin3_out <= 'Z' when pin3_internal = '1' else '0';
wenn er Klammern hätte, würde ich ihn schneller verstehen :) Das heißt wann Ich überprüfe , ob pin5
ich schweben sollte pin3
und pin1
, also denke ich, ich sollte dies in derselben Zeile tun, in der ich einstelle, pin3pin1pin5 <= "110"
und pin3_internal
hier pin3_out <= 'Z' when pin3_internal = '1' else '0';
ist keiner der Pin2, Pin7, Pin6, Pin4? Wo soll und soll ich pin3_internal
arbeiten?dout <= 'Z' when din='0' else '1';
, ich weiß, dass Sie viel geschrieben haben, aber würden Sie mir bitte die Lösung ein bisschen näher erläutern?Da Sie VHDL verwenden und eine asynchrone Eingabe haben, schreibe ich diese Antwort, um sicherzustellen, dass Sie Vorsichtsmaßnahmen getroffen haben. Ich bin mir nicht sicher, ob dies Ihr Problem ist, aber es könnte sehr gut sein.
Siehe eine Frage, die ich vor einiger Zeit gestellt habe: VHDL: Empfangsmodul schlägt zufällig fehl, wenn Bits gezählt werden
Jetzt sagst du das:
Da "0000" als keine gedrückte Taste erkannt wird, springt die Zustandsmaschine von Zustand zu Zustand. Während man 4 und 6 hält, wenn man mehrmals drückt und 4 verlässt, wird es als mehrmals gedrückte 6 erkannt, was ein großer Fehler ist.
Das ist etwas ähnlich dem, was ich konfrontiert war. Ich hatte ein Problem, bei dem meine Zustandsmaschine Zustände übersprang, was unmöglich schien.
Wenn Sie die Antworten auf die oben verlinkte Frage lesen, werden Sie sehen, dass es empfehlenswert ist, einen Synchronisierer zur Eingabeleitung hinzuzufügen, bevor sie in Ihre Zustandsmaschine eingespeist wird. Dies wird normalerweise mit zwei D-Flip-Flops in Reihe erreicht:
Wenn Ihre Tasteneingabe nicht mit Ihrer HW synchronisiert ist, treten sehr bizarre Probleme auf, die ich bei meinem N64-Projekt erlebt habe. Das Hinzufügen dieses kleinen bisschen HW war fast wie Magie.
Überprüfen Sie daher zuerst, ob Ihre Eingaben synchronisiert werden.
async_in
mit 3 Taktzyklen verzögert ist, aber sein Wert und alles ist gleich?Das ist eine interessante Frage! Der Grund, warum Pin7 niedrig ist, wenn Sie Taste4 und Taste6 drücken, liegt an Pin3 und Pin5.
Um es weiter zu erklären, werden Pin3 und Pin5 niemals gleichzeitig hoch sein - einer von ihnen wird immer ein Pfad zur Erde sein (gemäß Ihrem Design). Wenn Sie also Taste 4 und Taste 6 drücken, erstellen Sie einen Pfad zur Masse für Pin7.
Siehe Bild:
fru1tbat
Anarkie
Anarkie
Tut
Anarkie
Tut
Tut
Anarkie
Tut