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
Gast
#4066598
Wenn du des Englischen maechtig bist: https://www.youtube.com/watch?v=EtJBqvk1ZZw Schau mal diesen Link an. Da wird das ganz gut erklaert. Gruss Ralf
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-Flankenerkennung http://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 | |
2 | |
3 | |
4 | |
5 | |
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?
Gast
#4067667
Ja. Die "01" dient zum Erkennen der Flanke. Duke
Gast
#4067700
Daniel K. schrieb: > 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 :) > ). Da hats hier auf Mikrocontroller.net ein Projekt wo ein PS/2 Controller benutzt wird: http://www.mikrocontroller.net/svnbrowser/redz0mb1e/src/vhdl/kb2vhdl_fk.vhd?view=markup http://www.mikrocontroller.net/articles/Retrocomputing_auf_FPGA#Tastatur_2 http://www.mikrocontroller.net/articles/Retrocomputing_auf_FPGA#Tastatur_3 Tückisch ist der Scancode da er zweimal gesendet wird, beim Drücken und beim Loslassen. Aber nur so kann man erkennen ob die Shifttaste mitgedrückt wurde. MfG,
Gast
#4067703
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 :)
Gast
#4069066
Kannst Du die Testbench hier mit reinstellen? Dann kann man die Simulation nachvollziehen. Das macht vieles leichter. Duke
Ahh sorry. Dachte ich hätte sie mit hoch geladen...
Gast
#4069081
Kein Problem. Erstmal passt hier PS2_Keyboard(entity) nicht zu PS2_Keyboard(testbench):
1 | |
2 | |
3 | |
Hier die Ursache:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
Nur als Tipp: Die Verbindung der Signale über Positionen ist auch Fehleranfällig:
1 | |
Nun fehlt noch das Keyboard-ROM:
1 | |
2 | |
3 | |
Duke
mmh das habe ich alles behoben, aber es kommt immer noch kein Wert aus dem ROM :(
Gast
#4069146
Zeig doch mal Deinen ROM. Duke
Ich verwende einen Block Memory Generator mit dem angehängten Initialisierungsfile.
Gast
#4069193
Da muss doch trotzdem ein VHDL (oder verilog) File rausfallen. Sonst kann man das ja gra nicht simulieren. Duke
mmh ich weiß jetzt nicht welches VHDL File du meinst. Ich habe dir mal den Ordner hochgeladen...da kannst du dann mal gucken.
Gast
#4069226
Der müßte es sein: VGA.srcs\sources_1\bd\Font_ROM\hdl\Font_ROM.vhd Na, schaun wir mal.
Gast
#4069227
Quatsch. Keyboard_ROM.vhd natürlich...
Gast
#4069251
Wenn man in Zeile 29+1 (=Adresse 0x1d) des .mif-File was reinschreibt, kommt auch was raus. Duke
....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...
mmh ich habe mal eine Frage... Und zwar verstehe ich mein Simulationsergebnis nicht. Ich habe folgende Dateien: PS/2-Keyboard
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
Und die folgende TB:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
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?!
Hat sich erledigt. War wohl leicht spät gestern Abend....
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
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
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?
Gast
#4072863
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:
1 | |
2 | |
3 | |
4 | |
5 | |
Duke
mmh das verstehe ich nicht so ganz. Wie erzeugst du den dann das "Enable"? Dafür brauche ich doch auch nen Clock.
Daniel K. schrieb: > Wie erzeugst du den dann das "Enable"? Dafür brauche ich doch auch nen > Clock. So wie dort im Lauflicht: http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html Oder dort in der PWM (unteres Drittel der Prescaler): http://www.lothar-miller.de/s9y/categories/47-PWM Oder so wie dort, wo gleich 3 unterschiedliche Clock-Enables erzeugt werden: http://www.lothar-miller.de/s9y/archives/85-SAB0600.html Der Trick: jedes der Designs läuft mit 1 einzigen Takt, dem des Quarzoszillators....
Hallo, danke für die Antworten. Der Fehler war aber was ganz anderes :) Ich hatte
1 | |
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
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.


