Hallo!
Ich baue gerade einen XC9572XL basierten Anodencontroller für LED
Matrizen.
Der CPLD lauscht an der Clockleitung des SPI Busses mit dem die
Shiftregister mit integrierten Konstantstromsenken mit Daten beladen
werden.
Jede 2592 Clocks muss folgendes passieren:
Es sollen 8 Anodenausgänge durchgeschaltet werden, es soll jeweils 1
Anodenausgang low sein, während die anderen High-Z sind.
Der CPLD soll auch ein Latchsignal für die Shiftregister generieren.
Dabei muss der Latch mindestens 10ns nach der letzten ansteigenden
Clockflanke und mindestens 100ns vor der nächsten ansteigenden
Clockflanke kommen.
Außerdem soll ein Reset vorhanden sein welcher die Register auf bekannte
Startwerte setzt und alle Ausgänge auf High-Z schaltet.
Im Moment habe ich das ganze wie folgt implementiert:
Im behavioral Sim scheint es richtig zu funktionieren, da ich aber nicht
all zu viel Erfahrung mit VHDL und CPLDs habe vermute ich, dass man den
Code auch eleganter schreiben könnte.
Ich würde mich freuen wenn ihr kurz drüber schauen und mir
Verbesserungsvorschläge geben könntet.
Alex T. schrieb:> dass man den Code auch eleganter schreiben könnte.
Man sollte den Reset aus der Sensitivliste rauslassen, weil die Prozesse
wegen des synchronen Resets nur auf clk sensitiv sind.
(Eine Frage am Rande: ist der Reset wirklich einsynchronisiert?)
Falls nicht: Gratulation!
Du hast einen Zustandsautomaten mit asynchronem Eingang gebaut:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Man sollte immer die selbe Taktflanke verwenden, weil sich sonst die
Laufzeiten für bestimmte Pfade halbieren, und das Design eigentlich für
den doppelte Taktfrequenz ausgelegt werden muss. Noch schlimmer ist es,
wenn dann das Tastverhältnis des Takte nicht genau 50% ist...
> anodes <= "ZZZZZZZZ";
Warum hochohmig? Hängt an dem Bus noch was anderes?
> anodes(7 downto 0) <= output(7 downto 0); --Anodenbits ausgeben
So gehts kürzer:
anodes <= output; --Anodenbits ausgeben
Erstmal vielen Dank für die Antworten!
> Hast Du da noch eine passende Testbench dazu?
Ich habe noch nie eine geschrieben. Werde es mir demnächst anschauen.
Getestet habe ich es in Isim mit "Force constant" und "Force Clock".
> Eine Frage am Rande: ist der Reset wirklich einsynchronisiert?
Habe mal auf deiner Seite die Infos darüber nachgelesen, tatsächlich war
der reset nicht richtig einsynchronisiert. Werde das korrigieren.
> Man sollte immer die selbe Taktflanke verwenden, weil sich sonst die
Laufzeiten für bestimmte Pfade halbieren, und das Design eigentlich für
den doppelte Taktfrequenz ausgelegt werden muss. Noch schlimmer ist es,
wenn dann das Tastverhältnis des Takte nicht genau 50% ist...
Der Grund für das Verwenden beider Taktflanken ist dass ich nicht weiß
wie ich das Timing für den Latch erfülle: "Dabei muss der Latch
mindestens 10ns nach der letzten ansteigenden
Clockflanke und mindestens 100ns vor der nächsten ansteigenden
Clockflanke kommen."
Wenn ich den bei der letzten ansteigenden Clockflanke hoch setzte kommt
er möglicherweise zu früh, wenn ich den bei der ersten ansteigenden
Clockflanke setze kommt er zu spät.
Bei der Abtastung an der fallenden Flanke kann ich den Latch nach einer
halben Clockperiode setzen. Sprich solange meine SPI Clock kleiner als
5MHz ist kann ich die Timings für den Latch einhalten.
Gibt es da eine Lösung bei der ich dem CPLD nicht einen eigenen von SPI
unabhängigen clock zuführen muss?
> Warum hochohmig? Hängt an dem Bus noch was anderes?
Die Ausgänge hängen an Gates der P-MOSFETs die wiederum mit einem Pullup
an maximal 5V hängen. Damit nutze ich die 5V Toleranz des CPLD aus und
spare Treibertransistoren um die P-MOSFETs zu treiben.
Alex T. schrieb:> Getestet habe ich es in Isim mit "Force constant" und "Force Clock".
Schreib eine Testbench. Das geht für dieses Projekt unglaublich einfach.
siehe dort zweiter Teil:
http://www.lothar-miller.de/s9y/archives/80-Hello-World!.html
Und nochmal Schritt für Schritt in der zweiten Hälfte der Anleitung:
http://www.lothar-miller.de/s9y/archives/81-Xilinx-ISE-Step-by-Step.htmlAlex T. schrieb:> Der Grund für das Verwenden beider Taktflanken ist dass ich nicht weiß
Das ist in der Regel der schlechteste Grund!
> wie ich das Timing für den Latch erfülle: "Dabei muss der Latch> mindestens 10ns nach der letzten ansteigenden> Clockflanke und mindestens 100ns vor der nächsten ansteigenden> Clockflanke kommen."
Woher hast du diese Zeiten?
> Wenn ich den bei der letzten ansteigenden Clockflanke hoch setzte kommt> er möglicherweise zu früh, wenn ich den bei der ersten ansteigenden> Clockflanke setze kommt er zu spät.
Ratestunde?
In einem FPGA ist es bei einem synchronen Design so, dass sofort nach
und wegen einer positiven Taktflanke Unruhe hersscht, weil neue
Zustände, Zählerstände usw... ermittelt werden. Das dauert eine Weile
und muss rechtzeitig vor der nächsten positiven Taktflanke muss Ruhe
herrschen. Und ob es reicht oder nicht, dass können die Tools selber
ausrechnen, du sagt in einem Constraints-File nur, welche Taktfrequenz
du willst.
> Woher hast du diese Zeiten?
Die sind aus dem Datenblatt des Schieberegisters/Stromsenke:
http://www.ti.com/lit/ds/symlink/tlc5947.pdf
Die relevanten zeiten sind:
Th1 ist die Zeit zwischen der letzten ansteigenden Clockflanke und dem
Latch - mindestens 10ns.
Tsu1 ist die Zeit zwischen dem ansteigendem Latch und der nächsten
Clockflanke - mindestens 100ns.
> Ratestunde?
Möglicherweise weil: Wenn ich den Latch bei der letzten Clockflanke
setze und der mehr als 10ns im CPLD braucht wird das Timing des
Schieberegisters eingehalten. (sind die Timings im CPLD determenistisch?
oder handelt es sich um Maximalwerte?)
Alex T. schrieb:> Der CPLD lauscht an der Clockleitung des SPI Busses mit dem die> Shiftregister mit integrierten Konstantstromsenken mit Daten beladen> werden.>> Jede 2592 Clocks muss folgendes passieren:
Das ist übrigens ein recht kritischer Ansatz, denn wenn du nur die Takte
mitzählst und sonst keinen Sync-Mechanismus hast, dann hagelt dich ein
einziger Störimpuls für den Rest des Tages raus... :-o
Alex T. schrieb:> (sind die Timings im CPLD determenistisch?> oder handelt es sich um Maximalwerte?)
Zweimal ja.
Weil die Maximalwerte angegeben werden, sind die Zeiten
deterministisch. Dein eigentliches Problem hier ist, dass du Zeiten
generieren willst und keinen Takt hast. Denn jede Zeit in einem
programmierbaren Baustein mird idR. über Zähler realisiert.
> Dabei muss der Latch mindestens 10ns nach der letzten ansteigenden> Clockflanke und mindestens 100ns vor der nächsten ansteigenden> Clockflanke kommen.
Das kannst du dann bestenfalls über Hardwaregebastel hinbiegen...
Der richtige und einzig sinnvolle Ansatz ist, den Latch-Impuls vom uC
aus zu generieren. So ist das eigentlich gedacht...
> Das ist übrigens ein recht kritischer Ansatz, denn wenn du nur die> Takte mitzählst und sonst keinen Sync-Mechanismus hast, dann hagelt> dich ein einziger Störimpuls für den Rest des Tages raus... :-o
Eventuell könnte ich dem Entgegenwirken indem ich nach jedem Frame
(20736 Clocks) den CPLD resette.
> Dein eigentliches Problem hier ist, dass du Zeiten> generieren willst und keinen Takt hast. Denn jede Zeit in einem> programmierbaren Baustein mird idR. über Zähler realisiert.
Sprich idealerweise hätte der CPLD einen eigenen Takt mit dem ich die
entsprechenden Delays generieren kann?
> Der richtige und einzig sinnvolle Ansatz ist, den Latch-Impuls vom uC> aus zu generieren. So ist das eigentlich gedacht...
Klar, ich würde im Prinzip auch ohne CPLD auskommen nur: Ich möchte die
ganze Bildausgabe durch einen DMA im uC realisieren, welcher quasi
endlos den Speicherbereich mit dem Frame auf dem SPI ausgibt. Sprich das
Chipselect kann automatisch nur ausgegeben werden wenn der DMA am Ende
des Frames ankommt.
Der wichtigere Grund ist aber: Ich wollte schon immer mal mit CPLDs
rumspielen und dachte eine praktische Verwendung für den CPLD gefunden
zu haben.
Alex T. schrieb:>> Das ist übrigens ein recht kritischer Ansatz, denn wenn du nur die>> Takte mitzählst und sonst keinen Sync-Mechanismus hast, dann hagelt>> dich ein einziger Störimpuls für den Rest des Tages raus... :-o> Eventuell könnte ich dem Entgegenwirken indem ich nach jedem Frame> (20736 Clocks) den CPLD resette.
Könnte man machen, das ist dann ja auch ein Sync-Impuls...
> Sprich idealerweise hätte der CPLD einen eigenen Takt mit dem ich die> entsprechenden Delays generieren kann?
Ja, so um die 50MHz sind da üblich. Nur blöd, dass in einem CPLD so
wenige Flipflops sind...
Gut, dann probiere ich es mal mit einem extra Takt umzusetzen. Mal sehen
wie weit ich mit dem CPLD den ich habe komme.
Vielen Dank für deine Hilfe, ich hab einiges gelernt!