Hallo,
ich bin gerade dabei, eine Art Treiber-CPLD für LEDs anzudenken.
Die Idee ist, dass über einen mehrpoligen Bus der Reihe nach Farbwerte
für die einzelnen angeschlossenen seriell LEDs übertragen werden. Diese
werden abgespeichert und nach Erhalt eines "Start"-Signals aktiviert.
Ab diesem Zeitpunkt an werden die angeschlossenen LEDs mit den
erhaltenen Helligkeitsinformationen PWM-gedimmt. Bis zum Eintreten des
nächsten START-Signals werden währenddessen neue PWM-Werte empfangen.
Die Clock-Leitung des Busses dient dabei als Clock für das ganze CPLD.
An ihr hängt also auch die PWM.
Hier mein Programm im Einzelnen:
Ein interner Counter zählt die erhaltenen CLK-Signale, um die
Adressierung der Speicher-Flipflops sicher zu stellen. Damit es zu
keiner Race-Condition kommt, zählt er als einziger Prozess bei einer
negativen Flanke
1
Zaehler:
2
process
3
begin
4
waituntilfalling_edge(CLK);
5
if'1'=STARTthen
6
largeCnt<=0;
7
else
8
largeCnt<=largeCnt+1;
9
endif;
10
endprocessZaehler;
Hier wird (wegen der vielen Konstanten etwas unübersichtlich) das am Bus
anliegende Signal in das LEDdata-Array gespeichert.
Dieser Prozess verschiebt die Daten in das LASTdata-Array, wenn die
Übertragung abgeschlossen ist.
1
Startmove:
2
process
3
begin
4
waituntilrising_edge(CLK);
5
if'1'=STARTthen
6
forjin0toLEDs-1loop
7
LASTdata(j)<=LEDdata(j);
8
endloop;
9
endif;
10
endprocessStartmove;
Mit den interessanten bits des largeCnt-Signals und den in LASTdata
gespeicherten Werten wird an den Ausgangspins eine PWM realisiert.
1
Output:
2
process
3
begin
4
waituntilrising_edge(CLK);
5
6
foriin0toLEDs-1loop
7
if(largeCntmodPWMres)<LASTdata(i)then
8
LEDout(i)<='0';
9
else
10
LEDout(i)<='1';
11
endif;
12
endloop;
13
endprocessOutput;
14
endverhalten;
ich hoffe, der Code ist so zerstückelt besser lesbar geworden.
Als Plattform möchte ich einen Altera MAX II verwenden, der laut
datasheet bis 304 MHz spezifiziert ist.
Allerdings wirft die Timing-Analyse einen Haufen Fehler (failed paths),
wenn ich probehalber 266MHz verlange. "Actual time" wird mit 50MHz
angegeben.
Nun stellen sich für mich mehrere Fragen:
- auf was beziehen sich denn diese angegebenen 304 MHz? Wie kann ich
abschätzen, ob ein in Frage kommender PLD meinen Anforderungen
entspricht?
- was bedeutet es denn, wenn ich 266MHz verlange? Bisher dachte ich,
dass ich damit spezifiziere, dass die negativen Flanken dss CLK-Signals
mit 266MHz ankommen können. Aber genauer betrachtet bin ich mir nicht
sicher, ob das alles ist.
Immerhin wäre es mir ja egal, wenn alle Ausgänge z.B. 100ns später
aktualisiert werden. Wichtig für die Funktionalität ist ja nur, das
intern die Zuweisung der Adressen, die Speicherung der Buswerte und das
"Verschieben" bei "START" sauber geschieht. Gleichmäßige Latenzen stören
mich eher wenig. Oder anders: die Priorität der PWM ist eher gering =)
- Was kann ich am Code ändern, um die Timing Requirements zu erfüllen?
Beziehungsweise, wie kann ich dem Programm klar machen, welche
Funktionalität genau wichtig ist? Also dass ein anliegendes Signal nach
3ns wieder im Ausgang liegt, gehört ja wie erläutert schon mal nicht
dazu.
- gibt es unter Umständen eine klügere Lösung, als den Zähler bei einer
rising_edge zu aktualisieren? Das hätte für die Erzeugung des
BUS-Signals eventuell Vorteile...
Armin schrieb:
> - auf was beziehen sich denn diese angegebenen 304 MHz?
Auf die Schaltfrequnz zweier ideal verbundener Flipflops innerhalb des
Bausteins. Da ist einiges an Handarbeit und wohlüberlegter Beschreibung
nötig, dass dieser Wert erreicht wird. Garantiert bekommst du nicht das
ganze Design so schnell. Bestenfalls kleine Teile davon.
> "Actual time" wird mit 50MHz angegeben.
Das kommt wahrscheinlich von dem Monstermux, den du da aufgebaut hast:
DATABUS(3*PWMbits*j+PWMbits to 3*PWMbits*j+PWMbits+PWMbits-1)
Mach sowas besser über ein Schieberegister.
alles klar, danke für den Tip.
Ich hab das mal geändert und als Schieberegister realisiert (denke, das
erkennt man schön)
Im Anhang hab ich mal einen aktuellen Schaltplan (inkl weiterer kleiner
Änderungen)
der BUS hat hier eine Breite von 6 bit (2bit PWM und 3LEDs). In 4 Takten
sind die Register alle gefüllt und ein START-Signal wäre sinnvoll.
Die Geschwindigkeit hat dadurch tatsächlich profitiert. Je nach Größe
gehen mittlerweile 70-80MHz statt vorher 40-60MHz.
Wie geht's weiter?
Ich habe noch ein wenig experimentiert:
1. Eigentlich könnte man den LASTdata-Zwischenspeicher weglassen. Dann
wird die Anzeige LED für LED aktualisiert und nicht mehr bei jedem
START. Das bringt laut Timing Analyzer allerdings keine Vorteile.
2. Könnte man das gesamte design wegen dem hinzugekommenen
Schieberegister auf die rising_edge takten? Der largeCnt-Counter ist ja
nicht mehr zur Adressierung des MUX da, sondern nur noch für den enable
der Schieberegister. Meint ihr das gibt Probleme?? Falls nicht, wäre die
Frequenz schonmal doppelt so hoch.
3. Wenn man im output-process das "wait until" wegmacht und eine
Sensitivity List schreibt, verschwinden die FlipFlops am Ausgang (siehe
Schaltplan). Wirklich deutliche Geschwindigkeitsvorteile bringt das aber
nicht. Was ist klüger?
4. Hier im Board habe ich gelesen, dass die "<"-Vergleiche sehr
aufwändig sind. Ließen sich diese geschwindigkeitseffizient einsparen?
Der erste "LessThan0" vergleicht den Zähler mit ein bis zwei Konstanten
("nur ein paar Takte lang kommen wirklich Daten für Diesen CPLD"). Die
Ausgangszähler realisieren die PWM (zeitunkritisch).
Armin schrieb:
> 3. Wenn man im output-process das "wait until" wegmacht und eine> Sensitivity List schreibt, verschwinden die FlipFlops am Ausgang
Klar, denn dann ist das alles einfach nur noch kombinatorisch. Und
warten auf einen Takt heißt ja gerade, dass FFs verwendet werden sollen.
> Was ist klüger?
Das kommt darauf an.
Wenn du in FPGAs diese Register drin lässt, dann kommen die Daten am
Ausgang mit deutlich geringerem Laufzeitunterschied, und sie kosten
keine zusätzlichen Ressourcen, weil sie dort im IO-Block schon mit drin
sind.
Wenn du allerdings den 1 Takt Latency nicht brauchen kannst, dann mußt
du die Dinger leider weglassen.
> Hier im Board habe ich gelesen, dass die "<"-Vergleiche> sehr aufwändig sind.
Das betrifft CPLDs mit ihren Produkttermen.
In FPGAs kann die Synthese mit einem > und < Vergleich besser
optimieren. Da habe ich die Erfahrung gemacht, dass solche Vergleiche
durchschnittlich effizienter implementiert werden als ein = oder ein /=.
> Könnte man das gesamte design wegen dem hinzugekommenen> Schieberegister auf die rising_edge takten?
Das wäre sowieso sinnvoll, denn die Toolchain muss durch die Verwendung
der steigenden und der fallenden Flanke quasi mit der doppelten
Frequenz kalkulieren. Wenn du im gesamten Design nur auf eine Flanke
reagierst, könnte sich u.U. die maximale Frequenz sofort verdoppeln.
Lothar Miller schrieb:
>> Hier im Board habe ich gelesen, dass die "<"-Vergleiche>> sehr aufwändig sind.> Das betrifft CPLDs mit ihren Produkttermen.> In FPGAs kann die Synthese ...
Die Altera MAX II die hier verwendet werden sind von Ihrem Aufbau quasi
FPGAs und keine CPLDs. Sie unterscheiden sich signifikant von den Xilinx
und Lattice CPLDs.
Also gut. Dann bleiben die Ungleichheitszeichen drin.
Mit allen bisherigen Ergebnissen und Experimenten komm ich auf eine
maximal erlaubte Clock-Geschwindigkeit zwischen 80MHz und 120MHz - je
nach Wahl der Konstanten.
Dann versuche ich - um auf Nummer sicher zu gehen - , unter diesem Wert
zu bleiben.
Kann ich also davon ausgehen, dass wenn ich den MAXII mit diesem Takt
anfahre, dass es dann intern keine Komplikationen gibt? Es existieren ja
noch weitere Kenngrößen im "timing analyzer": tsu, tco, tpd, th
Versteh ich die Kenngrößen richtig?
tsu - da das CLK-Signal im Chip schneller unterwegs ist, müssen die
BUS-Signale um tsu früher anliegen, damit sie intern an der Logik sind,
bevor der CLK da ist. Für mich also zeitkritisch, da sonst die Werte
nicht abgespeichert werden können. Ich gebe die halbe Taktperiode an, da
meine BUSdaten mit der negativen Flanke angelegt werden?
tco - "maximum acceptable clock to output delay" - verstehe ich nicht
ganz, aber da am output nichts mehr synchron sein muss, wähle ich eine
große Zeit, oder? (10*Taktperiode, 40ns bei 250MHz)
tpd - "Specifies the maximum acceptable input to non-registered output
delay, that is, the time required for a signal from an input pin to
propagate through combinatorial logic and appear at an output pin." Ist
mir auch nicht ganzt klar, was das genau bedeutet. Komplett durch den
Chip durch geht ja kein Signal - außer vielleicht CLK über den Counter.
Kann ich also wieder vernachlässigen (10*Taktperiode), da es wieder nur
um die Ausgänge geht? Außerdem hab ich ja keine "non-registered"
Outputs, wie oben im kleinen Schaltplan zu sehen ist.
th - "Specifies the maximum acceptable clock hold time for the input
(data) pin." Bedeutet was? Dass der so Takt so lange aktiv sein muss,
bis die Flanke im ganzen Chip angekommen ist? Hört sich eher gefährlich
an... Halbe Taktperiode?
Aber werden mit dem Analyzer über diese Kenngrößen auch schon interne
Laufzeitprobleme erfasst? Oder kann ich mich darauf verlassen, dass es
die Toolchain hinbekommt, beispielsweise den Zähler schnell genug zu
implementieren?
Die Toolchain sagt dir am Ende einer Synthese, mit welcher maximalen
Frequenz du dein Desing im CPLD / FPGA laufen lassen kannst, dass
gewährleistet ist, dass alle Zeitanforderungen eingehalten werden.
Es wird also sichergestellt, dass die Signallaufzeit durch den
LANGSAMSTEN kombinatorischen Pfad zwischen zwei Registern inclusive der
Brücksichtigung aller Werte für Tsu etc. nicht länger als eine Zeit X
ist.
Die maximale Frequenz ergibt sich dann aus 1/X.
Aber ganz ehrlich sehe ich nicht, warum du eine PWM-Geschichte für LEDs
mit 200MHz takten willst?
tsu
Am einem FF (Flip -Plop), auch Register genannt, müssen das Datenbit
eine Weile vor dem Takt anliegen. Sonst wird das Datenbit nicht sicher
erkannt. Das ist die Setup-Time (tsu)
th
Ebenso muss das Datenbit noch dem Takt noch für eine Weile anliegen. Das
ist die Hold-Time.
Innerhalb der eines CPLDs oder FPGAs gibt ein ausgeklügeltes
Clock-System mit speziellen Leitungen die den Takt auf dem Silizium so
verteilt, dass ermöglichst synchron an allen FFs gleichzeitig anliegt
(bitte mich jetzt nicht prügeln, für einen Anfänger reicht diese
Betrachtung). Dann kommen noch Signallaufzeiten dazu die das Signal auf
dem Chip von einem Ausgang eines FFs zum Eingang eines nächsten
benötigt. tsu + th + Laufzeit begrenzen die maximale Taktrate. Damit das
sicher funktioniert wird der Pfad gesucht, bei dem die Laufzeit am
größten ist.
tco
Ist die Zeit die ein Signal benötigt das von einem Takt an einem FF
übernommen wird und bis es dann an einem "Beinchen" ankommt.
tpd
Die Zeit die in einem rein kombinatorischen Pfad von einem
Eingangsbeichen zu einem Ausgangsbeinchen benötigt wird.
Auf das innere Timing kannst Du dich verlassen, allerdings musst Du das
"Einsynchronisieren" unbedingt beachten. Sonst kann es zu Metastabilen
Zuständen kommen. Dazu gibt es genügend Beiträge im Forum was das
bedeutet und wie so was zustande kommt.
Schrotty, du hast natürlich recht! Das Takten der LEDs muss nicht mit so
hoher Frequenz passieren. Ich könnte genausogut vorher eine
Integer-Division auf den Zähler durchführen und damit "weniger schnelle
bits" die PWM steuern lassen.
[Zur Erklärung: die hohe Frequenz kommt von der Datenmenge, die über den
Bus muss (in Verbindung mit begrenzen Pinzahlen).]
Einen Nachteil sehe ich derzeit aber darin auch nicht. Oder hat jemand
Erfahrungen mit LED-Schaltverlusten bei diesen Geschwindigkeiten?
Wie schnell die PWM in der Praxis genau wird und welche Auswirkungen das
hat werde ich dann beizeiten einfach durch "Testen" herausfinden. Was
das Treiben angeht, habe ich demnächst ohnehin noch ein paar weitere
Fragen, die hier thematisch gar nicht passen und deswegen einen neuen
Thread bekommen.
Aktuell:
Die tsu macht mich noch Probleme. Das Design wäre jetzt mit ca. 100MHz
lauffähig (10ns). Aber die tsu beträgt 6.6ns. Also müsste ich praktisch
beim Erzeugen der Busdaten diese etwa einen 2/3 Takt vor dem CLK auf die
Reise schicken oder?
Dafür sehe ich prinzipiell zwei Lösungen:
1. Die Erzeugung (wieder mittels CPLD oder FPGA) läuft mit der
dreifachen Geschwindigkeit. im ersten Schritt werden die Daten an den
BUS gelegt, im zweiten Schritt herrscht Langeweile, im dritten Schritt
wird CLK hinterhergeschickt. Das sieht aber in meinen Augen ziemlich
aufwändig aus.
2. ich schaff es, per Layout das CLK-Signal um 7ns zu verzögern. Das
ergibt also 7ns * 300e06m/s = 2.1 Meter - und das, ohne eine Antenne zu
bauen...
Auch das klingt - selbst so ganz ohne HF-Erfahrung - utopisch?
was meint ihr?
Wie löst man sowas üblicherweise?
Armin (Gast)
>Wie löst man sowas üblicherweise?
Ganz anders. Beschäftige dich mal mit den Grundlagen synchroner,
digitaler Schaltungen. Fang mal hier an, SDRAM-Timing
Ein schneller IC ersetzt kein Fachwissen.
MfG
Falk
> Aber die tsu beträgt 6.6ns.
Welche?
Die tsu eines heutigen FFs in einem FPGA ist garantiert um eine
Zehnerpotenz niedriger. Du verwechselst da was.
> Wie löst man sowas üblicherweise?
Man schaut einfach mal über den Tellerrand, wie z.B. Daten zu
LC-Displays übertragen werden. Dort geht das mit LVDs, damit der
Datenpfad an sich mal sauber definiert ist und nicht noch Tricks mit der
Terminierung gemacht werden müssen.
Warum brauchst du eifentlich so eine auffällig hohe Übertragungsrate?
Eine LVDS-Lane bei einem Display kann 3*8 Bit bei ca. 25 MHz
LVDS-(Pixel-)Takt, der dann 7-fach überabgetastet wird und in 175 MHz im
FPGA resultiert.
>Aber die tsu beträgt 6.6ns
Welche Tsu meinst du? Die, der Register in deinem FPGA? Ganz sicher
nicht, die ist viel geringer.
Ich versteh nicht ganz, wo dein problem ist. Offensichtlich redest du
von einem externen Bus (also außerhalb des FPGA) mit einem ebenso
externen CLK.
Solche Signale solltest du eigentlich mit dem internen Takt deines FPGA
abtasten. Und dann kommt her Shannon in´s Spiel ;-)
Wenn dein FPGA SERDES-Blöcke zur Verfügung stellt, könntest du das
Problem mit diesen Erschlagen, denn die können mit deutlich höheren
Frequenzen zurechtkommen (mal salopp formuliert)
Wenn du keinen Separaten Takt für das FPGA verwendest, sondern das FPGA
mit dem Bustakt des externen Bus taktest, dann kann man sowas auch
machen, allerdings solltest du dann die Laufzeitunteschiede von deinen
Pins (Takt und Daten) bis zum ersten Register durch geeignete
Constraints so setzen, dass die Synthese "weiss", dass zwischen diesen
Signalen nur ein maximaler Skew erlaubt ist.
Wie das geht, steht im Handbuch des Synthesewerkzeugs.
Ich hoff, ich hab dein Problem richtig erfasst