Hallo alle,
ich bin gerade dabei für ein kleines Projekt mit meinem Spartan 3E
Starter einen rotary encoder (Drehregler) mit VHDL zu programmieren.
Hier auf der mikrocontroller-Seite gibt es einen guten Artikel darüber
und auch schon fertigen Code. Ich wollte das jedoch alleine versuchen
und es möglichst verständlich programmieren. Könnt ihr mir sagen, ob das
so in Ordnung ist? Ich habe ein bischen bedenken, da ich von möglicher
Glitches gelesen habe. Die sind bei mir nicht berücksichtigt, wie wirkt
sich das aus? Wenn das ein Problem ist, wie kann ich das in meinen Code
verbessern ohne zu viele Änderungen zu machen? Danke!
Was genau stört sich an dem Code aus dem Drehgeber-Artikel? Wir haben
den in leicht modifizierter Form (2-fach und 1-fach Abtastung) weltweit
in Industrieprojekten im Einsatz, ohne einen Ausfall.
Nichts stört mich an dem Code, bin mir sicher, dass das der optimale
ist.
Wollte das nur selbst versuchen und hätte es, wenn ich den anderen Code
noch nie gesehen hätte, immernoch so gemacht wie ich es jetzt gemacht
habe. Über den Sinn bitte nicht weiter nachdenken, habe das eher aus
Interesse gemacht :)
Felix O. schrieb:> Könnt ihr mir sagen, ob das> so in Ordnung ist?
Nein, das ist nicht in Ordnung, weil 2 verschachtelte if (x'event and x
= '1') nicht möglich sind.
Das ist einerseits nicht synthetisierbar, und andererseits wäre es ja
ein großer Zufall wenn die Flanken für clk und rotary_center "genau"
zusammenfallen würden, oder?
Wie sieht denn deiner Meinung nach ein Bauteil aus, das einen Eingang
für eine fallende und einen für eine steigende Taktflanke hat? Und wenn
eine Taktflanke theoretisch Null ps dauert, wie lange wird in diesem
Design der rotary_use auf '1' sein? Wie lange würde rotary_use im relaen
FPGA '1' sein?
> Ich wollte das jedoch alleine versuchen und es möglichst verständlich> programmieren. Könnt ihr mir sagen, ob das so in Ordnung ist?
rotary_use = '0'; <--- Das geht so sicher nicht. Das ist kein VHDL...
VHDL ist eine Hadrwarebeschreibungssprache. Du musst also ein Bild
oder eine Vorstellung von der Hardware haben, die du beschreiben
willst. Sonst kommt nichts Brauchbares dabei heraus...
> Ich habe ein bischen bedenken, da ich von möglicher Glitches gelesen> habe. Die sind bei mir nicht berücksichtigt, wie wirkt sich das aus?
So, dass dein Design evtl. jede ms ein Problem hat, oder aber auch nur
1x pro Woche...
> Wenn das ein Problem ist, wie kann ich das in meinen Code verbessern> ohne zu viele Änderungen zu machen?
Gar nicht. Am einfachsten löschst du den Code und sorgst beim
Neuschreiben dafür dafür, dass du nur 1 einzigen Takt, der auf nur 1
Flanke aktiv ist, im Design hast. Such einfach mal hier im Forum nach
meinen Postulaten. Die gelten für alle Anfänger... ;-)
BTW: warum verwendest du nicht die Funktionen rising_edge() oder
falling_edge() für einen Takt?
> Wie sieht denn deiner Meinung nach ein Bauteil aus, das einen Eingang> für eine fallende und einen für eine steigende Taktflanke hat? Und wenn> eine Taktflanke theoretisch Null ps dauert, wie lange wird in diesem> Design der rotary_use auf '1' sein? Wie lange würde rotary_use im relaen> FPGA '1' sein?
Also würde rotary_use verdamt schnell hin und her wechseln und ich
könnte das gar nicht sinnvoll benutzen.
>>> Ich wollte das jedoch alleine versuchen und es möglichst verständlich>> programmieren. Könnt ihr mir sagen, ob das so in Ordnung ist?> rotary_use = '0'; <--- Das geht so sicher nicht. Das ist kein VHDL...
Äh, ja sollte natürlich "<=" sein.
>> Wenn das ein Problem ist, wie kann ich das in meinen Code verbessern>> ohne zu viele Änderungen zu machen?> Gar nicht. Am einfachsten löschst du den Code und sorgst beim> Neuschreiben dafür dafür, dass du nur 1 einzigen Takt, der auf nur 1> Flanke aktiv ist, im Design hast.
Ja, dumm von mir eigentlich klar..
> BTW: warum verwendest du nicht die Funktionen rising_edge() oder> falling_edge() für einen Takt?
Wir hatten das in einem Einführungskurs zu VHDL in der UNI mit dem
clk'event ... gemacht aber auch mit dem Hinweis, dass rising_edge()
genauer ist, da mit der neunwertigen-Logik bei meiner Beschreibung ja
auch eine Veränderung von z.B. u nach 1 als treffendes Ereignis gesehen
wird..
Werde mich mal an das rising_edge() gewöhnen.
Gustl Buheitel schrieb:> So sieht meins aus:
Was tut diese Beschreibung?
Besonders da (und ähliche Abfragen) würde ich Probleme erwarten:
1
ifcount0<255andencin(0)='1'then
2
count0<=count0+1;
Denn wenn encin() tatsächlich ein asynchroner Eingang ist, dann hast du
da garantiert eine amoklaufende Statemachine (=Zähler). Genau wie da
beschreiben:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Ich hätte eine Variante, die einen Takt und die beiden Spuren als
Eingang bekommt, und einen Zähler als Ausgang hat:
http://www.lothar-miller.de/s9y/categories/46-Encoder
Und dort: zuallererst werden die beiden Eingänge einsynchronisiert...
Felix O. schrieb:>> Wie sieht denn deiner Meinung nach ein Bauteil aus, das einen Eingang>> für eine fallende und einen für eine steigende Taktflanke hat? Und wenn>> eine Taktflanke theoretisch Null ps dauert, wie lange wird in diesem>> Design der rotary_use auf '1' sein? Wie lange würde rotary_use im relaen>> FPGA '1' sein?> Also würde rotary_use verdamt schnell hin und her wechseln und ich> könnte das gar nicht sinnvoll benutzen.
Es wäre einfach immer '0', weil eine Flanke keine Zeitdauer hat...
> Werde mich mal an das rising_edge() gewöhnen.
Kann nicht schaden...
Warum?
Was ich will, ist auch debouncen.
Also ich "sample" da quasi den asynchronen Eingang. Daher funktioniert
das auch nur wenn die Clock sehr viel schneller ist wie das Signal von
Encoder.
Wenn jetzt der Encoder von 0 auf 1 wechselt geht der Zähler langsam nach
oben und wenn er von 1 auf 0 wechselt geht der Zähler nach unten. Mit
dem Zähler füge ich da nur etwas "Trägheit" ein, quasi wie einen
Kondensator der geladen/entladen wird.
Wenn da Jitter bei ist geht da zähler nicht ganz so schnell nach
oben/unten und erreicht die 255/0 nie.
Mit
1
ifcount0<8then
2
level0<='0';
3
elsifcount0>247then
4
level0<='1';
5
endif;
habe ich dann Schwellen gesetzt, also wenn der Zähler < 8 dann ist das
für mich hinreichend Null und wenn > 247 ist es hinreichend Eins. Man
könnte das jetzt auch sicher anders machen, aber so funktioniert es
recht gut.
Lothar Miller schrieb:>> Werde mich mal an das rising_edge() gewöhnen.> Kann nicht schaden...
Obwohl ich gerade sehen, dass in Dokumenten von Xilinx auch clk'event
and clk ='1' genutzt wird. Warum machen die das, wenn das andere
offensichtlich besser ist? Oder nutzen die nicht std_logic? :D
Siehe angehängtes Dokument.
clk'event and clk ='1'
und
wait until rising_edge(clk);
ist genau das Gleiche.
Bei Ersterem hast du aber ein if das du irgendwann wieder schließen
musst, daher finde ich das nicht so hübsch.
Gustl Buheitel schrieb:> Also ich "sample" da quasi den asynchronen Eingang. Daher funktioniert> das auch nur wenn die Clock sehr viel schneller ist wie das Signal von> Encoder.
Nein, das geht sicher dann und wann schief, denn der Zähler verzählt
sich einfach. Es ist nämlich nicht so, dass der Eingang nur auf ein
einziges Flipflop des Zählers geht, sondern auf alle Zählerflipflops
parallel. Wenn da nicht die unterschiedlichen Laufzeiten zu den acht
Flipflops durch das Routing wären...
> clk'event and clk ='1'> und> wait until rising_edge(clk);> ist genau das Gleiche.
Nein, da fehlt noch das clk'last. Aber es wird vom Synthesizer das
gleiche draus gemacht, weil es in der realen Hardware nur '0' und '1'
für einen Takteingang gibt...
Felix O. schrieb:> Obwohl ich gerade sehen, dass in Dokumenten von Xilinx auch clk'event> and clk ='1' genutzt wird.
Danke für die Steilvorlage.
Du darfst nicht alles glauben, was dir von irgendwoher irgendwie
zukommt. Siehe den Klassiker
Beitrag "Re: Variable vs Signal"> Warum machen die das, wenn das andere offensichtlich besser ist?
Keine Ahnung. Vielleicht "Weil man das hier schon immer so gemacht hat!"
und encin(0) ist mein Eingang.
Jetzt kommt da die Taktflanke, es wird geguckt ob count0 < 255 and
encin(0) = '1' oder count0 > 0 and encin(0) = '0' zutrifft und wenn,
dann wird count0 <= count0 +1 oder count0 <= count0 -1 gemacht.
Aber dabei get doch nie der Eingang direkt an den Zähler sondern immer
nur die 1. Klar, Zähler und Takt müssen natürlich so gewählt sein, dass
der Zähler die Addition durchgeführt hat bevor der nächste Takt kommt,
aber das ist bei mir mit 8-Bit und 75MHz locker gegeben.
Gustl Buheitel schrieb:> Aber dabei get doch nie der Eingang direkt an den Zähler
Richtig, es ist noch vertrackter...
> Ich habe:
1
waituntilrising_edge(clk);
2
:
3
ifcount0<255andencin(0)='1'then
4
count0<=count0+1;
5
elsifcount0>0andencin(0)='0'then
6
count0<=count0-1;
7
endif;
> und encin(0) ist mein Eingang.
Und encin(0) geht (über die Carry-Chain) auf alle 8 Flipflops von count0
(das ist ja ein synchroner Zähler). Und wenn jetzt der Wechsel von
encin(0) kurz vor, nach oder mit der Flanke vom clk kommt, dann rennt
die Carrychain schon mal los, kommt aber evtl. nicht ganz durch. Und
dein Zähler zählt eben nicht +1 oder -1 sondern irgendeinen Käse.
> Klar, Zähler und Takt müssen natürlich so gewählt sein, dass der Zähler> die Addition durchgeführt hat bevor der nächste Takt kommt
Drehst du dann synchron am Rad?
Nein, das "glaube" ich nicht.
> Und encin(0) geht (über die Carry-Chain) auf alle 8 Flipflops von count0
Nur im Moment der steigenden Flanke von der Clock wird entschieden ob +1
oder -1. Und danach läuft die Addition durch wie zu diesem einen
Zeitpunkt entschieden.
Ja wenn encin(0) kurz vor der steigenden Taktflanke von 0 auf 1 wechselt
und danach wieder auf 0 zurück wird trotzdem +1 gezählt obwohl encin(0)
die meiste Zeit auf 0 liegt und nicht auf 1. Aber die Addition läuft
immer genau so durch wie zum Zeitpunkt der steigenden Flanke entschieden
wurde.
Natürlich sehe ich damit nicht das reale Signal des Encoders, aber ich
taste es sehr oft, also meine Sampleclock ist sehr viel Größere wie die
Änderungsrate des Encoders. Meintest du das? Also dass ich
Wertänderungen zwischen den steigenden Taktflanken (= meine
Samplezeitpunkte) nicht beachte?
Also ich habe mir jetzt mal eine Testbench geschrieben mit einem leicht
verschobenen Takt, also es fällt jetzt das Encodersignal 2ns nach der
Taktflanke von 1 auf 0 und es wird trotzdem richtig die 1 addiert. Es
ist alerdings der Webpack ISim, der das vielleicht nicht korrekt macht
mit den Laufzeiten.
So ich habe jetzt mit noch anderen Zeiten in der Testbench den Fall,
dass der Eingang 0.3ns nach der steigenden Taktflanke von 1 auf 0 fällt
und trotzdem das mit der Addition zumindest laut Simulation richtig ist.
und das Carry muss sogar was machen von 10111 nach 11000.
Gustl Buheitel schrieb:> Nur im Moment der steigenden Flanke von der Clock wird entschieden ob +1> oder -1. Und danach läuft die Addition durch wie zu diesem einen> Zeitpunkt entschieden.
Nein, die Addition für einen synchronen Zähler ist (hoffentlich) vor der
Taktfklanke schon lange fertig berechnet. Und die Flipflops übernehmen
mit dem Takt nur das Ergebnis (den neuen Zählerstand), das aus der Logik
bereitgestellt wird. Und wenn diese Logik jetzt wegen der Änderung des
Eingangssignals noch irgendwie rumzappelt, dann übernehmen die FFs eben
dieses Gezappel.
> 2ns nach der Taktflanke von 1 auf 0> dass der Eingang 0.3ns nach der steigenden Taktflanke
Du musst den Eingang kurz vor der Taktflanke ansteigen lassen. Und
zwar um die Laufzeiten vom Portpin zur Logik früher. Nur so kann sich
das Signal am FF ändern, wenn es nicht sollte, und so die tsu/th
verletzen...
Also der zeitliche Ablauf wie ich das bisher glaubte verstanden zu
haben:
1
waituntilrising_edge(clk);
Es wird auf die steigende Taktflanke gewartet.
1
ifcount0<255andencin(0)='1'then
2
3
elsifcount0>0andencin(0)='0'then
4
5
endif;
Kommt jetzt diese Taktflanke, dann wird "geguckt" welche und ob
überhaupt eine der Bedingungen wahr ist.
Wenn eine wahr ist, dann wird das gemacht was drinnen steht, also 1
addiert oder subtrahiert.
Das muss dann bis zur nächsten steigenden Flanke geschehen sein weil
dort der Wert des Zählers für die Bedingungen abgefragt wird.
Aber anscheinend sehe ich das falsch, was passiert denn da genau? Also
wann wird da das Eingangssignal angeguckt wenn icht genau einmal je Takt
und zwar genau bei der steigenden Flanke?
Also genauer:
Ändert sich der Wert der if Bedingung, das ist ja Bool, auch zu anderen
Zeiten als zur steigenden Flanke? Obwohl ich ja
Gustl Buheitel schrieb:> wait until rising_edge(clk);> Es wird auf die steigende Taktflanke gewartet.> Kommt jetzt diese Taktflanke, dann wird "geguckt" welche und ob> überhaupt eine der Bedingungen wahr ist.
Du hast ein zu "ereignisgesteuertes" Bild der Hardware. Es wird nicht
"gewartet" und es wird auch nichts "nachgeschaut". Sondern es wird ganz
einfach mit der Taktflanke vom clk ein Flipflop angesteuert, vor dem ein
Logiknetz sitzt, das den nächsten Zählerstand ausrechnet. Und dieser
nächste Zählerstand sollte tunlichst vor der Taktflanke stabil sein,
weil sonst dein Logiknetz irgendwie herumglitcht und hinundher zappelt.
> Wert der if Bedingung, das ist ja Bool
Die Bedingung ist ein logisches Gatter, das (vermutlich zusammen mit
anderen Funktionen) in einer LUT realisiert ist, die direkt vor dem FF
D-Eingang sitzt.
> Ändert sich der Wert der if Bedingung, das ist ja Bool, auch zu anderen> Zeiten als zur steigenden Flanke?
Er ändert sich nach jeder Taktflanke (oder besser: er kann sich
ändern) und muss rechtzeitig vor der nächsten Taktflanke stabil sein.
Das nennt sich dann synchrones Design:
Takt-Gezappel-Ruhe-Takt-Gezappel-Ruhe-Takt-Gezappel-Ruhe-Takt-usw.
Und wenn sich encin(0) ändert, dann ändert sich kurz darauf (Laufzeiten
vom Pin zur Logik und durch die Logik hindurch) der Eingang der
betroffenen Flipflops.
Gustl Buheitel schrieb:
>Kommt jetzt diese Taktflanke, dann wird "geguckt" welche und ob>überhaupt eine der Bedingungen wahr ist.
und da liegt vlt. dein Denkfehler: es wird nicht zum Flankenzeitpunkt
geguckt/gesampelt und dann das Ergebnis an alle anderen FFs übermittelt,
sondern COUNT0 und ENCIN werden in einen LUT-Wald eingefüttert. Und
dieser spuckt nach einiger Zeit ein Ergebnis aus (Dauer lässt sich bei
synchronen Signalen vom Fitter etc. genau berechnen).
Aber dein ENCIN ist NICHT synchron.
Und jetzt hast du zwei Fälle:
1. Der Ausdruck "count0 < 255 and encin(0) = '1'" wird in einem
Baum/Wald synthetisiert. Dann muss aber das Ergebnis zu allen
COUNT0-FFs, was aber unterschiedlich lange dauern kann => FSM und
COUNT0-FFs können ins Chaos geraten.
2. Ausdruck wird für jedes COUNT0-FF zu einem LUT-Baum: hier hast
du dann das Problem, dass ENCIN unterschiedlich lange braucht, d.h.
die Ergebnisse werden nicht synchron berechnet => FSM und COUNT0-FFs
stürzen auch hier ins Chaos.
Schau dir einfach mal die Technology-Schematics nach der Synthese
an und mach dir klar, dass alle Signale unterschiedliche Laufzeiten
haben.
Ja die zwei weil encin ja auch 2 Drähte sind, hatte ich nur
rauseditiert.
Vielen Dank übrigens :-) Im meinem alten Weltbild dachte ich irgendwie,
dass da schon ein Speicherelement drinnen wäre automatisch das den Wert
zum Zeitpunkt der steigenden Flanke festhalten und dann erst an die
Kombinatorik weiterreichen würde.
Gustl Buheitel schrieb:> Ja die zwei weil encin ja auch 2 Drähte sind, hatte ich nur> rauseditiert.
Nein, dann wären es 4... ;-)
Oder andersrum: zum Einsynchronisieren verwendest du, wenn deine Latenz
es zulässt am besten 2 Flipflops pro asynchronem Eingang.
> Vielen Dank übrigens :-)
Kein Ursache...
So, hatte mir Lothars Beispiel angeschaut und danach selbst versucht auf
die Zustände etc zu kommen, hat auch funktioniert. Allerdings habe ich
das doch ein wenig anders:
1
architecturebehaveofrotary_encoderis
2
3
typepositionsis(P00,P01,P10,P11);
4
signalp:positions:=P00;
5
signalrot_ab:std_logic_vector(1downto0);
6
7
begin
8
9
turning:process(clk,rotary_a,rotary_b)
10
begin
11
waituntillrising_edge(clk);
12
13
rot_ab<=rotary_a&rotary_b;
14
15
casepis
16
whenP00=>if(rot_ab="10")then
17
p<=P10;
18
rotary_use<='1';
19
left_to_right<='1';-- links_nach_rechts
20
elsif(rot_ab="01")then
21
p<=P01;
22
rotary_use<='1';
23
left_to_right<='0';-- rechts_nach_links
24
endif;
... usw.
1. Ich habe in der Sensitivitätsliste rotary_a und rotary_b noch drin.
Brauche ich das, oder benutzen wir die Änderungen der beiden Signale eh
erst, wenn wir einen neuen Taktzyklus haben? Und da der Prozess, der
dann rotary_use usw benutzt, auch erst mit dem neuen Taktzyklus
angesprochen wird, reicht ein clk in der Sensitivitätsliste? Aber warum
gibt es dann Fälle, wo das clk nicht ausreicht?
2. Lothar du hast bei dir noch den Prozess:
1
processbegin-- Eintakten der asynchronen Signale
2
waituntilrising_edge(clk);
3
i<=A&B;-- Zusammenfassen der Eingänge A und B
4
e<=i;
5
endprocess;
Kannst du bitte nochmal erklären, warum das nötig ist und was passieren
würde, wenn man das wie in meinem Code weglässt und direkt A und B
benutzt?
Danke!
Mein Gott, die klassische Lösung mit Dekodertabelle und 4 FlipFlops kann
man nicht vereinfachen oder verbessern, nur verschlimmbessern. Und es
geht auch nicht rein kombinatorisch. Das Ganze System ist die asynchrone
Abtastung eines Gray-Codes, die funktioniert nun mal so.
Falk Brunner schrieb:> Mein Gott, die klassische Lösung mit Dekodertabelle und 4 FlipFlops kann> man nicht vereinfachen oder verbessern, nur verschlimmbessern. Und es> geht auch nicht rein kombinatorisch. Das Ganze System ist die asynchrone> Abtastung eines Gray-Codes, die funktioniert nun mal so.
:o)
mehr muss man dazu auch nicht sagen...
berndl schrieb:> Falk Brunner schrieb:>> Mein Gott, die klassische Lösung mit Dekodertabelle und 4 FlipFlops kann>> man nicht vereinfachen oder verbessern, nur verschlimmbessern. Und es>> geht auch nicht rein kombinatorisch. Das Ganze System ist die asynchrone>> Abtastung eines Gray-Codes, die funktioniert nun mal so.>> :o)>> mehr muss man dazu auch nicht sagen...
Haha ja kann ich verstehen, dass sowas für Kenner der Materie in den
Augen schmerzt, aber wenn man dabei ist soetwas zu lernen, kommen nunmal
seltsame Ideen und Fragen auf :D
Mit dem Takt würde mich jetzt auch interessieren. Wenn man jetzt einen
Prozess ohne Takt macht aber sonst alle anderen Prozesse mit Takt, dann
dürfte es doch keine Synchronisationsschwierigkeiten geben oder? Also
jedenfalls, wenn das Ergebnis des Prozesses ohne Takt von einem Prozess
mit Takt benutzt wird. Oder doch?
@Felix O. (felixanius)
>Augen schmerzt, aber wenn man dabei ist soetwas zu lernen, kommen nunmal>seltsame Ideen und Fragen auf :D
Ja, was meist an mangelnden Grundlagen liegt.
>Mit dem Takt würde mich jetzt auch interessieren. Wenn man jetzt einen>Prozess ohne Takt macht aber sonst alle anderen Prozesse mit Takt, dann>dürfte es doch keine Synchronisationsschwierigkeiten geben oder?
Oder.
> Also>jedenfalls, wenn das Ergebnis des Prozesses ohne Takt von einem Prozess>mit Takt benutzt wird. Oder doch?
Oder doch.
Siehe oben. Du musst dich mal mit den Grundlagen der Digitaltechnik
befassen. Was macht kombinatorische Logik? Was machen Speicherelemente?
Wie muss das Timing sein? Und in den höheren Semestern lernt man dann
was über asynchrone Taktdomänen und deren Probleme sowie Lösungen.
Falk Brunner schrieb:> @Felix O. (felixanius)>>>Augen schmerzt, aber wenn man dabei ist soetwas zu lernen, kommen nunmal>>seltsame Ideen und Fragen auf :D>> Ja, was meist an mangelnden Grundlagen liegt.
Hm aber irgendwo muss man anfangen die Grundlagen zu lernen. Das man
alles was man in Büchern liest sofort komplett versteht halte ich für
unwahrscheinlich und da finde ich ist es viel effektiver, man setzt sich
praktisch mit dem Thema auseinander und merkt dann, wo noch Lücken sind
bzw. was man noch nicht ganz verstanden hat. Ich sehe das Forum hier als
Hilfe um die Grundlagen zu verstehen/festigen. Die Fragen richten sich
an User, die viel Ahnung in dem Gebiet haben und vielleicht auch wissen,
wo die Verständnisprobleme von Anfängern liegen. Und die vorallem Lust
darauf haben die Fragen zu beantworten und zu helfen. Wer nicht
antworten will, antwortet halt nicht, hatte nur hier den Eindruck, dass
es sehr viele hilfsbereite User gibt, deswegen all die Fragen.
Ich möchte später nicht als VHDL-Programmierer arbeiten, ich habe nur
zur Zeit Interesse an der Sprache und an FPGAs bekommen. Dazu bearbeite
ich gerade ein Projekt, welches eine Spielerei mit LEDs ist (Grundlagen
;))
Ich bin mir ziemlich sicher, dass mir hier einer die Frage oben in drei
Sätzen beantworten könnte und ich dann zumindest auf das Beispiel
bezogen die Nutzung vom Takt besser verstehen würde.
Ich verstehe, dass es für jemanden, der sich mit VHDL schon Jahre
beschäftigt, schwer nachzuvollziehen ist, warum ein Anfänger dieses und
jenes noch nicht weiß. Aber dieses "Ist doch ganz logisch" ist nunmal
nicht von Anfang an da.
Der Hinweis, ich solle erstmal Grundlagen lernen, hilft mir nicht
weiter.
Ich hoffe trotzdem weiterhin auf Hilfe von den ganzen "Pros" hier :)
Felix O. schrieb:> turning:process (clk, rotary_a, rotary_b)> begin> wait untill rising_edge(clk);
Ein WAIT zusammen mit einer Sensitivliste geht nicht...
>> rot_ab <= rotary_a & rotary_b;
Aus Versehen Glück gehabt: wenigstens 1 Flipflops zum
Einsynchronisieren...
> 1. Ich habe in der Sensitivitätsliste rotary_a und rotary_b noch drin.
Unnötig.
> Brauche ich das, oder benutzen wir die Änderungen der beiden Signale eh> erst, wenn wir einen neuen Taktzyklus haben? Und da der Prozess, der> dann rotary_use usw benutzt, auch erst mit dem neuen Taktzyklus> angesprochen wird, reicht ein clk in der Sensitivitätsliste? Aber warum> gibt es dann Fälle, wo das clk nicht ausreicht?
Die Sensitivliste verwendet nur der Simulator. Mit der Liste sagst du
ihm, wann ein Prozess neu berechnet werden muss.
Ein synchroner Prozess muss nur mit dem Takt neu berechnet werden. Ein
kombinatorischer Prozess braucht da alle Signale, die eine Auswirkung
auf andere Signale haben.
Die Synthese erweitert eine unvollständige Sensitivliste von allein und
gibt dir bestenfalls eine Info, dass das Syntheseergebnis nicht zur
Simulation passt... :-o
> 2. Lothar du hast bei dir noch den Prozess:> -- Eintakten der asynchronen Signale>> Kannst du bitte nochmal erklären, warum das nötig ist und was passieren> würde, wenn man das wie in meinem Code weglässt und direkt A und B> benutzt?
Da passiert dann genau das, was ich in diesem Thread bis zum Umfallen
erklärt habe: du hast eine FSM mit asynchronen Eingängen. Sieh dir
einfach meine HP zum Thema Eintakten, Metastabilität, usw an.
> Danke!
Bitte!
Gustl Buheitel schrieb:> Mal ne komische Idee, aber kann man das nicht sogar ganz ohne Takt> machen?
Naja, du hast da sogar 2 Takte drin:
> wait until falling_edge(encin(0));> wait until falling_edge(encin(1));
Und dann kommt die Geschichte mit dem Einsynchronisieren eben gleich
danach, wenn die Ergebnisse (r und l) dieses Prozesses im restlichen
Design weiterverarbeitet werden sollen.
Am Rande:
deine Lösung hat einen fetten Haken: es können beide Signale
gleichzeitig aktiv sein...
@ Felix O. (felixanius)
>Hm aber irgendwo muss man anfangen die Grundlagen zu lernen.
Sicher, aber nicht dirch maiximal wildes Drauflosrennen mit ein
Bruchteil eines Bruchteils von Wissen.
> Das man>alles was man in Büchern liest sofort komplett versteht halte ich für>unwahrscheinlich
Logisch, aber . . .
>und da finde ich ist es viel effektiver, man setzt sich>praktisch mit dem Thema auseinander und merkt dann, wo noch Lücken sind>bzw. was man noch nicht ganz verstanden hat.
Jain. Wie überall muss man erstmal das kleine 1x1 lernen. Und das tut
man am besten, indem man es im Lehrbuch liest, durchdenkt und genau so
nach macht. Auf Digitalechnik bezogen heißt das, was sind Logikgatter,
was ist ein FlipFlop, Wie funktionieren sequentielle und kombinatorische
Schaltungen. Das alles muss man erstmal durchkauen, mit kleinen Übungen,
die aber noch recht eingeschränkt sind. Bei VHDL ist es ähnlich.
Kombinatorische und sequentielle Prozesse, sinnvolle, synthetisierbare
Beschreibungen von Standard funktionaliät, State machine.
Was du machst ist, mit deinem Funken Halbwissen alles neu erfinden
wollen. Aber das geht schief. Zuerst musst du mal alles so nachmachen
und versthen, wie es im Buch steht. DANACH kannst du kreativ werden.
>darauf haben die Fragen zu beantworten und zu helfen. Wer nicht>antworten will, antwortet halt nicht, hatte nur hier den Eindruck, dass>es sehr viele hilfsbereite User gibt, deswegen all die Fragen.
Klar, aber machmal ist einfach der Hinweis notwenig, dass wir hier nicht
in der Grundschule sind, wo alles haarklein immer wieder vorgekaut wird.
Es ist Eigeninitiative vonnöten.
>Ich möchte später nicht als VHDL-Programmierer arbeiten, ich habe nur>zur Zeit Interesse an der Sprache und an FPGAs bekommen. Dazu bearbeite>ich gerade ein Projekt, welches eine Spielerei mit LEDs ist (Grundlagen>;))
Naja, die echten Grundlagen wären sinnvoller. Z.B. mal ein VHDL-Tutorial
durcharbeiten, davon gibt es einige.
>Ich verstehe, dass es für jemanden, der sich mit VHDL schon Jahre>beschäftigt, schwer nachzuvollziehen ist, warum ein Anfänger dieses und>jenes noch nicht weiß.
Jain.
> Aber dieses "Ist doch ganz logisch" ist nunmal>nicht von Anfang an da.
Sicher.
>Der Hinweis, ich solle erstmal Grundlagen lernen, hilft mir nicht>weiter.
Vielleicht doch. Zuerst musst du bestehende, vollständige Beispiele
nachvollziehen und mehr oder weniger 1:1 nachbauen.