Taktung FPGA/CPLD

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

Einleitung

Von den vier Signalgruppen

  • interne Signale
  • IO Signale
  • Reset
  • Takt (Clock)

ist letzterer der mit den höchsten Anforderungen an die Signalqualität und Laufzeit. Defizite im Taktnetzwerk führen zu ungewolltem, oft katastrophalen Verhalten der Schaltung. Um dies zu vermeiden, sind besondere Konstuktionsregeln verfasst- und Komponenten für die Taktverteilung in digitalen Schaltungen entwickelt worden. Dabei sind die Methoden für die Signalführung in ASICs und FPGAs im Details durchaus unterschiedlich und unterscheiden sich auch von den Ansprüchen und Methoden bei externer Signalführung auf PCBs:

Grundanforderungen Taktnetzwerk

Der Takt muss möglichst störungsfrei an alle getakteten Bauelemente (FlipFlops, RAMs, IO-Zellen) im IC (ASIC / FPGA) geführt werden und zudem sehr viele Gatter-Eingänge treiben können (bis einige Hunderttausend!). Die Laufzeit vom Eingang des Chips zu jedem Endpunkt des Netzes muss idealerweise exakt gleich sein. Nur so ist gewährleistet, dass alle FlipFlops zum einem möglichst gleichen Zeitpunkt schalten und eine hohe Synchronität gewährleistet ist. Die verbleibenden Differenzen, die unvermeidlich sind, werden von den Tools dahingehend berücksichtigt, dass genügend Zeitreserven vorgesehen werden. Der Laufzeitunterschied zwischen verschiedenen Endpunkten des Taktnetzes wird Skew genannt und liegt bei modernen Digitalschaltkreisen idealerweise unter 100ps.

Um dies zu realisieren, werden eine Reihe von Maßnahmen getroffen:

- An den Eingängen der PLDs, FPGAs und ASICs werden spezielle Eingangsbuffer bereitgestellt, die mitunter durch symmetrische Signalquellen gespeist werden können.

- In PLDs und FPGAs werden unterschiedliche Taktnetze und Taktregionen bereitgestellt. In ASICs werden diese nach Bedarf aufgezogen.

- Es werden globale und mitunter regionale Takttreiber genutzt (in Xilinx FPGA: BUFG).

- Taktnetzwerke als sehr oft als Baumstruktur gestaltet (d.h. gleiche Länge von der Baumwurzel zu jeder Astspitze). Man nennt diese Schaltungstechnik daher auch "Clock Tree". Hierdurch entsteht nicht nur eine begrenzte Last für jeden einzelnen Treiber, sondern auch eine Auffrischung des Signals. Aufgrund der Besonderheiten der Laufzeiten in digitalen Schaltungen ist eine mehrfach mit Treibern unterbrochene Leitung trotz scheinbar mehr Schaltzeiten schneller, als eine einzige lange Leitung.

Clock tree.png

- In ASICs und schnellen FPGAs geht man dazu über, auch intern differenzielle Taktnetze zu verwenden.

- In ASICs und machen FPGAs wird das Taktnetzwerk physikalisch über einfache Inverter weitergeschaltet, wodurch partiell negierte Takte entstehen, was dann schaltungstechnisch berücksichtigt werden kann und muss, indem FFs verwendet werden, die mit negierter Flanke arbeiten, so, wie in besonderen ASIC-Anwendungen zur Balancierung des Strom-Schaltverhaltens auch komplette Schaltungsteile mit invertierter Logik betrieben werden können. Auch in FPGAs sind solche Prinzipien aktuell, werden aber von den Herstellern nicht kommuniziert und sind für den Nutzer auch nicht von Belang. Daher ist es in aller Regel ungünstig bis kontraproduktiv, beim FPGA-design negierte Takte zu verwenden oder FFs mit fallenden Flanken zu kommandieren.

Taktdomänen / Takterzeugung

In fast jeder Digitalschaltung kommt es vor, dass verschiedene Bereiche nicht bei jedem Takt eine Aktion ausführen sollen oder mit erheblich geringeren Taktrate als der Rest der Schaltung arbeiten. Dazu muss aus dem relativ schnellen Systemtakt ein langsamer Takt gewonnen werden. Was auf den ersten Blick recht einfach aussieht, wird im Detail oft falsch gemacht.

Bei externen Schaltungen wird hierzu gerne ein programmierbarer Taktteiler eingesetzt, um abgeleitete Takte zu gewinnen und Chips zu versorgen. Diese bestehen praktisch aus Zählern, welche als Teiler wirken. Diese Arbeitstechnik lässt sich so aber nur bei PLDs und langsam getakteten FPGAs direkt umsetzen, weil die dafür nicht optimierten physikalischen Resourcen (LUTs) in aller Regel unnötige Verzögerungen und Störanfälligkeit ins Spiel bringen.

Daher ist die Verwendung der dedizierten Taktnetze zu bevorzugen und die langsame Ausführung von Aktionen mit enable-Signalen zu regeln. Dort wo dies nicht möglich ist, um z.B. Strom zu sparen, sollten Takte aus PLLs gewonnen- und einzelne Taktregionen benutzt werden, welche dann mitunter Synchronisationsstufen erfordern, um Daten zwischen ihnen zu übergeben.

Geschaltete Takte (Gated Clock)

Dieser Begriff bezieht sich auf geschaltete, also unterbrochene (engl. "gate"), Taktleitungen. Dies kann durch die Verwendung von:

  • Multiplexern (Auswahl zwischen Taktquelle 1 und 2)

oder

  • kombinatorischer Logik (Schaltungsteile werden unter bestimmten Bedingungen vom Takt getrennt)

geschehen.

Taktmultiplexer

Falls ein völliges Abschalten des Taktes wirklich erforderlich ist, z. B. um den Leistungsbedarf zeitweilig zu drosseln, sollte der Takttreiber selbst abgeschaltet werden. Bei Xilinx würde man statt eines BUFG einen BUFGMUX einsetzen. Dieser garantiert durch seinen speziellen Aufbau, daß während des Umschaltens keine Glitches entstehen.

Kombinatorik im Taktpfad

Ein solches Design ist aus zwei Gründen problematisch:

  • es entstehen neben den gewünschten Schaltflanken zusätzliche, ultrakurze Flanken (->Glitches)
  • bei CLK-Teilern hat der langsame Takt eine Phasenverschiebung zum schnellen Takt (-> Skew).
  • bei "gegateten" Takten besitzt der erzeugte Takt eine Phasenverschiebung zum Quell-Takt (-> Skew).

Im ersten Fall können durch die Glitches unerwünschte Schaltaktivitäten an FlipFlops in folgenden Schaltungsteilen ausgelöst werden. Das ist fatal! Schon deshalb ist diese Variante nicht brauchbar. Sie wurde dennoch oft in der Vergangenheit angewendet, weil die relativ langsamen ICs die Glitches gefiltert bzw. ignoriert haben. Doch heute sind CPLDs und FPGAs extrem schnell, dass man mit dieser Methode schnell scheitert.

Im zweiten Fall erfolgt durch Skew eine Verschiebung der Schaltzeiten im anderen Schaltungsteil, die insgesamt weniger Zeitreserve für Signale lässt, die aus dem anderen Schaltungsteil wieder in den ersten Schaltungsteil übergeben werden sollen. In der Vorwärtsrichtung bestehen sogannnte race conditions, d.h. Daten innerhalb der Quelltaktdomäne gelangen eher an FlipFlops der Zieldomäne als Daten, die innerhalb der Zieldomäne erzeugt wurden. Sind Signale zu früh, werden sie gfs. vom falschen Takt übernommen, wodurch das design "komisch" arbeitet, weil scheinbar ein Takt fehlt. Diese Methodik ist ohne Behandlung oder besondere Betrachtung der möglichen Fälle nicht zuverlässig und damit allgemeinen nicht akzeptabel.

In Sonderfällen kann durch einen ausreichende Verschiebung dafür gesorgt werden, daß die Schaltungsteile zueinander korrekt laufen und stabil arbeiten. Dies ist dann einfach zu erreichen, wenn kein Rückwärtspfad der Daten benötigt wird, der im selben Taktzyklus agieren muss.

Asynchrone Taktleitung

Durch diese Methodik der verschobenen Takte kann jedoch auch eine Geschwindigkeitssteigerung erreicht werden, wenn der Takt quasi wie ein Lauffeuer durch den Chip läuft und bei korrektem Timing der Daten (kurze Kombinatorik), jene aus der zukünftigen Zeitebene nie einholt. Damit sind asynchron gepipelinete Architekturen bildbar, die unterhalb der Taktebene arbeiten und lokal die typischen setup-hold-Bedingungen einhalten.

Dies wird üblicherweise aber nur bei ASICs eingesetzt, bei denen ohnehin die Takte und Daten passend lokal optimiert werden. Im Bereich des typischen FPGA-Designs findet man hierzu jedoch bislang nur akademische Lösungen und manuell plazierte Teildesigns bei Sonderlösungen, z.B. auf dem Gebiet der TDC (Time to Digital Converter, schnelle PMW-Generierung z.B. im PICCOLO von TI), da die Tools allesamt auf einem FPGA-weit synchronen Takt und Design aufbauen, dies nicht automatisiert unterstützen und folglich ein Design extrem aufwändig und schwer zu testen ist. Geschwindigkeitssteigerungen lassen sich bei FPGAs daher meist einfacher, sicherer und billiger erreichen, wenn man stärker Pipelining oder Parallelisierung nutzt, ggf. unter Nutzung von mehreren FPGAs.

Derived Clock

Eine geringfügige Verbesserung des Gated Clock erreicht man durch das Anfügen eines FlipFlops hinter den kombinatorischen Dekoder. Durch diese Zwischenspeicherung wird der Takt zumindest frei von Glitches. Wenn im FPGA/CPLD nur ein langsamer Takt gebraucht wird, oder der langsame Schaltungsteil keine logische Verbindung zum schnellen Schaltungsteil hat, dann ist diese Lösung akzeptabel und sicher. Wenn jedoch zwischen dem langsamen Schaltungsteil und schnellen Schaltungsteil Daten oder Steuersignale ausgetauscht werden, dann muss man zu einer anderen Entwurfsmethode greifen.

Clock Enable

Jedes FlipFlop in FPGAs/CPLDs hat einen synchronen Steuereingang namens CE (Clock Enable). Damit kann man festlegen, ob das FlipFlop bei der nächsten Taktflanke neue Daten speichern oder die alten behalten soll. Da es sich um einen synchronen Eingang handelt, ist es vollkommen unkritisch, wenn diese Signal Glitches enthält. Es muss nur im Zeitraum beginnend kurz vor der Taktflanke (Setup Time, Aufbauzeit) bis kurz danach (Hold Time, Haltezeit) stabil anliegen. Eine Verschiebung dieses Signals zum Takt ist auch unkritisch, denn jedes normale Steuersignal ist phasenverschoben zum Takt (Schaltzeit der FlipFlops, Durchlaufzeit der Logik, Laufzeit der Verdrahtung (Routing)). Das CE-Signal kann von der Entwurfssoftware wie ein normales Steuersignal behandelt werden und vereinfacht damit erheblich die automatische Analyse der maximalen Schaltfrequenz (Timing Analyses).

Beispiele

Im nachfolgenden Bild sind alle drei Typen von Takt kurz skizziert. Der schnelle Takt treibt einen 4Bit Zähler (CNT1). Dessen Ausgänge werden über eine UND-Gatter (Gate1) kombinatorisch verknüpft. Der Ausgang des UND-Gatters ist nur dann HIGH, wenn alle Eingänge HIGH sind. Das ist nur einmal alle 16 Takte der Fall, wenn der Zählerstand binär 1111 erreicht ist. Dieses Signal als Takt zu verwenden wäre sträflich, denn es ist ein Gated Clock. Wenn er jedoch noch einmal mittels FlipFlop (FF1) zwischengespeichert wird ist es ein Derived Clock. Der beste und sinnvollste Weg ist jedoch die Verwendung des CE-Eingangs der FlipFlops (FF2) wie es ganz unten im Bild dargestellt ist.

verschiedene Taktteiler


Umsetzung in VHDL

-- Die Verwendung von "Clock Enable" in VHDL
-- die Signale clk und ce sind hier natürlich nur Beispiele
-- es kann dafür jeder beliebige Signalname verwendet werden

-- Das hier muss in die Signaldeklaration zwischen
-- achitecture ...   und  begin

constant cnt_div: integer:=16;                  -- Teilerverhältnis
signal   cnt:     integer range 0 to cnt_div-1; -- Zähler für Teiler
signal   ce:      std_logic;

-- die Prozesse logischerweise nach begin der Architecture

-- Prozess mit langsamen Clock Enable

process(clk)
begin
  if rising_edge(clk) then
    if ce='1' then

    -- Aktionen hier einfügen, welche mit langsamen Takt laufen    

    end if;
  end if;
end process;

-- Clock Enable Generator

process(clk)
begin
  if rising_edge(clk) then
    if cnt=cnt_div-1 then
      ce  <= '1';
      cnt <= 0;
    else
      ce  <= '0';
      cnt <= cnt +1 ;
    end if;
  end if;
end process;

Takterzeugung mit PLLs

Clock Skew

Mithilfe der clock skew Einstellung kann ein Synthesewerkzeug angewiesen werden, den Zeitpunkt der Taktflanke entsprechend den Erfordernissen der Schaltungsverzögerungen einzustellen. Dies schafft mehr Reserven. Üblicherweise werden die Takte im FPGA so hingeschoben, dass sie synchron mit dem Erzeugertakt liegt, weil die damit erzeugten Daten am Ausgang ebenfalls wieder zur Taktphase passen und in der Regel auf diese Weise auch synchrone Datenbusse, die mit diesem Takt ankommen, leicht eingesampelt werden können.

Phase Shift

Innerhalb der FPGA-PLLs können mehrere Takte von demselben Eingangstakt abgeleitet werden, die eine feste Verschiebung aufweisen. Diese Verschiebung ist das Hauptwerkzeug, um den benötigten Zeitpunkt für einen steigende Flanke eines internen Taktes im Bezug zu extern eingehenden Daten herzustellen und Laufzeiten im FPGA und den IO-Bänken auszugleichen.