Hallo zusammen,
da mein VGA nun sehr zufriedenstellend funktioniert möchte ich gerne
noch eine PS/2 Tastatur an mein FPGA anschließen.
Über einen Mikrocontroller habe ich das Auslesen schon realisiert, von
daher weiß ich ungefähr wie das abläuft.
Im FPGA möchte ich das gerne über eine State Machine machen und habe
dafür schon mal was gezeichnet um mir den Ablauf zu verdeutlichen (PS/2
ist relativ einfach, das weiß ich aber das ist dann schön zur Übung :)
).
Ist das Ablaufdiagramm so richtig? Wenn ja, dann würde ich mal versuchen
das so in VHDL zu implementieren.
Danke schon mal :)
Daniel K. schrieb:> Ist das Ablaufdiagramm so richtig?
Die Daten liegen als Scancode vor. Das ist noch weit weg vom ASCII-Code.
Dazu kommt noch ein Break-Code, der vor einer losgelassenen Taste
gesendet wird. Und ein Timeout würde mir auch fehlen.
Ich mache solche seriellen Protokolle gerne mit einem Schieberegister
statt einem Bitzähler:
http://www.lothar-miller.de/s9y/archives/75-PS2-Tastatur.html
Danke für die Antworten :)
Lothar Miller schrieb:> Daniel K. schrieb:>> Ist das Ablaufdiagramm so richtig?> Die Daten liegen als Scancode vor. Das ist noch weit weg vom ASCII-Code.> Dazu kommt noch ein Break-Code, der vor einer losgelassenen Taste> gesendet wird. Und ein Timeout würde mir auch fehlen.>> Ich mache solche seriellen Protokolle gerne mit einem Schieberegister> statt einem Bitzähler:> http://www.lothar-miller.de/s9y/archives/75-PS2-Tastatur.html
Ahh sorry. Das mit dem Scancode hatte ich komplett vergessen :(
Im Mikrocontroller hatte ich das mit einer Headerdatei und einem Array
gemacht, wo ich an die entsprechende Posi den passenden ASCII Wert
abgelegt habe.
Das muss ich hier natürlich auch berücksichtigen.
Der Tipp mit dem Schieberegister ist gut :) Das werde ich dann direkt
mal so umsetzen.
Danke für das Video Tutorial. Ich werde es mir speichern. Ist ganz
praktisch ein paar Tutorials als Video zu haben :)
Hallo Lothar,
ich habe mir mal dein Beispiel angeschaut.
Warum hast du das hier gemacht?:
DataSR <= DataSR(0) & PS2_Data;
ClkSR <= ClkSR(0) & PS2_Clk;
if (ClkSR = "10") then
RxRegister <= DataSR(1) & RxRegister(10 downto 1);
end if;
Ist das aus dem selben Grund wie im Video um das eventuell verrauschte
PS/2-Signal zu filtern?
Daniel K. schrieb:> Ist das aus dem selben Grund wie im Video um das eventuell verrauschte> PS/2-Signal zu filtern?
Mehr oder weniger ja. Nur mit weniger Flipflops...
Zum Hintergrund die beiden dort:
http://www.lothar-miller.de/s9y/categories/18-Flankenerkennunghttp://www.lothar-miller.de/s9y/categories/5-Entprellung> Ist das aus dem selben Grund wie im Video um das eventuell verrauschte> PS/2-Signal zu filtern?
Ein "verrauschtes" Signal sollte dort gar nicht auftreten, denn sonst
hast du prinzipiell Probleme mit instabiler Übertragung. Denn durch
diese "Filterung" wird natürlich auch der Abtastzeitpunkt verschoben.
Hallo Lothar,
ok, ich habe dann direkt mal noch eine Frage zu deinem Code.
Bei der PS/2 Schnittstelle handelt es sich ja um eine asynchrone
Übertragung.
Du schreibst ja nun folgendes:
1
ClkSR<=ClkSR(0)&PS2_Clk;
2
3
if(ClkSR="10")then
4
...
5
endif;
Das dient, wenn ich das richtig verstanden habe, auch zum eintakten des
asynchronen Clock-Signals vom PS/2 oder?
Sobald dein Schieberegister den Wert "10" erreicht hat weiß du, dass ein
Flankenwechsel geschehen ist, da zu dem Zeitpunkt t der Pegel High war
und zu dem Zeitpunkt t+1 war der low (t ist dabei der Takt der 50MHz
Quelle).
Sehe ich das soweit richtig :o?
Daniel K. schrieb:> Ist das Ablaufdiagramm so richtig? Wenn ja, dann würde ich mal versuchen> das so in VHDL zu implementieren.
Nope, das passt nicht. Der scancode kann sich auch über 3 bytes
erstrecken (windows media keys) und ich erkenne nicht wie die FSM
erkennen soll ob die Taste gerade gedruckt oder losgelassen wurde oder
ob die shifttaste noch aktiv ist.
MfG,
Hallo zusammen,
so ich habe mein PS/2 Controller für die Tastatur fertig (dank dem Video
und dem Artikel vom Lothar :) ) - siehe Anhang.
Ich habe mir zudem noch ein Top-Design für das Keyboard gemacht, wo ich
ein ROM einbinde mit dessen Hilfe ich den Scancode in ASCII Zeichen
umwandel.
Dieses ROM ist als Blockmemory ausgeführt, lässt sich aber in der
Simulation nicht benutzen. Ich bekomme meinen Wert vom
Tastaturcontroller, der dann die Adresse für mein ROM ist, aber aus dem
ROM kommt nichts raus (siehe Screenshot).
Das ROM habe ich in dem Top-Design auskommentiert, da es im fertigen
Design ebenfalls Probleme gemacht hat und ich es erst einmal raus lassen
wollte. Für die Simulation war es drin.
Und dann noch eine kleine Frage nebenbei...
Für mein fertiges Design habe ich ebenfalls eine TB gemacht. Da in
meinem Design aber ein DCM ist muss ich die Auflösung des Simulators auf
1ps stellen, da der DCM sonst keinen Takt erzeugt.
Wie kann ich das für den Vivado Simulator machen?
Danke schon mal :)
....habe ich mich da etwa wieder verzählt :(?
Dank dir für den Hinweis!
Jetzt noch eine andere Frage.
Ich habe jetzt folgende Situation:
- Mein Top Design läuft mit 100MHz
- VGA läuft mit 25MHz
- PS/2 läuft mit 5MHz
Der PS/2 stellt ein Signal bereit, wenn er mit dem Empfangen fertig ist.
Dieses Signal ist beim PS/2-Controller 1 Takt lang. Wenn ich dieses
Signal nun im Top-Design verarbeiten will um z.B. die Position des
VGA-Zeichens um eins zu erhöhen muss ich dieses langsamere Signal ja
eintakte, da bei einer einfachen High-Abfrage würde die Abfrage ja im
Top-Design 20x durchlaufen bis sich das Ready-Signal vom PS/2 ändert.
Soviel zum theoretischen...
Praktisch wäre das dann wieder so, dass ich ein Schieberegister baue und
das Signal (wie in Lothars Link) eintakte und dann wieder auf "10"
vergleiche, sprich wenn das Signal einen Wechsel von High nach Low (oder
umgekehrt) macht.
Ist diese Überlegung korrekt?
Daniel K. schrieb:> Ich habe jetzt folgende Situation:> - Mein Top Design läuft mit 100MHz> - VGA läuft mit 25MHz> - PS/2 läuft mit 5MHz
Lass doch einfach alles mit 100MHz laufen. Dann sind alle
Handshakesignale einen Zyklus lang für jeweils 10ns aktiv. Einfacher
gehts nicht.
Lothar Miller schrieb:> Daniel K. schrieb:>> Ich habe jetzt folgende Situation:>> - Mein Top Design läuft mit 100MHz>> - VGA läuft mit 25MHz>> - PS/2 läuft mit 5MHz> Lass doch einfach alles mit 100MHz laufen. Dann sind alle> Handshakesignale einen Zyklus lang für jeweils 10ns aktiv. Einfacher> gehts nicht.
Stimmt :P
Btw. ich habe den Fehler im Initialisierungsfile gefunden.
Ich habe zwei Zahlen ausgelassen, weswegen der Versatz entstanden ist...
Warum bekomme ich in der Simulation nun ein so langes Ready-Signal wie
auf dem Screenshot zu sehen?
Normal müsste er doch sehen, dass Ready = 1 ist und beim nächsten Takt
da rein springen und "Read" setzen.
Daraufhin springt die State-Machine in die Abfrage, löscht "Ready" und
gibt die Daten aus. Wegen dem fehlenden Ready wird dann in der TB das
Read-Signal gelöscht.
Das sollte doch nur 4-5 Takte dauern und nicht so lange?!
mmh ich habe jetzt noch ein Problem damit mehrere Buchstaben auf meinem
Bildschirm ausgeben zu lassen.
Ich habe meinen VGA-Core und meinen PS/2-Core. Mein PS/2-Core gibt ein
Signal aus sobald die Wandlung bereit ist (Codes im Anhang).
Jetzt habe ich aber das Problem, dass der Buchstabe an mehrere Adressen
meines Display-RAMs geschrieben wird (das RAM besitzt pro Buchstaben auf
dem Bildschirm einen Speicherplatz und das RAM wird vom VGA
ausgelesen...das funktioniert 1a).
Ich habe folgenden Codeschnipsel für die Tastatur
Da scheint es noch ein Problem mit dem "Ready"-Signal zu geben...
Die Idee ist darauf zu warten, dass der Tastaturcontroller das
"Ready"-Signal setzt, dann entsprechend das "Read"-Signal setzen um den
Controller auszulesen, wodurch der Controller die Daten ausgibt und
wieder in den ersten Zustand der State-Machine springt.
Sobald ein Zeichen ausgelesen ist, wird die Schreibadresse für das
Display-RAM um eins erhöht (und das auch wenn ich statt dem 1kHz Clock
den Systemclock verwende).
Aber sobald ich eine Taste drücke wird nach und nach der komplette
Bildschirm mit dem selben Buchstaben vollgeschrieben, was bedeutet das
er die ganze Zeit die Schreibadresse für das Display-RAM erhöht.
Aber warum?
Daniel K. schrieb:> Aber warum?
Weil Du immer noch mit Clock, statt Clock-Enable arbeitest.
> if(rising_edge(Clock_1kHz)) then
Versuch mal wirklich auf nur einen Clock umzusteigen:
Hallo,
danke für die Antworten.
Der Fehler war aber was ganz anderes :)
Ich hatte
1
if(PS2_Ready<='1')then...
geschrieben ;)
Das das einen Fehler verursacht ist klar...wenn ich einem Signal nen
High zuweise und dann nach High abfrage ist die If-Abfrage natürlich
immer erfüllt...
Daniel K. schrieb:> wenn ich einem Signal nen High zuweise und dann nach High abfrage ist> die If-Abfrage natürlich immer erfüllt...
Wo weist du dem Signal das High zu?
In der If-Abfrage kannst du nämlich nicht so einfach was zuweisen, wir
sind hier ja nicht bei C. Es ist eher so, dass ein std_logic Signal, das
nur '0' oder '1' sein kann, natürlich immer auch kleiner-gleich '1'
ist...
Lothar Miller schrieb:> Daniel K. schrieb:>> wenn ich einem Signal nen High zuweise und dann nach High abfrage ist>> die If-Abfrage natürlich immer erfüllt...> Wo weist du dem Signal das High zu?> In der If-Abfrage kannst du nämlich nicht so einfach was zuweisen, wir> sind hier ja nicht bei C. Es ist eher so, dass ein std_logic Signal, das> nur '0' oder '1' sein kann, natürlich immer auch kleiner-gleich '1'> ist...
Ah ok :)
Dachte es wäre in dem Fall identisch wie C, dass der Wert dann dem
Signal zugewiesen wird.
Danke für die Korrektur :o