Ich habe das mal eine Frage über verschiedene Komponenten bzw. derer
Timings in VHDL.
Wenn ich mehrere Komponenten habe, die jeweiles die Werte der
vorangegangenen Komponente benötigt, z.B.:
Komponenten A,B,C, haben je ein Ausgang der der anderen Komponente als
Eingang dient. Der Eingang von A möge ein ADC sein und von C ein Ausgang
um eine externe Schaltung zu triggern:
ADC ----> A ----> B -----> C ----->extern
Wie baut man sowas klugerweise auf, sodass C erst den Eingang übernimmt,
wenn B fertig mit seiner Berechnung oder so ist?
Ich habe versucht sowas aufzubauen und bekommen immense Timingprobleme,
da die Komponenten einfach direkt miteinander verbunden sind.
Innerhalb der Komponenten finden verschiedene Berechnungen statt, die
unterschiedlich lange dauern.
Nutzt man da eher Handshakes unter den Komponenten? Ich glaube ich wühle
mich immer tiefer rein und sehe die einfachen Lösungen nicht mehr.
PS:
Diese Frage ist ein wenig vereinfacht dargestellt, um das Kernproblem zu
zeigen. In Realität soll diese FPGA-Konfiguration eine komplexe Regelung
mit Stromanstiegskompensationen, einer schnellen PWM (4MHZ) sowie
mehrerer langsameren PWM-Ausgänge (95kHz). Ebenso sollen verschiedene
Fehlerfälle abgefangen werden können. Daher ist es nicht so simpel oder
übersichtlich auf die verschiedenen Komponenten zu verzichten.
Komponenten-Timing schrieb:> Nutzt man da eher Handshakes unter den Komponenten? Ich glaube ich wühle> mich immer tiefer rein und sehe die einfachen Lösungen nicht mehr.
Welche Optionen kennst Du den?
Sagt dir die Stichworte Datarate conversion und FIFO etwas?
Hast du schonmal ein Blockdiagramm gezeichnet?
Ich setze bei solchen Datenpfaden definierte Zustände an den Ausgängen
ein.
Z.b. Dataout + Datavalid
Das Datavalid ist dann genau einen Takt aktiv, das Nachfolgemodul wartet
darauf und übernimmt die Daten sobald es aktiv wird.
Geht auch bei Pipelining mit kontinuierlichen Daten.
Gelegentlich brauchts noch sowas wie ein Sync/Start vorne weg.
Sind die Taktraten ECHT asynchron unterschiedlich, nicht nur ein 96Khz
Signal was man eh mit xx MHz und Clockenable berechnet, dann packe ich
ein Asynchrones Fifo dazwischen.
Das Datavalid ist dann das writeenable fürs Fifo, das als (not) empty
auf der anderen Seite wieder raus kommt.
Dunst Emulator schrieb:> Sagt dir die Stichworte Datarate conversion und FIFO etwas?
(Tiefe) FIFOs und Regelschleifen vertragen sich nicht wirklich, da es
hierbei so unnötigen Totzeiten kommt. Ein FIFO ist nur dann interessant,
wenn eine Datenquelle "stoßweise" Daten erzeugt, wohingegen der TE für
Regelungsaufgaben eher einen kontinuierlichen Datenstrom hat.
Also entweder setzt man einen Handshake-Mechanismus für die Übertragung
von Komponente zu Komponente ein oder man baut sich einen separaten
Timingblock, der für die einzelnen Komponenten mehrphasige Takte
generiert.
Dunst Emulator schrieb:> Komponenten-Timing schrieb:>> Nutzt man da eher Handshakes unter den Komponenten? Ich glaube ich wühle>> mich immer tiefer rein und sehe die einfachen Lösungen nicht mehr.>> Welche Optionen kennst Du den?> Sagt dir die Stichworte Datarate conversion und FIFO etwas?> Hast du schonmal ein Blockdiagramm gezeichnet?
Das Prinzip des FIFOs kenne ich, Datarate conversion wüsste ich so
spontan nicht, wie dies mein Problem lösen kann.
Das mit dem "Dataout + Datavalid" geht ungefähr in die Richtung, wie ich
es mir auch gedacht hätte. Ist zwar kein richtiges Handshake, da dass
Validsignal nicht vom folgenden Modu zurückgesetzt ist. Könnte aber
schon mein Problem lösen.
Ich werde es mal ausprobieren und dann berichten. Bis hierhin schonmal
Danke ;)
Andreas S. schrieb:>> Also entweder setzt man einen Handshake-Mechanismus für die Übertragung> von Komponente zu Komponente ein oder man baut sich einen separaten> Timingblock, der für die einzelnen Komponenten mehrphasige Takte> generiert.
Wie meinst du das genau mit dem Timingblock?
Das dort wirklich "nur" aus dem Systemtakt weitere heruntergeteilte
Takte generiert werden (über Zählwerke?) und diese Teiltakte dann also
Triggerung von synchronen Prozessen in meinen Komponenten dienen?
ich mache sowas mittlerweile alles als AXI4-Stream-Interface mit TDATA,
TVALID und TREADY. Die IP-Cores von Xilinx (Cordic, FIR-Filter, usw.)
haben auch dieses Interface
Komponenten-Timing schrieb:> Wie meinst du das genau mit dem Timingblock?> Das dort wirklich "nur" aus dem Systemtakt weitere heruntergeteilte> Takte generiert werden (über Zählwerke?) und diese Teiltakte dann also> Triggerung von synchronen Prozessen in meinen Komponenten dienen?
Oh, ich hatte mich in der Tat etwas ungünstig ausgedrückt: zusätzliche
Takte darf man nicht durch solche Zählwerke erzeugen, weil man die nie
wieder synchron bekommt, sondern solch ein Timingblock darf natürlich
nur Clock Enables oder Strobes für die einzelnen Aktionen erzeugen. Die
Erzeugung der eigentlichen Takte sollte nur in den entsprechenden
dedizierten Taktbausteinen (Xilinx: Clocking Wizard mit MMCM und PLL)
erfolgen, damit auch die zugehörigen Taktverteilnetze (Xilinx: BUFG,
BUFH, BUFR, usw., siehe UG472) richtig verwendet werden.
Lukas schrieb:> ich mache sowas mittlerweile alles als AXI4-Stream-Interface mit TDATA,> TVALID und TREADY. Die IP-Cores von Xilinx (Cordic, FIR-Filter, usw.)> haben auch dieses Interface
womit man sich aber auf X festlegt. Natives VHDL kriegst du überall
rein.
Bonzo schrieb:> Lukas schrieb:>> ich mache sowas mittlerweile alles als AXI4-Stream-Interface mit TDATA,>> TVALID und TREADY. Die IP-Cores von Xilinx (Cordic, FIR-Filter, usw.)>> haben auch dieses Interface>> womit man sich aber auf X festlegt. Natives VHDL kriegst du überall> rein.
Nö, das Interface ist natives VHDL und dazu noch recht einfach.
Lukas schrieb:> Bonzo schrieb:>> Lukas schrieb:>>> ich mache sowas mittlerweile alles als AXI4-Stream-Interface mit TDATA,>>> TVALID und TREADY. Die IP-Cores von Xilinx (Cordic, FIR-Filter, usw.)>>> haben auch dieses Interface>>>> womit man sich aber auf X festlegt. Natives VHDL kriegst du überall>> rein.>> Nö, das Interface ist natives VHDL und dazu noch recht einfach.
Das Interdace als solches natürlich nicht, lässt sich selbstredend
leicht nachbilden. Die Cores aber nicht und darum ging es ja. Wenn ich
keine Cores von Xilinx verwende, muss ich auch kein Protokoll nutzen,
das dazu kompatibel ist.