Forum: FPGA, VHDL & Co. Process wird kontinuierlich durchloffen - Altium LiveDesign Board


von Daniel S. (schindla)


Lesenswert?

Hallo zusammen,

ich habe ein Problem mit unserem Projekt, bei dem wir einen 
Taschenrechner mit Tastatursteuerung in VHDL auf dem Altium LiveDesign 
Board beschreiben sollen.
Bis jetzt sollte es soweit funktionieren, dass man zwei Zahlen eingeben 
kann und diese zusammengesetzte Zahl dann auf einer 7-Segment-Anzeige 
ausgibt.
Die Eingabe funktioniert soweit, genauso wie die Ausgabe.
Mit einer Simulation funktioniert auch die Funtion soweit, bei der 
Synthese allerdings spielt das ganze verrückt.

Beim erstmaligen hochladen nimmt das signal ausgabe den wert x"00002" 
an(wieso ??), zustand den Wert x"FF", beim betätigen des Reset-Tasters 
hat zustand dann den Wert x"03" und die Anzeige, wenn man zB vor dem 
Reset-Drücken die A-Taste(oder 4-Taste) gedrückt hat, den Wert 
x"000AA"(oder x"00044").

Das heißt, dass der Process mit usignal in der Sensitive list 
kontinuierlich ausgeführt wird, ohne dass sich usignal ändert, damit 
liege ich ja denk ich schomal richtig.
Nach einigem Stöbern habe ich auch herausgefunden, dass die Sensitive 
list bei der Synthese nicht relevant ist. (wegen Schaltnetzverhalten)

Jetzt ist meine Frage wie man es erreichen kann, dass der unterste 
Process nur ausgeführt wird, wenn usignal sich ändert, bzw wenn eben ein 
neuer Tastencode rein kommt???

Ein Ansatz meinerseits wäre es nun gewesen ein checkEvent 
std_logic_vector(2 downto 0) Signal einzufügen, mit dem man steuern 
kann, wann ein Process "ausgeführt" wird. Z.B mit Bedingungen, dass der 
Process mit code_static nur ausgeführt wird, wenn das rechte Bit 
ungleich dem Mittleren, und der Process mit usignal nur ausgeführt wird, 
wenn das Mittlere ungleich dem Linken ist.
Die einzelnen Bits werden dannin den Processen an der richtigen Stelle 
jeweils mit checkEvent(i) <= not checkEvent(i) geändert
also im Endeffekt wie eine Flankenerkennung.
Ich hoffe ich konnte so ungefähr beschreiben, wie ich das ganze meine...

Ist meine Denkweise so korrekt oder passt da immer noch was nicht?
Ich muss dazusagen, dass uns das mit der Sensitive list, die bei der 
Synthese keinen juckt, nie vom Prof gesagt wurde und wir zuerst gar 
nicht wussten, was wir tun sollten.

Zum Testen haben wir leider nicht mehr soviel Zeit, deswegen wollte ich 
hier diese Frage stellen.

Schonmal viele Dank für die Bemühungen und sollten irgendwelche Infos 
fehlen, einfach nachfragen.

Codeausschnitt:
1
ENTITY taschenrechner_complete IS PORT (
2
  Reset: IN STD_LOGIC;
3
  KeyboardC: IN STD_LOGIC;
4
  KeyboardData: IN STD_LOGIC;
5
  state: OUT std_logic_vector(7 downto 0);
6
  seg: OUT std_logic_vector(47 downto 0)
7
  );
8
END taschenrechner_complete ;
9
10
architecture Behavioral of taschenrechner_complete is
11
12
----- Signale für Eingabe ----------------------------------
13
signal code_static: std_logic_vector(7 downto 0):="UUUUUUUU";
14
signal code_vorher: std_logic_vector(7 downto 0):="00000000";
15
signal code_temp: std_logic_vector(7 downto 0):="00000000";
16
17
----- Signale für Funktion -------------------------------
18
signal ausgabe: std_logic_vector(19 downto 0):="00000000000000000000";
19
signal usignal: std_logic_vector(3 downto 0):="0000";
20
signal zustand: std_logic_vector(7 downto 0):=x"01";
21
signal zeichen: std_logic:='0';
22
signal wert1: std_logic_vector(15 downto 0):=x"0000";
23
signal wert2: std_logic_vector(15 downto 0):=x"0000";
24
signal operator: std_logic:='1';   -- bei 1 + und bei 0 -
25
signal vorzeichen: std_logic:='0';
26
  
27
-- Signal für Ausgabe -------------------------------------
28
signal seg_intern: std_logic_vector(47 downto 0):=
29
"000000000000000000000000000000000000000000000000";
30
31
-- Signale zur Kontrolle ----------------------------------
32
signal test: std_logic:='1';
33
signal puls: std_logic:='1';
34
35
begin
36
37
-----------------------------------------------------------
38
----------------------- Eingabe ---------------------------
39
-----------------------------------------------------------
40
41
  ----- liest von Tastatur kommende Bitfolge in code ein und übergibt bei
42
  ----- kompletten Byte an code_temp
43
  PROCESS(KeyboardC)
44
  variable counter: integer:=0;
45
  variable code: std_logic_vector(10 downto 0):="00000000000";
46
  BEGIN
47
48
49
    IF (KeyboardC 'event and KeyboardC = '0') then
50
      code(counter) := KeyboardData;
51
      counter := counter +1;
52
      if(counter>10) then
53
        counter := 0;
54
      end if;
55
    end if;
56
57
    if(counter=0) then
58
      code_temp(7 downto 0) <= code(8 downto 1);
59
    end if;
60
    
61
  END PROCESS;
62
  
63
  
64
  -- Process wartet auf Releasecode und liest den darauf 
65
  -- folgenden Tastencode ein
66
  process(code_temp)
67
  begin
68
    if(code_vorher=x"F0" and not(code_temp=x"F0")) then
69
      code_static <= code_temp;
70
      code_vorher <= "00000000";
71
    elsif(code_temp=x"F0") then
72
      code_vorher <= x"F0";
73
    end if;
74
  end process;
75
76
-----------------------------------------------------------
77
----------------------- Funktion ---------------------------
78
-----------------------------------------------------------
79
80
81
PROCESS (code_static)
82
BEGIN
83
   IF (not(code_static=x"F0")) THEN
84
    test <= '1';
85
     case   code_static   is
86
87
      when x"70" => usignal <= "0000"; zeichen <= '0';  -- 0
88
      when x"69" => usignal <= "0001"; zeichen <= '0';  -- 1
89
      when x"72" => usignal <= "0010"; zeichen <= '0';  -- 2
90
      when x"7A" => usignal <= "0011"; zeichen <= '0';  -- 3
91
      when x"6B" => usignal <= "0100"; zeichen <= '0';  -- 4
92
      when x"73" => usignal <= "0101"; zeichen <= '0';  -- 5
93
      when x"74" => usignal <= "0110"; zeichen <= '0';  -- 6
94
      when x"6C" => usignal <= "0111"; zeichen <= '0';  -- 7
95
      when x"75" => usignal <= "1000"; zeichen <= '0';  -- 8
96
      when x"7D" => usignal <= "1001"; zeichen <= '0';  -- 9
97
      when x"1C" => usignal <= "1010"; zeichen <= '0';  -- A
98
      when x"32" => usignal <= "1011"; zeichen <= '0';  -- B
99
      when x"21" => usignal <= "1100"; zeichen <= '0';  -- C
100
      when x"23" => usignal <= "1101"; zeichen <= '0';  -- D
101
      when x"24" => usignal <= "1110"; zeichen <= '0';  -- E
102
      when x"2B" => usignal <= "1111"; zeichen <= '0';  -- F
103
      when x"79" => usignal <= "1010"; zeichen <= '1';  -- +
104
      when x"7B" => usignal <= "1011"; zeichen <= '1';  -- -
105
      when x"5A" => usignal <= "1100"; zeichen <= '1';  -- ENTER          
106
      when x"71" => usignal <= "1101"; zeichen <= '1';  -- ENTF(,)
107
      when x"66" => usignal <= "1110"; zeichen <= '1';  -- BACKSPACE
108
      when others => usignal <= "1111"; zeichen <= '1'; -- ERROR
109
    end case;
110
111
  else test <= '0';
112
  END IF;
113
END PROCESS;
114
115
116
Process(usignal)
117
BEGIN 
118
  if(test = '1') then
119
  if (reset='0') then
120
    ausgabe<= x"00000";
121
    vorzeichen <= '0';
122
    zustand <= x"01";
123
  
124
  else
125
    case zustand is
126
    
127
      when x"01" =>      -- Einlesen der 1. Zahl        
128
        if (zeichen = '0') then
129
          wert1 (15 downto 4) <= x"000";
130
          wert1 (3 downto 0) <= usignal;
131
          ausgabe (3 downto 0) <= wert1(3 downto 0);
132
          zustand <= x"02";
133
        end if;
134
        
135
      when x"02" =>       -- Einlesen der 2. Zahl
136
        if (zeichen = '1') then
137
          zustand <= x"05";
138
        elsif (zeichen = '0') then          
139
          wert1 (7 downto 4) <= wert1 (3 downto 0);
140
          wert1 (3 downto 0) <= usignal;
141
          ausgabe (7 downto 4) <= ausgabe (3 downto 0);
142
          ausgabe (3 downto 0) <= wert1(3 downto 0);
143
          zustand <= x"03";
144
        end if;
145
          
146
147
      when x"03" => zustand <= x"03";
148
149
      when others =>   zustand <= x"FF"; -- ERROR
150
151
    end case;
152
  end if;
153
  end if;
154
  
155
END Process;
156
157
-- Ausgabe hier weggelassen
158
159
end Behavioral;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Daniel Schindler schrieb:
1
 Process(usignal)
2
 BEGIN
3
   if(test = '1') then
4
   if (reset='0') then
Diese Sensitivliste ist unvollständig --> die Simulation passt nicht zur 
Realität...   :-o

> Nach einigem Stöbern habe ich auch herausgefunden, dass die Sensitive
> list bei der Synthese nicht relevant ist. (wegen Schaltnetzverhalten)
Richtig. Da sagt dir der Synthesizer mit einer Info oder Warnung dann, 
dass die Simulation nicht zur Realität passen wird. Und genau diese 
Unstimmigkeit ist das Problem. Denn was nützt eine Simulation, die nicht 
in die Realität umgesetzt werden kann.

1
 if (code_vorher=x"F0" and not(code_temp=x"F0")) then
2
       code_static <= code_temp;
3
       code_vorher <= "00000000";
Das gibt einen BÖSEN Glitch (oder gleich ein paar davon)!
Und garantiert bekommen es nicht alle Elemente im FPGA mit, dass da 
gerade der code_vorher mal 0xf0 war, und was dann damit passiert ist...

Und dann wird das Ganze noch weiter getrieben und mündet letztlich in 
einer kombinatorischen Schleife:
http://www.lothar-miller.de/s9y/categories/36-Kombinatorische-Schleife
Ich habe das mal auf das Wesentliche reduziert:
1
  if(test = '1') then
2
  if (reset='0') then
3
    zustand <= x"01";
4
  else
5
    case zustand is
6
7
      when x"01" =>      -- Einlesen der 1. Zahl
8
        if (zeichen = '0') then
9
           zustand <= x"02";
10
        end if;
11
12
      when x"02" =>       -- Einlesen der 2. Zahl
13
        if (zeichen = '1') then
14
          zustand <= x"05";
15
        elsif (zeichen = '0') then
16
          zustand <= x"03";
17
        end if;
18
19
      when x"03" =>  zustand <= x"03";
20
21
      when others => zustand <= x"FF"; -- ERROR
22
23
    end case;
24
  end if;
25
  end if;
26
27
END Process;
So werden in der Realität keine Zustandsautomaten codiert. Bei diesem 
Zustandsautomat hier fehlt der getaktete Speicher.
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html

>     IF (KeyboardC 'event and KeyboardC = '0') then
Was ist das für ein Takt?
In eine FPGA-Design gibt es im Idealfall genau 1 Takt, der für ALLE 
Zustandsautomaten und zur Einsynchronisierung von Eingängen und 
wasweißichnochalles verwendet wird. Dieser Takt hat dann so um die 
20-100MHz.

> Ist meine Denkweise so korrekt oder passt da immer noch was nicht?
Die Denkweise sieht für mich komplett softwarelastig aus. Das Ganze 
Konzept wirst du, so wie es da hingeschrieben ist, bestenfalls im 
Simulator ans Laufen bekommen, aber garantiert niemals auf einem FPGA.
Und blöderweise sind die Fehler so grundlegend, dass es nichts bringt, 
das, was du da gepostet hast, als Basis für ein funktionsfähiges Design 
zu nehmen.

> Ich muss dazusagen, dass uns das mit der Sensitive list, die bei der
> Synthese keinen juckt, nie vom Prof gesagt wurde
Das ist erst mal schnurzegal. Denn wenn die Sensitivliste stimmt und 
die Simulation funktioniert, dann funktioniert auch die Hardware, wenn 
ein paar Rahmenbedingungen passen. Hier mal meine Postulate:
1
Ein Design (insbesondere ein Anfängerdesign) hat genau 1 Takt, 
2
der immer auf dieselbe Flanke aktiv ist. 
3
Es gibt keinen (und schon gar keinen asynchronen) Reset.
4
Externe Signale werden über 2 Flipflops einsynchronisiert.
5
Jede Abweichung von diesen Regeln muß fundiert begründet werden können.
Wenn du die Begründungen für diese Postulate finden willst, dann such 
mal hier im Forum danach:
http://www.mikrocontroller.net/search?query=postulate&forums[]=9

> und wir zuerst gar nicht wussten, was wir tun sollten.
Ich hätte da gleich zu Beginn mal ein Buch abgegriffen.
Z.B. Reichardt&Schwarz VHDL Synthese

> Zum Testen haben wir leider nicht mehr soviel Zeit
Uuuuups. Das ist schlecht.

von Daniel S. (schindla)


Lesenswert?

> Diese Sensitivliste ist unvollständig --> die Simulation passt nicht zur
> Realität...   :-o
Das ist mir klar, ich hatten den Reset auch zunächst in der sensitive 
list, habe dann ein wenig rumgespielt (deswegen erscheint hier auch ein 
test signal, welches nicht direkt zum programm gehört) und bin daraufhin 
über Foren erst darauf gekommen, dass der Prozess eben ständig und nicht 
nur dann durchloffen wird, wenn sich ein Signal der sensitive list 
ändert

> Das gibt einen BÖSEN Glitch (oder gleich ein paar davon)!
> Und garantiert bekommen es nicht alle Elemente im FPGA mit, dass da
> gerade der code_vorher mal 0xf0 war, und was dann damit passiert ist...
wie gesagt die Eingabe hat bis jetzt funktioniert, eben auch das mit dem 
code_vorher usw, habe es auch auf der Anzeige getestet und alles


>>     IF (KeyboardC 'event and KeyboardC = '0') then
> Was ist das für ein Takt?
> In eine FPGA-Design gibt es im Idealfall genau 1 Takt, der für ALLE
> Zustandsautomaten und zur Einsynchronisierung von Eingängen und
> wasweißichnochalles verwendet wird. Dieser Takt hat dann so um die
> 20-100MHz.
tut mir leid, das habe ich vergessen zu erwähnen, KeyboardC ist der Takt 
der von der Tastatur (bei gedrückter Taste) reinkommt (laut 
Dokumentation zwischen 20 und 30 kHz)
uns wurde auch gesagt, dass wir bei diesem Projekt nicht mit dem Takt 
des FPGAs arbeiten müssen, sondern es reicht der von der Tastatur

> Die Denkweise sieht für mich komplett softwarelastig aus. Das Ganze
> Konzept wirst du, so wie es da hingeschrieben ist, bestenfalls im
> Simulator ans Laufen bekommen,
da magst du sehr recht haben, da wir bis jetzt hauptsächlich C/C++ 
programmiert haben
dennoch funktioniert die Eingabe und das Durchschieben der Zahlen, eben 
bis auf die Tatsache, dass der Process ständig durchloffen wird und man 
deshalb niemals in einem Zustand bleibt

> Das ist erst mal schnurzegal. Denn wenn die Sensitivliste stimmt und
> die Simulation funktioniert, dann funktioniert auch die Hardware
dennnoch ist es leider so herübergekommen, als würde auch bei der 
Synthese eben der Process nur beim Ändern aufgerufen, deshalb haben wir 
zunächst

die Höhe ist ja eigentlich dabei, dass der Prof das letzte mal selbst 
glaub ich eine Stunde vor diesem Process gesessen ist, und ihm ist 
nichts dabei aufgefallen bzw er wusste nicht, wie man das ändern könnte
das ist das traurige dabei

Grundsätzlich jetzt nocheinmal eine Frage zu dem Ganzen:
Wird ein Process richtig ausgeführt, wenn die sensitive list falsch ist, 
im Process selbst aber alles richtig implementiert wurde?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Daniel Schindler schrieb:
> die Höhe ist ja eigentlich dabei, dass der Prof das letzte mal selbst
> glaub ich eine Stunde vor diesem Process gesessen ist, und ihm ist
> nichts dabei aufgefallen bzw er wusste nicht, wie man das ändern könnte
Ja nun, ein paar Schwachstellen habe ich ja mal aufgezeigt. Und die sind 
nicht ausschließlich im fraglichen Prozess. Allerdings kann der in 
diesem Prozess beschriebene Zustandsautomat sicher nie zuverlässig 
funktionieren. Das wäre der erste Schritt zum asynchronen Computer.
Mein Tipp: Mach da erst mal einen Takt rein. Also probiers einfach mal 
so:
1
Process BEGIN
2
  wait until rising_edge(KeyboardC ); 
3
  if (reset='0') then
4
    ausgabe<= x"00000";
5
    vorzeichen <= '0';
6
    zustand <= x"01";
7
  else
8
    case zustand is
9
    :
10
    :
Und dann sieh deine Simulation nochmal an. Denn der Simulator ist der 
Debugger der Hardware.

> Grundsätzlich jetzt nocheinmal eine Frage zu dem Ganzen:
> Wird ein Process richtig ausgeführt, wenn die sensitive list falsch ist,
> im Process selbst aber alles richtig implementiert wurde?
Ja, weil der Prozess eben nicht ausgeführt, sondern in Hardware 
übersetzt wird. Und den Synthesizer interessiert die Sensitivliste 
keinen Deut. Er setzt nur die Beschreibung im Prozess in entsprechende 
Hardware um. Und an Hardware gibt es für dich im FPGA zwei Dinge: 1. 
Kombinatorik (und-oder-nicht-multiplexer-usw...) und 2. D-Flipflops als 
Speicherelemente.

> dennoch funktioniert die Eingabe und das Durchschieben der Zahlen, eben
> bis auf die Tatsache, dass der Process ständig durchloffen wird und man
> deshalb niemals in einem Zustand bleibt
Das ist dann genau die Stelle, wo man in der Praxis mal ein Design in 
die Tonne klopft. Weil man zwar zu 3/4 fertig ist, aber einsehen muss, 
dass man so nicht ins Ziel kommt.

> das ist das traurige dabei
Schade, eigentlich...

von Daniel S. (schindla)


Lesenswert?

dankeschön für die Antworten
ich werde das ganze morgen früh ein wenig überarbeiten und mal schaun 
wies anders funktioniert
haben jetzt noch bis zum 12. Dezember Zeit, allerdings kommen wir auch 
nicht immer ins Labor ;)

bin ja gespannt was das noch wird :D

von Thomas Thol (Gast)


Lesenswert?

Daniel Schindler schrieb:
> die Höhe ist ja eigentlich dabei, dass der Prof das letzte mal selbst
> glaub ich eine Stunde vor diesem Process gesessen ist, und ihm ist
> nichts dabei aufgefallen bzw er wusste nicht, wie man das ändern könnte
> das ist das traurige dabei

Tja, der fachkräftemangel macht auch vor ner FH nicht halt.

Ich drück Euch die Daumen!

von Bronco (Gast)


Lesenswert?

Hallo Daniel,

wie Lothar schon geschrieben hat: Du brauchst einen Takt!
Das ist jemandem, der von CPUs (µCs) kommt, i.a.R. nicht klar, weil in 
der CPU der Takt implizit in der Hardware steckt und man ihn als 
Programmierer nicht sieht.

Das Problem ist, daß im FPGA ein Vektor (eine Einheit mehrerer Bits) 
nicht zu jederzeit integer ist! D.h. wenn Du eine Zuweisung machst wie
1
a <= "11";
dann wird a(0) eine andere Lauzeit haben als a(1), d.h. a(0) wird zu 
einem anderen Zeitpunkt auf '1' gehen als a(1). Dazwischen hast Du einen 
Zustand wie "01" oder "10", den es laut Code gar nicht geben kann.
Daher ist es zwingend notwendig, mit Takten zu arbeiten, damit die 
Zeitpunkt von Zuweisung und Abfrage klar definiert sind und die Inhalte 
stabil sind.
Das ist völlig anders in C, wo alle Bits eines Worts immer gleichzeitig 
geschrieben und gelesen werden (weil die CPU getaktet ist).

Ohne Takt passiert es Dir, daß Du in Deinen Vektoren Werte vorfindest, 
die es eigentlich gar nicht geben dürfte. Da spring Deine State-Machine 
in undefinierten States rum, die es laut Code nicht gibt.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Bronco schrieb:
> Dazwischen hast Du einen Zustand wie "01" oder "10",
> den es laut Code gar nicht geben kann.
Zur weiteren Suche das Schlüsselwort:
das ist der bereits angesprochene "Glitch".

> dann wird a(0) eine andere Lauzeit haben als a(1), d.h. a(0) wird zu
> einem anderen Zeitpunkt auf '1' gehen als a(1).
Und das überaus unschöne ist, dass dieses eine Signal an verschiedenen 
Stellen im FPGA unterschiedliche Werte haben kann und haben wird. Siehe 
dazu das Thema "Einsynchronisieren":
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html

von Daniel S. (schindla)


Lesenswert?

Jaaaaa genau das mit den Zustand, den es nicht geben kann, hatten wir 
auch zu genüge...
Jetzt wird mir das auch endlich mal klar, danke!

Kann ich aber dann mit dem Takt vom CPU trotzdem noch abfragen, wann der 
Clock vom Keyboard ne steigende bzw fallende Flanke erreicht?
Muss dazu der Takt vom CPU einfach schnell genug sein?
Weil für das Einlesen der hereinkommenden Bits der Tastatur muss man 
eben fallende Flanken des Tastaturtakts erkennen können.

von Nadine16 (Gast)


Lesenswert?

Daniel Schindler schrieb:
> mit dem Takt vom CPU trotzdem noch

Wo hast du denn auf einmal eine CPU her? Bzw. wo steckt denn die in 
deinem Aufbau nun?

von Daniel S. (schindla)


Lesenswert?

Das Altium Board hat eine CPU mit nem Takt von 50 MHz, der Takt, den ich 
oben verwende, ist der von der PS2-Tastatur, der reinkommt, wenn eine 
Taste gedrückt wird. Und es hieß anfangs noch, dass dieser Takt für 
unser Projekt ausreicht. Allerdings habe ich heute nochmal nachgebort 
und dann sagte der Prof wieder was anderes...

Hier mal ein kurzer Auszug aus der Dokumentation:

Auf dem Board ist ein Spartan 3 FPGA der Firma Xilinx bestückt. Die 
exakte Typenbezeichnung
lautet "XC3S1000", mit der Gehäuseform "FG456" (Fine-Pitch Ball Grid 
Array mit 456 Pins).
Hierbei stehen die ersten 4 Ziffern für die Xilinx Spartan 3 Familie, 
während die Zahl 1000 die
Anzahl der System Gates angibt (hier: 1000k). Der FPGA ist mit 1920 
konfigurierbaren
Logikblocks (48 Reihen x 40 Spalten) ausgerüstet, verfügt u.a. über 432k 
Block Ram, 24
Multiplizierern (18 Bit) und maximal 391 benutzerdefinierbare Ein- bzw. 
Ausgänge.
Das Board besitzt einen 50 MHz Oszillator, der
mit den Pin GCLK (Global Clock) verdrahtet ist.

von Daniel S. (schindla)


Lesenswert?

Morgen sind wir von nachmittag bis abends im Labor. Dann werde ich wohl 
das ganze mal komplett überarbeiten, dass die Geschichte synchron mitm 
Takt vom FPGA läuft, denn das mit den Glitches leuchtet mir jetzt erst 
so richtig ein!

von berndl (Gast)


Lesenswert?

Na also,

den FPGA mit den 50MHz betreiben (ist fuer nen S3 ein Klacks), dann eure 
ominoese PS2-Clock einfach einsynchronisieren und als normales 
Logiksignal weiter verarbeiten.

Alles andere wird da nix, das geht schief (ok, fuer nen Schein im 
Studium mag es reichen, aber das ist dann eher ein Armutszeugnis fuer 
den Prof...)

von Bronco (Gast)


Lesenswert?

Daniel Schindler schrieb:
> Kann ich aber dann mit dem Takt vom CPU trotzdem noch abfragen, wann der
> Clock vom Keyboard ne steigende bzw fallende Flanke erreicht?
> Muss dazu der Takt vom CPU einfach schnell genug sein?

Bitte nicht durcheinander bringen!

Dein FPGA braucht einen Takt (woher auch immer), mit dem Du die interne 
Logik taktest. Wenn es möglich ist, benutze nur einen einzigen Takt.
Das ist der Takt, der in den Anweisungen wie
1
wait until rising_edge(LogikTakt);
drinn steht.

Du kannst weiterhin beliebig viele Signale, die sich "Takt" nennen, an 
Eingangs-Pins anschließen, solange Du sie nicht intern als Logik-Takt 
verwendest, sondern eben nur als ganz normale Eingangssignale.
Z.B. so:
1
wait until rising_edge(LogikTakt); 
2
if (Eingangssignal_namens_Takt = '1') then

Der eigentliche Logiktakt muß so schnell sein, daß Du alle Signale 
abtasten und verarbeiten kannst.

von Daniel S. (schindla)


Lesenswert?

Es sieht schon ein wenig besser aus.
Ich hab jetz für die Keyboardclockabfrage folgendes angesetzt:

IF (KeyboardC_vorher = '1' and KeyboardC = '0') then

KeyboardC ist das hereinkommende Signal vom Tastaturclock
KeyboardC_vorher wird immer umgesetzt, wenn ein die Bedingung oben bzw 
die dazugehörige zur steigenden Flanke erfüllt ist, also so ca wie

IF (KeyboardC_vorher = '1' and KeyboardC = '0') then
....
KeyboardC_vorher <= '0';
end if;

und insgesamt arbeitet alles jetzt synchron mit dem Takt vom Board.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Daniel Schindler schrieb:
> KeyboardC ist das hereinkommende Signal vom Tastaturclock
> KeyboardC_vorher wird immer umgesetzt, wenn ein die Bedingung oben bzw
> die dazugehörige zur steigenden Flanke erfüllt ist, also so ca wie
Kann man machen, muss man aber nicht...  ;-)

Die einfachste Flankenerkennung ist etwa so:
1
  process begin
2
    wait until rising_edge(clk50mhz);
3
    if (kbclk_alt='0' and KeyboardC='1') then
4
      -- steigende Flanke
5
    end if;
6
    if (kbclk_alt='1' and KeyboardC='0') then
7
      -- steigende Flanke
8
    end if;
9
    kbclk_alt <= KeyboardC;
10
  end process;

Aaaaaber!!! In dieser FSM (ja, das ist eine Zustandsmaschine, weil 
kbclk_alt abhängig von irgendwas den Zustand wechselt) ist immer noch 
ein asynchroner Eingang. Und was mit asynchronen Eingängen in FSM 
passiert, das habe ich schon geschrieben...

Wie eine Flankenerkennung auf einem asynchronen Eingang aussieht, findet 
sich dort:
http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung

von Daniel S. (schindla)


Lesenswert?

Die "Flinke Flankenerkennung" hat mich jetz schon ein wenig 
weitergebracht, da die Tastaturtasten prellen. Jetzt funktioniert die 
Eingabe so, dass bei gedrückter Taste ein konstanter Code (so wie es 
sein sollte) eingelesen wird und nicht wie zuvor verschiedene Codeworte 
und der Zähler in der Eingabe zählt jetzt auch richtig.
Allerdings stimmt das erhaltene Codewort nicht mit dem Tastencode laut 
Dokumentation überein, sondern es ist eine manchmal mehr, manchmal 
weniger abweichende Bitfolge.
Aber vielleicht können wir trotzdem auch damit weiterarbeiten... mal 
sehen

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Daniel Schindler schrieb:
> Die "Flinke Flankenerkennung" hat mich jetz schon ein wenig
> weitergebracht, da die Tastaturtasten prellen.
Wie ist denn die Schaltung dieser "Tastatur", die ja offenbar auch einen 
TAkt ausgeben kann?

von Daniel S. (schindla)


Angehängte Dateien:

Lesenswert?

> Wie ist denn die Schaltung dieser "Tastatur", die ja offenbar auch einen
TAkt ausgeben kann?
Den Schaltungsaufbau haben wir nicht in die Hand bekommen, nur eben die 
prinzipielle Funtionsweise der Tastatur.
Hier mal die Dokumentation dazu.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Das ist offenbar eine stinknormale Ps2 Tastatur. Findest du auch auf 
meiner HP. Und dieser "Takt" der Tastatur ist nur ein Signal, aber 
niemals eine Taktquelle für ein FPGA.

von Bronco (Gast)


Lesenswert?

Daniel Schindler schrieb:
> Allerdings stimmt das erhaltene Codewort nicht mit dem Tastencode laut
> Dokumentation überein, sondern es ist eine manchmal mehr, manchmal
> weniger abweichende Bitfolge.

Mögliche Fehler:
- Die Signale sind nicht sauber zum Logik-Takt synchronisiert
- Du tastest zu einem falschen Zeitpunkt des PS2-Clocks ab

von Daniel S. (schindla)


Lesenswert?

Vielen, vielen Dank für eure Antworten und eure Tipps!!!!!
Es funktioniert endlich :-)
Die Eingabe hab ich einigermaßen von Lothars Homepage übernommen mit ein 
paar Änderungen, die FSM für die Funktion musst ich nicht viel ändern, 
obwohl mir klar ist, dass da auch noch was zu tun ist.
Und sonst läuft alles synchron mit dem Boardtakt.
Er reagiert zwar dabei auf fallende UND steigende Flanken (dabei habe 
ich gelesen, dass man lieber nur ein fallende oder steigende reagieren 
sollte), aber trotzdem tut er ;-)
Lediglich einige Implementierungsdetails sind noch nicht komplett 
ausgefeilt, aber das dürfte kein Problem mehr sein.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Daniel Schindler schrieb:
> Es funktioniert endlich :-)
Schön.
Für andere, die später ein ähnliches Problem haben, wäre deine 
aktuelle und (besser) funktionierende Beschreibung sicher auch nicht 
schlecht.

von Daniel S. (schindla)


Lesenswert?

> Für andere, die später ein ähnliches Problem haben, wäre deine
> aktuelle und (besser) funktionierende Beschreibung sicher auch nicht
> schlecht.

Das wollte ich sowieso noch machen, nachdem wir noch die restlichen 
Teile fertig bearbeitet haben.

von Daniel S. (schindla)


Lesenswert?

So, heute war die Abnahme und es hat alles einwandfrei funktioniert 
sogar mit erweiterter Funktion. Nochmal vielen Dank an alle die mir 
dabei geholfen haben. Hier ist dann mal der komplette Code:

[EDIT: Code als Anhang im nächsten Post]

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Da war noch was:
1
Antwort schreiben
2
Wichtige Regeln - erst lesen, dann posten!
3
    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
Ich habe deine Datei mal aus dem Post rausgelöscht und hier angehängt...



Eine etwas ungewöhnliche Beschreibung eines Clock-Enables:
1
  if(clk='1' and clk'event and (checkEvent = '1' or OP_typed='1')) then
Aber die Synthesizer von heute kapieren, was gemeint ist...  ;-)

von Daniel S. (schindla)


Lesenswert?

>
1
> Antwort schreiben
2
> Wichtige Regeln - erst lesen, dann posten!
3
>     Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
4
>
> Ich habe deine Datei mal aus dem Post rausgelöscht und hier angehängt...

Oh entschuldigt, hatte nicht viel Zeit und hab den Code nur schnell 
hochgeladen.

Ich habe noch Fragen bezüglich gewissen Fehlern die während der 
Projekterstellung mal aufgetreten sind. Wäre nett, wenn mir jemand 
erklären könnte, woran die Fehler lagen:

1. Eine Abfrage wie  if(usignal =“0010“)  hat ein falsches Verhalten 
gezeigt. Wenn man aber zB schreibt if(usignal(0)='0' and usignal(1)='1' 
...) oder das ganze in einen case reinpackt funktionert es einwandfrei.

2. Wenn ich in einem Process unabhängige Codezeilen getauscht habe, kam 
es bei jedem Tausch zu einem anderen Verhalten (zB aufeinanderfolgende 
Zuweisungen an zwei verschiedene Signale. Allerding muss ich dazusagen, 
dass das nur bis dahin passierte, bis wir das ganze synchronisiert 
haben.
Lag das an der Asynchronität?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Daniel Schindler schrieb:
> 1. Eine Abfrage wie  if(usignal =“0010“)  hat ein falsches Verhalten
> gezeigt. Wenn man aber zB schreibt if(usignal(0)='0' and usignal(1)='1'
> ...) oder das ganze in einen case reinpackt funktionert es einwandfrei.
>
> 2. Wenn ich in einem Process unabhängige Codezeilen getauscht habe, kam
> es bei jedem Tausch zu einem anderen Verhalten (zB aufeinanderfolgende
> Zuweisungen an zwei verschiedene Signale. Allerding muss ich dazusagen,
> dass das nur bis dahin passierte, bis wir das ganze synchronisiert
> haben.
> Lag das an der Asynchronität?
Zweimal ja. Solche "eigenartigen" Verhaltensweisen kommen zu 95% von 
asynchronen Taktdomänenüergängen. Und ganz kurios wird es dann, wenn du 
im Modul A irgendwas änderst und das Modul B zeigt dann Fehler, weil 
sich dort irgendeine Laufzeit um ein paar ns verändert...

Und der Trick an der Sache ist: mit einer Simulation findest du solche 
Fehler nicht, weil da die ganzen klitzekleinen Fertigungstoleranzen, 
Temperaturabhängigkeiten und Versorgungsabhängigkeiten, Taktjitter und 
wasweißichnochalles nicht abgebildet werden (können).

von Daniel S. (schindla)


Lesenswert?

Ahja ok super danke! So hab ichs mir auch schon gedacht.

Da wäre dann noch eine Sache und zwar wenn man sich die Ausgabe ansieht:
Ich wollte das mit dem Codewandeln von dem Signal ausgabe zuerst mit 
einer "for-Schleife" und dann eben mit einem "case ausgabe" angehen, was 
nicht funktionierte.
Erst als ich den case durch ein if ersetzt habe, konnte das ganze so 
umgesetzt werden mit for...
Worin lag hier das Problem?

von Bronco (Gast)


Lesenswert?

Daniel Schindler schrieb:
> was nicht funktionierte.
Das lag an Deinem Fehler!

Im Ernst: Eine Ausage wie "es funktioniert nicht" enthält zu wenig 
Information, um zu erraten, warum es nicht funktioniert.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Daniel Schindler schrieb:
> Worin lag hier das Problem?
Wie lautete die Fehlermeldung?

von Hawa M. (hawamand)


Lesenswert?

Lothar Miller schrieb:
> ...
> Die einfachste Flankenerkennung ist etwa so:
>
1
>     if (kbclk_alt='1' and KeyboardC='0') then
2
>       -- steigende Flanke
3
>     end if;
4
>
> ...
alt=1,neu=0 -> fallende Flanke

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

hawa mand schrieb:
> alt=1,neu=0 -> fallende Flanke
Ich sag mal einfach, den Fehler hätte ich absichtlich eingebaut... 
;-)

von Bronco (Gast)


Lesenswert?

Lothar Miller schrieb:
> Ich sag mal einfach, den Fehler hätte ich absichtlich eingebaut...
Das hast Du doch nur eingebaut, um zu prüfen, ob wir auch aufpassen.

von Daniel S. (schindla)


Lesenswert?

> Wie lautete die Fehlermeldung?

Ist jetzt schon einige Zeit her, aber ich glaub es kam irgendwas mit 
"unconstrained array". Wäre jetzt auch nicht so wichtig, dachte nur dass 
dabei prinzipiell etwas nicht stimmt aufgrund von irgendeinem 
Hardwareverhalten.
Naja morgen ist die Präsentation und ich glaub die Fehlerbehandlung ist 
trotzdem schon ausführlich genug ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.