Hallo!
Ich habe bisher alle Counteraufgaben entweder direkt mittels
Mikrocontrollern (in AVR-C) oder mit Hilfe von Logik-ICs realisiert. Da
im aktuellen Fall (Zählfrequenz > 50 MHz, 16-Bit Zählerbreite) jedoch
das Auslesen aufgrund von Glitches und Signallaufzeiten der kaskadierten
ICs zunehmend problematischer wurde, wollte ich folgenden Zähler gerne
mittels Xilinx XC9572XC CPLD realisieren.
- 16-Bit Auflösung/Breite, nur Aufwärtszählen nötig
- Impulse (Pulse-Eingang) treten unvorhersehbar und zufälllig, aber mit
einer maximalen Frequenz < 90 MHz auf
- Zählerüberlauf ist nicht relevant (Zählzeiten sind kurz genug, als
dass diese auftreten könnten)
Außerdem:
- Zähler soll über externes Signal (Gate-Eingang) "scharfgestellt"
werden können und möglichst zeitnah nach dem ersten tatsächlich
gezählten Impuls dies an einem Ausgang anzeigen (Active-Ausgang)
- Zählerstand soll parallel auslesbar sein, soll/braucht jeweils nur
nach Aufforderung (Clk-Takt) aktualisiert werden
- Zähler soll nach Ende des Zählvorgangs zurückgesetzt werden (momentan
einfach immer, wenn Gate-Eingang low ist)
Dies hier sind mein erstes CPLD-Projekt und meine ersten Schritte in
VHDL, herausgekommen ist bisher folgendes:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.STD_LOGIC_ARITH.ALL;
4
useIEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entityCounter16is
7
port(Clk,Pulse,Gate:instd_logic;
8
Active:outstd_logic;
9
Data:outstd_logic_vector(15downto0)
10
);
11
endCounter16;
12
13
ArchitecturebehaviourofCounter16is
14
signalQ:std_logic_vector(15downto0);
15
16
begin
17
18
process(Gate,Pulse)
19
begin
20
if(Gate='0')then
21
Q<=(others=>'0');
22
Active<='0';
23
elsif(rising_edge(Pulse))then
24
Active<='1';
25
Q<=Q+1;
26
endif;
27
endprocess;
28
29
process(Clk)
30
begin
31
ifrising_edge(Clk)then
32
Data<=Q;
33
endif;
34
endprocess;
35
36
endbehaviour;
Das Ganze funktioniert erstaunlicherweise schon einmal relativ gut, bis
auf ein kleines Detail: In mehr oder weniger regelmäßigen Abständen
erhalte ich nach einem Aktualisieren des Zählerstands an den Ausgangen
mittels Clk-Takt einen Wert der 64/128/256 zu hoch ist, der
darauffolgende Wert stimmt wieder.
Meine Vermutung ist, dies tritt immer dann auf, wenn zeitgleich ein
Pulse-Takt den Zähler hochsetzt und ein Clk-Takt die Ausgabe
aktualisiert. Vielleicht sind aber auch die Laufzeiten der FF im CPLD im
Allgemeinen daran Schuld, oder ein Problem, dass ich noch gar nicht
erkannt habe.
Ich wäre dankbar über jede Art von Tipp oder Anregung, wie ich diesen
Zähler optimieren kann. Eventuell kann das eine oder andere auch besser
völlig anders gelöst werden, als ich es bisher versucht habe.
Vielen Dank und viele Grüße
Ingo
Du bist mit deiner Vermutung schon auf der richtigen Spur.
Du hast zum einen das Zählregister Q beschrieben, welches mit "pulse"
getaktet wird und zum anderen ein Ausgangsregister, welches mit "Clk"
getaktet wird.
Da "Pulse" und "Clk" aber keinen starren phasenbezug zueinander haben,
kann es vorkommen, dass in dem Moment die Daten von Q aktualisiert
werden, während du die Daten in "Data" übernimmst.
Lösungsmöglichkeiten:
Entweder lässt du das "Data"-Register ganz weg
Oder du taktest das Ausgangsregister "Data" auch mit "Pulse"
Oder du synchronisierst "Pulse" mit dem Takt "Clk" ein und taktest das
Zählregister mit "clk" und enablest den Zähler immer nur dann, wenn eine
steigende Flanke auf "Pulse" kam...
Ingo S. schrieb:> Vielleicht sind aber auch die Laufzeiten der FF im CPLD im> Allgemeinen daran Schuld,
Ja, richtig, das ist die Ursache...
> oder ein Problem, dass ich noch gar nicht erkannt habe.
Du musst asynchrone Signale einsynchronisieren. Das, was du da gerade
beobachtest, findest du (in etwa) hier beschrieben:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Denn dein Pulssähler ist ein Zustandsautomat, und dein asynchroner
Übernahme"takt" hat unterschiedlich lange Laufzeiten zu den
Übernahme-Flipflops...
Vielen Dank für die schnellen Antworten!
Ich versuche einmal der Reihe nach darauf einzugehen, bevor ich anfange,
wild herumzuprobieren und die nächsten, ähnlichen Anfängerfehler
einbaue...
Schlumpf schrieb:
>Entweder lässt du das "Data"-Register ganz weg
Kurz zur Erklärung, warum ich das Data-Register eingeführt habe: Ich
lese dieses Register an den Ausgangspins mit einem 8-Bit Atmega2560 und
16MHz Systemtakt aus. Ein 16-Bit Register auszulesen dauert also selbst
im Idealfall zwei Taktzyklen, sprich 133ns. Bei einer Impulsfrequenz <=
90 MHz kann sich der Zählerstand bereits mehrmals geändert haben, also
wollte ich gerne eine "Standbildaufnahme" des momentanen Zählerstandes,
den ich in Ruhe mit dem Atmega auslesen kann.
>Oder du taktest das Ausgangsregister "Data" auch mit "Pulse"
Wenn ich das richtig sehe, hätte ich damit das oben beschriebene Problem
nicht gelöst, weil sich dann "Data" innerhalb von 133ns mehrmals ändern
könnte, oder?
>Oder du synchronisierst "Pulse" mit dem Takt "Clk" ein und taktest das>Zählregister mit "clk" und enablest den Zähler immer nur dann, wenn eine >steigende Flanke auf "Pulse" kam...
Dafür brauche ich einen Clk-Takt, der deutlich schneller ist, als mein
Pulse-Takt es in der Praxis werden kann, oder? Es sieht mir langsam
danach aus, als wäre mein Vorhaben unmöglich, dabei klingt es nach einer
so simplen Aufgabe...
Lothar Miller schrieb:
>Denn dein Pulssähler ist ein Zustandsautomat, und dein asynchroner>Übernahme"takt" hat unterschiedlich lange Laufzeiten zu den>Übernahme-Flipflops...
Die ersten 8 Bit des Registers werden frühestens 62,5ns (16 MHz
Systemtakt des uC) nach Erzeugen des "Clk"-Taktes ausgelesen, sind die
Laufzeiten der CPLD-FlipFlops insgesamt noch langsamer? Hier könnte ich
ja tatsächlich noch einfach eine Wartezeit einbauen.
Ist es eventuell möglich, dieses Problem mit einem zusätzlichen
Zwischenschritt zu lösen? Ich dachte spontan an:
-Pulse lässt Zähler hochzählen
-Clk fordert Zählerstand an
-Im Fall eines angeforderten Zählerstandes wird Data mit dem nächsten
Pulse einmalig aktualisiert
-Per Ausgabe-Pin wird die erfolgreiche Aktualisierung angezeigt
-Anschließend kann Data ausgelesen werden
-und "Anforderung" und "erfolreiche Aktualisierung" werden
zurückgesetzt?
Das Hauptproblem lässt sich vermutlich so zusammenfassen:
Verzhältnismäßig schnelle Zählimpulse sollen in einem sehr präzisen,
aber im Vergleich zu den Zählimpulsen langsamen Zeitraster ausgelesen
werden. So dass man beispielsweise mit 1kHz Clk-Frequenz irgendwann
innerhalb des 1ms-Fensters die Gelegenheit hat, den genauen Zählerstand
zur Zeit der 1kHz Clk-Flanke abzufragen.
Vielleicht ist das ganze auch ganz einfach, und ich habe nur noch nicht
ganz durchblickt, wie genau ich ein entsprechendes "Einsynchronisieren"
bewerkstelligen kann?
Das hinter der gegebenen URL erwähnte Problem des Asynchronen Resets in
meinem Code habe ich übrigens bemerkt, ist aber glaube ich zum Glück in
diesem Fall nicht besonders schlimm. Ich kann in meinem Fall sicher
sein, dass sowohl zum Zeitpunkt, wenn Gate HIGH gesetzt wird, als auch
beim LOW Zeitpunkt, keine Pulse-Takte auftauchen. Deshalb überhaupt erst
ein "Active"-Signal, um den tatsächlichen Beginn eines hereinhagelnden
Impulshaufens zu erfassen.
Vielen Dank für eure Mühen,
Ingo!
Wenn du systembedingt davon ausgehen musst, dass sich dein Zählerwert
ändert, während du ausliest, dann hilft es dir auch nichts, einfach den
Zählerwert in ein langsameres Register zwischenzuspeichern.. denn auch
dieses kann sich ja genau in dem Moment ändern, in dem du ausliest.
Du müsstest also eine Art Steuersignal einführen, mit dem du während des
Auselesevorgangs das Leseregister "einfrierst".
Das könnte z.B. das RD-Signal des Busses sein..
Ingo S. schrieb:> Es sieht mir langsam> danach aus, als wäre mein Vorhaben unmöglich,
Nein, das ist es nicht.. man muss nur ein paar Sachen beachten, dann
geht das..
Idealerweise arbeiten alle Register mit einem identischen Takt.
Diesen Takt wählst du so schnell, dass du damit das Eingangssignal
abtasten kannst.
Die Abtastung erfolgt durch mindestens 2 hintereinandergeschaltete
Register. Anhand des Zustandes der Register kannst du erkennen, ob das
"Pulse"-Signal gerade eine steigende Flanke durchläuft.
Wenn das der Fall ist, dann enablest du den Counter für einen internen
Systemtakt lang.
Das "Daten" Register übernimmt mit jedem Systemtakt den Wert vom
Counter. Tut dies aber nicht, wenn das externe Signal die Aktualisierung
"verbietet", während du das Register liest.
Achtung: Dieses Steuersignal muss auch synchronisiert werden!
Ingo S. schrieb:> -Im Fall eines angeforderten Zählerstandes wird Data mit dem nächsten> Pulse einmalig aktualisiert
Das ist der richtige Schritt...
> So dass man beispielsweise mit 1kHz Clk-Frequenz irgendwann> innerhalb des 1ms-Fensters die Gelegenheit hat, den genauen Zählerstand> zur Zeit der 1kHz Clk-Flanke abzufragen.
Du musst unbedingt die Namensgebung überarbeiten. Ein Takt ist idR.
etwas (relativ) dauerhaft anliegendes Schnelles. Dein Puls ist
eigentlich der Zähltakt.
Dein Takt ist nur ein Latch-Signal, das anzeigt, dass der aktuelle
Zählerstand irgendwohin übernommen werden soll.
> Das hinter der gegebenen URL erwähnte Problem des Asynchronen Resets in> meinem Code habe ich übrigens bemerkt, ist aber glaube ich zum Glück in> diesem Fall nicht besonders schlimm.
Die Absicht war nicht, den Reset anzuprangern, sondern zu zeigen, dass
du zwei asynchrone Signale hast, die aufeinander synchronisiert werden
müssen...
> wie genau ich ein entsprechendes "Einsynchronisieren"> bewerkstelligen kann?
Wie "zufällig" kommt der Zähltakt? Denn der Zähler läuft in seiner
eigenen Taktdomäne und nur diese Taktdomäne kennt einen "ungefährlichen"
Zeitpunkt zur Datan übernahme in das Schattenregister...
Lothar Miller schrieb:
>Das ist der richtige Schritt...
Ich bin dabei, es zu versuchen. Aber es scheint schwieriger, als
angenommen. Bisher ist nichts dabei herausgekommen, dass synthetisiert
werden konnte. Fehler wegen Multi-Source, wegen schreibendem/lesenden
Zugriff zugleich, Fehler in der Sensitivitätsliste, ...
>Du musst unbedingt die Namensgebung überarbeiten. [...]>Dein Takt ist nur ein Latch-Signal, das anzeigt, dass der>aktuelle Zählerstand irgendwohin übernommen werden soll.
Du hast völlig Recht, die Namen sind eher Relikt aus meinen ersten
VHDL-Tutorials. Latch beschreibt besser, was Clk hier tut!
>Die Absicht war nicht, den Reset anzuprangern, sondern zu zeigen, dass>du zwei asynchrone Signale hast, die aufeinander synchronisiert werden>müssen..
Genau das habe ich natürlich auch gesehen und so verstanden.
Informationen in Hülle und Fülle, ich bin schon dabei, mich hier schlau
zu lesen. Wollte hier lediglich einer Asynchroner-Reset-Diskussion
vorausgreifen, dessen Problematik bin ich mir bewusst.
>Wie "zufällig" kommt der Zähltakt? Denn der Zähler läuft in seiner>eigenen Taktdomäne und nur diese Taktdomäne kennt einen "ungefährlichen">Zeitpunkt zur Datan übernahme in das Schattenregister...
Eventuell kommt er sogar nie, es ist gar nicht garantiert, dass
innerhalb der Gate-Zeit Impulse auftreten. Eventuell aber auch welche
mit bis zu 90 MHz. Eine Art Geiger-Müller-Zählrohr beschreibt den
Anwendungszweck ganz gut.
Schlumpf schrieb:
>Idealerweise arbeiten alle Register mit einem identischen Takt.>Diesen Takt wählst du so schnell, dass du damit das Eingangssignal>abtasten kannst.
Dazu wäre eine Taktquelle nötig, die etwa dem dreifachen des maximalen
Eingangssignals entspricht, oder? Das ist ja kaum aufzutreiben :(
Vielleicht sollte ich doch einen Logik-IC wie den ACT161 oder Ähnlich
davor setzen, um die Frequenz schon mal auf 1/16 zu teilen, und mit
einem mäßig schnellen Clock-Signal den ACT161-Überlauf abtasten.
Mittlerweile liegt auch der Kompaktkurs VHDL auf dem Tisch, vielleicht
schaffe ich ja mit Hilfe von diesem Forum, Web-Tutorials und
Papierlektüre, dem Problem doch noch Herr zu werden.
Viele Grüße
Ingo
Ingo S. schrieb:> Dazu wäre eine Taktquelle nötig, die etwa dem dreifachen des maximalen> Eingangssignals entspricht, oder? Das ist ja kaum aufzutreiben :(
Wollte grad PLL schreiben, aber du hast ja nen CPLD und keinen FPGA..
--> Blöde Sache :-(
Wenn du keinen schnellen Systemtakt bereitstellen kannst, dann wird die
Sache wirklich sehr knifflig.
Ein einfaches Data-Latch (oder Register) hilft nicht weiter, da der
Zeitpunkt der Übernahme unbekannt ist und daher die Möglichkeit besteht,
dass du genau zu dem Zeitpunkt übernimmst, wenn sich gerade der Zähler
ändert. Aufgrund der unterschiedlichen Laufzeiten der einzelnen Bits vom
Zähler zum Latch und der eventuell auftretenden Setup-Zeit-Verletzungen
kann dann "irgendwas" im Latch stehen.
Eventuell kannst du drüber nachdenken, ob du dieses Register mit dem
Zähltakt selbst taktest. Dann steht halt im Register nicht der aktuelle
Wert des Zählers, sondern der vorangegangene Wert.
Aber Zähler und Schattenregister wären dann zumindest in der gleichen
Domain.
Dann bleibt aber noch das Problem, ein Aktualisieren des
Schattenregisters zu unterbinden, während du ausliest.
Das könnte mit einem Steuersignal geschehen, welches ebenfalls mit dem
Zähltakt synchronisiert wird.
Dann müsstest du dir allerdings das Timing des Zugriffs genau anschauen,
ob sichergestellt ist, dass das Timing zwischen Steuersignal, Zähler und
Schattenregister zusammenspielt..
Alles in Allem wird das ein ziemlicher Murks. Aber mir fällt grad auf
die Schnelle auch nichts Schlaues ein
Nachtrag:
Wenn die Zählimpulse zufällig auftreten, dann wird das von mir
beschriebene Verfahren auch kaum umsetzbar sein..
Aber vielleicht lässt sich was machen, indem man auf beiden Flanken des
Zählsignals arbeitet..
Schlumpf schrieb:> Wollte grad PLL schreiben, aber du hast ja nen CPLD und keinen FPGA..> --> Blöde Sache :-(
Nö.
Im Gegensatz zu FPGA's haben CPLD's richtig große AND-Gates am Eingang
der Macrozelle - anstelle der popligen LUT. Das prädestiniert sie
geradezu für große schnelle Synchronzähler. Man muß es bloß richtig
machen.
Mit Schematics ;-) würde ich als erste Stelle einen FDE (Flipflop mit
Clock, Dateneingang und Enable, ist bei den '95ern intrinsic) nehmen,
womit das Zähl-Enable des gesamten eigentlichen Zählers bereits erledigt
ist.
Die nachfolgenden Stellen kriegen die UND-Verknüpfung aller vorherigen
Stellen als Enable. Damit haben wir einen synchronen Zähler mit Enable,
der in jedem Falle nur 1 Gatterlaufzeit braucht.
Zum Auslesen kommt an jeden FF-Ausgang des Zählers ein weiterer FDE. Die
Enables dieser FDE's gehen allesamt an das Auslesesignal vom
angeschlossenen uC und getaktet werden sie ebenfalls mit der
Eingangsfrequenz. Damit ist sichergestellt, daß dieses Auffangregister
synchron zum Zählerstand-1 läuft, solange es nicht ausgelesen wird.
Während des Auslesens ändert es sich hingegen nicht (wegen Enable jetzt
auf 'passiv').
So, nun schreibt das mal mit VHDL hin.
W.S.
@ W.S.
Schlumpf schrieb:> Eventuell kannst du drüber nachdenken, ob du dieses Register [anm.> Data-Tegister] mit dem > Zähltakt selbst taktest. Dann steht halt im> Register nicht der aktuelle Wert des Zählers, sondern der vorangegangene> Wert.> Aber Zähler und Schattenregister wären dann zumindest in der gleichen> Domain.
Wo ist da jetzt der Unterschied?
Vielen Dank für alle eure Antworten. Ich bin mittlerweile etwas weiter
gekommen und wollte dies auch mitteilen:
Um nicht weiterhin im Dunkeln zu forschen, habe ich die Zählerwerte, die
bei Anlegen von 1-40 MHz Rechtecksignalen erfasst werden, genauer
analyisiert und zwei unterschiedliche Arten festgestellt.
Den Bärenanteil schienen zufällig auftretende, relativ
frequenzunabhängige Fehler auszumachen. Ich habe daraus geschlossen,
dass dies eigentlich nichts mit Asynchronität und FF-Laufzeiten zu tun
haben kann, sondern eventuell eher mit einem schlechten Aufbau (momentan
noch Seeedstudio Breakoutboard auf Steckbrett). Tatsächlich war die
Lösung, die Pins des Ausgaberegisters nicht alle direkt nebeneinander,
sondern mit Abstand und mit Pull-Down-Rs auszustatten und möglichst
kurze Leitungen zum AVR einzusetzen. Ich war so beschäftigt mit der
CPLD-Thematik, dass ich an Leitungsreflexionen und Fehler durch
miserable Breadboards gar nicht mehr gedacht habe...
Bei Frequenzen größer 5MHz sind zunehmend häufiger auch die die bereits
beschriebenen "Spikes" zu sehen, die wohl aus dem asynchronen Auslesen
herrühren. Hier sieht meine Lösung etwas anders aus: Ich habe die
langasme Latch-Frequenz (das "Clk"-Signal) von 1kHz auf die mit dem AVR
maximal realisierbare Geschwindigkeit erhöht, um möglichst kleine
Differenzen zwischen vorigem und aktuellem Zählerstand zu erreichen
(90MHz -> nicht mehr als 90 Impulse pro Mikrosekunde). Fehler von +128,
+256, ... können also mittels Software anschließend relativ gut erkannt
und korrigiert werden.
Ich habe außerdem die Einführung eines zweiten Counters (busy) für die
Zeit während des Auslesens versucht:
1
[...]
2
signalQ:std_logic_vector(15downto0);
3
signalbusy:std_logic_vector(3downto0);
4
[...]
5
process(Gate,Pulse)
6
begin
7
if(Gate='0')then
8
Q<=(others=>'0');
9
Active<='0';
10
elsif(rising_edge(Pulse))then
11
if(Clk='1')then
12
busy<=busy+1;
13
else
14
Active<='1';
15
Q<=Q+busy+1;
16
busy<=(others=>'0');
17
endif;
18
endif;
19
endprocess;
20
[...]
Dieses zusätzliche "busy"-Register hat aber weder einen positiven noch
einen negativen Effekt gehabt, außer dass damit der XC9572 nahezu
vollständig belegt ist. Vielleicht ist auch ein Denkfehler meinerseits
drin, dass es gar nicht helfen kann.
Alles in Allem treten nach Optimierung des Aufbaus und Erhöhung der
Latch-Frequenz die beschriebenen Fehler vielleicht noch jedes 1000. bis
5000. Mal auf. Mit diesem Fehler kann ich problemlos leben, das ganze
läuft deutlich besser als mit dem vorigen Versuch, alles mit ACT161s zu
realisieren.
Die Gray-Code Variante scheint mir sehr interessant, allerdings kann ich
mit der nun gewählten AVR Latch-Frequenz den Gray-Code nicht mehr
schnell genug umwandeln. Das ist aber eventuell auch nicht unbedingt an
dieser Stelle nötig, ich werde den Gray-Counter im Hinterkopf behalten
und eventuell eine Übertragung von Gray-Code und spätere Umwandlung
ausprobieren. Vielen Dank auf jeden Fall für das Gray-Code VHDL Snippet.
Abschließend noch eine Frage: Die Schematics-Variante klingt sehr
interessant, sind damit (bei entsprechendem Wissen) prinzipbedingt noch
bessere Realisierungen möglich als durch Beschreibung mittels Sprachen
wie VHDL?
Viele Grüße
Ingo
Ingo S. schrieb:> sind damit (bei entsprechendem Wissen) prinzipbedingt noch> bessere Realisierungen möglich als durch Beschreibung mittels Sprachen> wie VHDL?
Tja, dazu ein ganz dickes JEIN.
Die VHDL-Fraktion hier wird natürlich antworten, daß man ja bei
hinreichend intimer Kenntnis von VHDL alles viel besser machen könnte,
aber wenn ich deine letzten Beiträge lese, dann hab ich da leise
Bedenken.
Immerhin gilt eines: Mit Schematics kann man prinzipiell sehr exakt
arbeiten und dem Entwurfssystem sehr pingelig sagen, was man von ihm
haben will - auch dann, wenn man nicht jeden Tag 8 Stunden VHDL übt.
Mit VHDL ist das ein bissel schwieriger. Ich kann mich noch an damalige
Versuche meinerseits erinnern, wo die ISE mir für einen 16 Bit
Ausgangstreiber mit Tristate partout 32 Macrozellen verbraten wollte (in
VHDL). Das Ganze mit Schematics und außer den eigentlichen
Ausgangstreibern hat es gar keine Macrozelle gekostet. Klar: ich hätte
es ja gaaaaaanz anders formulieren können und dann, ja dann.. Also: Mit
HW-Beschreibungssprachen kriegt man häufig genug nicht das, was man
eigentlich haben wollte, entweder aus Mangel an Übung oder
prinzipbedingt.
In dem Sinne frohes Basteln. Aber was du da mit ""Spikes" zu sehen, die
wohl aus dem asynchronen Auslesen herrühren.." treibst, ist m.E. Pfusch,
der aus schierer Unüberlegtheit des Entwurfes herrührt. Lies dir meinen
ernst gemeinten Vorschlag weiter oben mal durch, ich meine, damit
arbeitet man schlichtweg störungsfrei.
W.S.
W.S. schrieb:> Ich kann mich noch an damalige Versuche meinerseits erinnern,> wo die ISE mir für einen 16 Bit Ausgangstreiber mit Tristate partout> 32 Macrozellen verbraten wollte (in VHDL).
Was hast du denn da falsch gemacht?
Ingo S. schrieb:> Abschließend noch eine Frage: Die Schematics-Variante klingt sehr> interessant, sind damit (bei entsprechendem Wissen) prinzipbedingt noch> bessere Realisierungen möglich als durch Beschreibung mittels Sprachen> wie VHDL?
Dir muss eines klar sein: du malst da auch nur ein paar Bildchen hin,
die erst mal nichts mit der tatsächlichen Struktur des
programmierbaren Bausteins zu tun haben. Auch die müssen übersetzt
werden (und liegen ihrerseits im Hintergrund oft auch "nur" als HDL
Beschreibung da). Denn wenn du in deinem Schaltplan ein UND-Gatter
malst, dann wird trotzdem kein UND-Gatter eingebaut, sondern die
Makrozelle so konfiguriert, dass sie sich wie ein UND verhält...
> sind damit (bei entsprechendem Wissen) prinzipbedingt noch> bessere Realisierungen möglich als durch Beschreibung mittels Sprachen> wie VHDL?
Nich mit sinnvollem Aufwand. Und die Darstellung wird auch unerträglich.
Hier der Klassiker im Beitrag "kruder Fehler bei FPGA-Programmierung (ISE WEBpack-Schematic)"
(Es lohnt sich, diesen Beitrag ganz durchzulesen, bevor man mit
Schematics anfängt)
Lothar Miller schrieb:> Was hast du denn da falsch gemacht?
Ähem.. na eben VHDL benutzt. Mal im Ernst, es ist fast 15 Jahre her und
ich hab damals die Sache mit Schematics final erledigt, ohne mich noch
länger mit der VHDL-Quelle zu befassen.
Lothar Miller schrieb:> die erst mal nichts mit der tatsächlichen Struktur des> programmierbaren Bausteins zu tun haben.
Erstens ist das zumeist falsch, weil ne ganze Menge der einfachen
Gatter eben intrinsics sind, also die direkte Struktur des Bausteins
darstellen. Konkret: sich durch die direkte Funktionalität einer
Makrozelle machen lassen. Das ist was anderes, als wenn man eine
Funktion in einer HDL beschreiben will, bei der dann die ISE (wir
bleiben mal bei Xilinx) erst schauen muß, durch welche Kombinationen aus
Makrozellen sich das gewünschte Verhalten realisiern läßt.
Zweitens ist der 'menschliche' Faktor nicht zu vegessen: Man will ja
haben, was man meint und nicht das, was man hinzuschreiben in der Lage
ist. Da steckt ne Menge Übung, Gewöhnung oder aber Schusselfehler,
Mißverständnis usw. drin. Ist wie gesagt, bei einer HDL
fehlerträchtiger, bei Schematics bei Weitem nicht so sehr. (nur der, der
ein UND mit nem FF verwechselt, ist zu doof). In dem Sinne kann man
Schematics mit Assemblerprogrammierung vergleichen, wo man dediziert
selbst über die exakte Logik entscheiden kann - und eine HDL kann man
dann mit dem Programmieren in höheren programmiersprachenvergleichen.
Ich denk mal, dieser Vergleich hinkt gar nicht so sehr.
Abgesehen davon macht Schematics genau dann richtig Sinn, wenn man
hierarchisch arbeitet, sich also Funktionsblöcke macht. Kleine Beispiele
meinerseits: QVGA-LCD-Modul, DDS-Modul usw.
Ja, gilt elleweil, ich weiß.
W.S.
W.S. schrieb:> Lothar Miller schrieb:>> Was hast du denn da falsch gemacht?> Ähem.. na eben VHDL benutzt. Mal im Ernst, es ist fast 15 Jahre her
Ich vermute mal, die VHDL-Synthesizer haben sich in den letzten 15
Jahren deutlich weiter entwickelt als die Schaltplaneditoren...
> weil ne ganze Menge der einfachen Gatter eben intrinsics sind,> also die direkte Struktur des Bausteins darstellen.
Keineswegs: eine Makrozelle oder eine LUT sind eben kein 7-fach UND
oder ein 4zu1-Multiplexer. Auch diese einfachen "Basisfunktionen" sind
nur nachgebildet...
> In dem Sinne kann man Schematics mit Assemblerprogrammierung> vergleichen, wo man dediziert selbst über die exakte Logik> entscheiden kann.
Und hinterher genauso die Optimierung zuschlägt und eine beliebig
komplexe logische Funktion aus vielen einzelnen Gattern in 1 Makrozelle
oder LUT packt. Denn ich wäre sehr enttäuscht, wenn ich in ein 36
Makrozellen CPLD 36 einfache logische Funktionen mit je 2 Eingängen
(UND, ODER, NAN, NOR, XOR...) und letzlich 1 gemeinsamen Ausgang packen
würde, und dann wäre es voll...
Aber es ist wie es ist: wenn es (jemandem) reicht, mit
herstellerspezifischen Schaltplänen zu arbeiten, weil er einen
FPGA-Wechsel nicht in Betracht zieht (oder ziehen muss/darf/kann/will),
dann kann er auch die jeweiligen Schaltplaneditoren aus der Toolchain
verwenden.
Lothar Miller schrieb:> Ich vermute mal, die VHDL-Synthesizer haben sich in den letzten 15> Jahren deutlich weiter entwickelt als die Schaltplaneditoren...
Jaaa, das glaub ich gern, wenn ich mir Schematics von Xilinx anschaue.
Und die Brüder von Altera und Lattice sind noch viel schlimmer.
Lothar Miller schrieb:> eine Makrozelle oder eine LUT sind eben kein 7-fach UND> oder ein 4zu1-Multiplexer.
Du kennst aber (hoffentlich) den Unterschied zwischen Makrozellen und
LUT's, ja?
Ich bin momentan zu faul, um nachzuschauen, aber bei den Coolrunnern ist
es so, daß eine Makrozelle kein 7-fach UND hat, sondern 8 Stück (oder
noch mehr) 36-fach UND's, deren Ausgängen dann auf ein 8(oder mehr)-fach
ODER geht, woran sich ein D-FF mit diversen Eingängen (D, T, R, P, C, S,
E usw) anschließt. (Daten, Takt, Enable, synchrones setzen und
rücksetzen, dito asynchron) Das ist erheblich anders als eine LUT. Und
weil so eine Makrozelle eben riesige UND-Gatter hat, ist der Aufbau
großer synchroner Zähler bei CPLD's eben günstiger als bei FPGA's, weil
schneller. Bei FPGA's muß man für sowas mehrere LUT's kaskadieren.
Und so ein D-FF in so einer Makrozelle ist für viele einfache
schematics-Elemente eben intrinsic. Da wird nix "nachgebildet". Lies dir
mal die entsprechenden Dokus durch. In dem Punkt ist Xilinx vorbildlich.
W.S.
Hinter den lustigen Bildchen steckt bei Xilinx wohldokumentierter
VHDL-Code. Das ist auch gut so, man kann daher sehr schnell z.B.
aus einem 8-Bit-Zähler einen mit 11 Bit ableiten. Dass aber die
Bildchen ein anderes Syntheseergebniss liefern sollen als
entsprechender VHDL-Code, ist eine sehr naive Vorstellung.
W.S. schrieb:> Du kennst aber (hoffentlich) den Unterschied zwischen Makrozellen und> LUT's, ja?
Mit Verlaub, gegenüber Lothar ist das schon eine Frechheit. :-(
@ W.S.
Du bist also der Auffassung, dass die Synthese 1:1 das in den Chip
packt, was du in Schematics zeichnest?
Da habe ich aber ganz große Zweifel, dass das so stimmt.
Zeichne doch mal zwei Inverter hintereinander und schau, ob du die
nachher in deinem Chip wieder findest? Ich könnte wetten, dass du da
sehr lange suchen wirst ;-)
In VHDL kann man mindestens genauso exakt beschreiben, wie die Schaltung
im Chip aussehen soll. Vermutlich sogar noch exakter, da man nicht über
eine art "Zwischencode" gehen muss, der aus den Schaltsymbolen gebildet
wird, und auf den du keinen Einfluss hast.
Wenn das damals vor 15 Jahren bei dir gehörig in die Hose ging, dann
sicher nur deswegen, weil du einen bösen Fehler in der VHDL-Beschreibung
gemacht hast. Eventuell hast du ein Latch beschrieben, ohne es zu
merken.
Natürlich gebe ich dir recht, dass es für jemanden, der keine Ahnung von
VHDL hat, einfacher ist, einen Schaltplan zu zeichnen. Aber dass du,
aufgrund einer Erfahrung vor 15 Jahren, bei der du in VHDL gescheitert
bist, jetzt behauptest, dass man mit Schematics viel "näher" an der HW
ist, halte ich für den falschen Schluss.
Garantiert hast du damals eine Schaltung im Kopf gehabt, aber warst
nicht im Stande, diese korrekt in VHDL zu beschreiben. Und dann hat die
Synthese eben das umgesetzt, was du beschrieben hast. Wie gesagt,
vermutlich hast du, ohne es zu merken, ein Latch beschrieben.
Deine Schlussfolgerung damals war dann ganz offensichtlich: Die Synthese
ist zu doof, meinen schönen HDL-Code umzusetzen, also zeichne ich
Schematics. Das hat dann wunderbar geklappt und nun bist du seit 15
Jahren der Auffassung, dass VHDL nicht geeignet ist, Hardware exakt zu
beschreiben.
Vielleicht gibts du HDL nochmal eine Chance und fängst mit ganz kleinen
"Elementen" an und du wirst sehr schnell feststellen, dass bei korrekter
Beschreibung auch exakt das rauskommt, was du dir wünschst.
Guido schrieb:> W.S. schrieb:>> Du kennst aber den Unterschied zwischen Makrozellen und LUT's, ja?> Mit Verlaub, gegenüber Lothar ist das schon eine Frechheit.
Danke für die Stellungnahme, aber ich steh da drüber... ;-)
W.S. schrieb:> Ich bin momentan zu faul, um nachzuschauen, aber bei den Coolrunnern ist> es so, daß eine Makrozelle kein 7-fach UND hat, sondern 8 Stück (oder> noch mehr) 36-fach UND's, deren Ausgängen dann auf ein 8(oder mehr)-fach> ODER geht
Also wird auch dort ein einfacher Schaltplan mit einem 7-fach UND und
einem weiteren Gatter dahinter eben nicht genau so umgesetzt, sondern
noch heftig optimiert. Denn wenn der Schaltplan genauso umgesetzt
würde, dann könnte ich gerade mal 36 logische 2-Input
Basisfunktionen realisieren, und dann wäre das CPLD "voll".
> Und weil so eine Makrozelle eben riesige UND-Gatter hat, ist der Aufbau> großer synchroner Zähler bei CPLD's eben günstiger als bei FPGA's, weil> schneller. Bei FPGA's muß man für sowas mehrere LUT's kaskadieren.
Nichtsdestrotz bekomme ich ohne weiteres in einem billigen S3 FPGA
einen 32-Bit-Zähler hin, der mit 500MHz getaktet werden kann. Und das,
weil die FPGA-Designer genau diese Problematik auch erkannt haben und
für solche Zähler (und/oder allgemein Addierer) eine extra Carry-Chain
eingbaut haben.
> Und so ein D-FF in so einer Makrozelle ist für viele einfache> schematics-Elemente eben intrinsic. Da wird nix "nachgebildet".
Damit ist dann aber auch schon Ende.
Ein Addierer existiert nicht, ein Mux auch nicht, die ganzen
2,3,4...16..-fach UND/ODER/NOR/NAND... existieren auch nicht, sondern
werden erst zusammengefasst und dann optimiert. Und die Tabelle, die
dabei herauskommt, hat mit dem ursprünglichen Schaltplan nur noch die
Funktion gemeinsam. Du könntest nicht einfach "rückwärts" gehen und
hättest deinen Schaltplan wieder. Und die Funktion kann ich mit VHDL
auch ganz einfach und genau beschreiben.
Lothar Miller schrieb:> Also wird auch dort ein einfacher Schaltplan mit einem 7-fach UND und> einem weiteren Gatter dahinter eben nicht genau so umgesetzt, sondern> noch heftig optimiert.
Ja. Wenn man ein CPLD mit was extrem Simplem füllt, dann ist es auch mit
diesem Simplem ruckzuck voll.
Aber deine Darstellung ist so nicht richtig. Wenn das "einem weiteren
Gatter dahinter" eine logische Verknüpfung ist, dann ist das mit dem
ODER am Ausgang des UND erledigt. Aber bleiben wir lieber auf dem
Teppich.
Ergo wird dein Beispiel mit dem 7fach UND "und einem weiteren Gatter
dahinter" überhaupt nicht optimiert, sondern genau so umgesetzt wie
gemalt, denn das ist bereits intrinsic - bei CPLD's. Bei FPGA's sieht
die Sache anders aus, da ist der Hardwareansatz ganz anders und das
7fach UND braucht mehr als nur 1 LUT. Also zieh dir mal ne CPLD-Doku
rein - ist ja nicht sooo.. umfänglich.
Aber so langsam fange ich an, mich zu ärgern. Eigentlich mehr über dich
als über den Schlumpf, weil der ja auch nur Gast ist wie ich (aber das
überleg ich mir nochmal..).
Im Prinzip könnte ich dem Schlumpf zustimmen, wenn er meine Worte nicht
so bösartig vebogen hätte. Nicht alles in Schematics kann (und wird) 1:1
umgesetzt - sowas hab ich auch nicht geschrieben. Aber näher an der HW
ist man mit Schematics - es sei denne, man ist ein geübter VHDL-Guru und
kennt genau 100% aller möglichen Fallstricke, über die man in VHDL zu
stolpern pflegt. Das ist nämlich der Punkt, den ich schon in nem anderen
Beitrag geschrieben hab: Wer nicht 3 Stunden täglich VHDL übt, sondern
nen Sack anderer Probleme hat, wird mit dieser Programmiersprache nicht
glücklich. Das ist auch ne Frage des Anspruches. Ich brauch Tools, die
mir helfen, das zu realisieren, was ich an Ideen hab - und ich kann
Tools nicht leiden, die sich durch Eigenartigkeiten und Störrischkeit
hervortun - VHDL ist so ein Tool. Sowas benutze ich nicht freiwillig.
Schließlich soll die Maschine dem Menschen dienen (und nützen) und nicht
umgekehrt.
Aber das ist alles nur Herumtheoretisieren. OK, ist ja grad Wochenende
und zu kühl für den Liegestuhl im Garten.
So.
Nun denkt mal an den TO und sein Anliegen. Die allermeisten Leute, die
Geräte entwickeln und elektronische Schaltungen entwickeln, weil diese
in den Geräten halt gebraucht werden, kommen mit Schematics prinzipiell
(bis auf die Hakeligkeiten der Programme) sofort klar und fallen selbst
bei 80% Kenntnis von VHDL immer noch auf die Nase. Daß der TO hier seine
Probleme mit Datenverfälschungen hat, die auf asynchrones
Hineingrabschen in einen Zähler zurückzuführen sind, zeigt uns
allerdings, daß die wahren Probleme jenseits der Diskussion Schematics
versus HDL liegen.
W.S.
Nun, um´s von meiner Seite auch zuende zu bringen:
Stein des Anstoßes war ja eigentlich, dass du in deinem Post als Lösung
"Schematics" angegeben hast und im Nachsatz, dass man das natürlich auch
mit HDL lösen kann, aber dass es dann ungleich viel komplexer ist und
eigentlich nur ein paar elitären Gurus möglich, die jeden Tag mindestens
3h HDL klimpern..
Und diese Behauptung wollten weder Lothar noch ich so stehen lassen. Für
meinen Teil war es so, bei Lothar nehme ich mal an, dass das auch sein
Ansinnen war.
Ich gebe dir recht: VHDL ist mächtig und man kann sehr gewagte Dinge
damit machen, wo man wirklich genau wissen muss, was die Synthese daraus
bastelt.
ABER: Kein Mensch wird gezwungen, diese Konstrukte zu verwenden.
Wenn du Schematics eingibst, dann beschränkst du dich auch auf
Basiselemente wie Gatter, MUXer, Register etc. Und genau das kann man in
VHDL auch.
Die Regeln für diese Beschreibungen sind definitiv nicht nur
irgendwelchen Freaks vorbehalten, sondern so einfach, dass sie von jedem
innerhalb kurzer Zeit erlernbar sind.
Damit lässt sich dann schon alles realisieren.
VHDL bietet aber auch Konstrukte, denen man nicht direkt ansieht, was
sie tun. z.B. Loops etc. Aber wie gesagt, man kann jedes Design auch
komplett ohne diese Konstrukte abbilden.
Nun, aber am Ende bleibt es natürlich dem persönlichen Geschmack, den
eigenen Fähigkeiten und der Bereitschaft, sich mit Neuem zu befassen,
überlassen, wie man die Entry macht.
Und wie du geschrieben hast, hast du ja ordentlich andere Probleme zu
lösen und möchtest dich daher nicht mit HDL rumärgern. Vielleicht wäre
das ja genau der Anlass, sich mal mit der Materie zu befassen. Denn das,
was in stundenlanger unübersichtlicher Arbeit und der damit verbundenen
Fehlerträchtigkeit aufgrund falsch gezeichneter Schematics eingegeben
wird, lässt sich in VHDL mit BASISWISSEN meistens in wenigen Minuten
textuell eingeben.
Da wäre dann unter´m Strich mehr Zeit, sich um die eigentlichen Probleme
zu kümmern. :-)
Fazit der Sache ist: Du stellst eine Behauptung über VHDL in den Raum,
ohne dich wirklich mit VHDL auszukennen. Du hast einmal aus Unwissenheit
ein Design in VHDL verkorkst und nun steht für dich fest, dass VHDL ein
Ungetüm ist, von dem man jedem nur abraten kann, der nicht extrem tief
in die Materie einsteigen will.
Und das ist nicht gut, wenn man von etwas nur rudimentär Ahung hat, es
dann so hinzustellen, als sei es schlecht.
Lerne die VHDL-Basics und wenn du dann immer noch der Meinung bist, dass
Schematics viel besser sei, oder VHDL so irrsinnig komplex, dann kannst
du deine Behauptungen auch untermauern. Aber so sind sie einfach nur
haltlos.
So, hier war´s definitiv nicht zu kalt für in die Sonne liegen und drum
verschwinde ich auch gleich wieder an die frische Luft.
Btw: VHDL ist kein Tool, sondern eine Beschreibungssprache..
Euch allen einen schönen Sommerabend!