Reset für FPGA/CPLD
Wie viele digitale Schaltungen mit FFs benötigt auch ein FPGA-Design oft einen definierten Anfangszustand, in den es per Reset zurückgesetzt werden soll. Je nach Art, Verteilung und Auslöser kann beim Reset unterschieden werden zwischen:
- synchroner, asynchroner Reset (FF mit synchronen oder asynchronen Set/Reset Eingängen)
- High oder Low-aktiver Reset (Der Resetzustand wird mit einer '1' oder '0' eingeleitet. Der Reset ist nie Flankengesteuert (?).
- Reset nach PowerUp, Abschluss FPGA-Laden, stabiles Taktsignal, externer Resetquelle oder Nutzer (Software) Auslösung.
- Verteilt über allgemeine Routing-Ressourcen oder globales Set/Reset-Netzwerk
Implementierung von FlipFlops/Registern mit verschiedenen Resetmöglichkeiten
Kein Reset
Nach dem Laden befindet sich ein FPGA immer in einem definierten Zustand, d.j. alle Speicherelemente (FFs, Schieberegister, RAM-Zellen) sind mit einem festen Wert geladen. Dieser ist bei den meisten FPGAs logisch 0. Es bedarf also für das erstmalige Setzen der Zellen keiner zusätzlichen Resetschaltung. Werden für Register oder Vektoren besondere Initialwerte benötigt, können diese Init-Werte bei Altera und Xilinx durch eine ausdrückliche Zuweisung direkt bei der Signal-Deklaration festgelegt werden:
signal is_0_after_FPGA_config: std_logic := '0';
signal is_1_after_FPGA_config: std_logic := '1';
Manche rudimentären Logikelemente (bei Xilinx: shift register SR16E) sind nicht mit einem Reset zu versehen und damit nicht einsetzbar, weswegen die Synthese gfs mehr Aufwand betreiben muss, um diese Funktion darzustellen. (siehe Beitrag im Forum).
Der Initialwert für Block-RAM-Speicher kann in VHDL, im ucf oder durch Konfigurationsfiles (Coregen, EDK) definiert werden. Falls das nicht erfolgt, kann eine Ladeschaltung verwendet werden, welche die Block-RAMS einmalig belegt.
Physikalisch kann das Initialisieren jederzeit als Reset verwendet werden, indem die Config-Leitung elektrisch bedingt wird. Der FPGA wird dann wieder beladen.
Asynchroner Reset
In speziellen Fällen, wird auch bei FPGAs der traditionelle asynchrone Reset verwendet:
process(clk, reset)
begin
if reset = '1' then
-- Initialisierung der Register
elsif rising_edge(clk) then
-- Kombinatorik
end if;
end process;
Bei ASICs ist der areset i.d.R. unverzichtbar, da diese nicht standardmäßig mit einem Initialwert geladen werden können. Bei FPGA-Designs wird er nur benötigt, wenn diese in einen ASIC überführt werden wollen. Bei reinen FPGA-Designs wird er meistens nicht verwendet, da er zeitlich kaum einen Vorteil gegenüber dem synchronen Reset bringt, weil FPGAs aufgrund des Ladens ohnehin eine geraume Zeit inaktiv und damit undefiniert sind.
Der aReset kann sogar zu Problemen führen, wenn die fallenden Flanke des Resetsignals zu einem ungünstigen Zeitpunkt kommt (Siehe Witepaper 272 bei Xilinx). Je nach Logikdesign und der dadurch bedingten Auswirkung der Resetrücknahme, ist damit u.U. eine Verlängerung des Resetsignales so durchzuführen, dass das Löschen des Signals in jedem Falle außerhalb des Bereiches möglicher Flankenwechsel des Systemtaktes erfolgen.
Im Regelfall geschieht dies durch eine externe Synchronisation, z.B. einen Prozessor oder einen anderen FPGA, der auf derselben Frequenz bzw. einer Frequenz mit stets bekannter Phase läuft.
Für FPGAs und auch vielen PLDs ist es daher sinnvoller, allein einen synchronen Reset zu benutzen. Dabei ist darauf zu achten, dass das synchrone Resetsignal eine genügend lange Periode besitzt, um erfasst zu werden.
Synchroner Reset
process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
-- Initialisierung der Register
else
-- Kombinatorik
end if;
end if;
end process;
Die Nutzung eines synchronen Resets, erfolgt durch das Eintakten / Einsynchronisieren des externen Resetsignals unbekannter Phasenlage und Länge, sodaß sichergestellt ist, daß der Resetimpuls überall innerhalb der verarbeitenden clock domain gleichzeitg anliegt und eine passende Länge hat. Wird dies unterlassen, so kann aufgrund der Laufzeiten des Resetsignals und des Taktes im FPGA der Flankenwechsel des Resets von einem FF gerade erkannt und von einem anderen FF gerade verpasst werden, sodaß der Reset von unterschiedlichen Schaltungsteilen in zwei verschiedenen Taktperioden verarbeitet wird und die Schaltungsteile so "auseinanderlaufen".
Die Verwendung eines synchronen Resets erfordert u.U. mehr Resourcen. In Einzelfällen können die sich ergebenden Strukturen jedoch auch durch die Synthese mit anderen Schaltungsteilen und Anforderungen zusammengefasst werden.
Resetgenerierung
Folgend ein Beispiel einer internen Resetschaltung (auch wenn dergleichen heute im FPGA-Bereich kaum noch nötig ist), die einen 16 Takte langen Reset-Impuls erzeugt:
--xilinx spartan3
--reset using a 16bit shift register
gen_dcm_srl : SRL16E
GENERIC MAP (INIT => X"FFFF") -- a 16 clk long '1' -pulse
PORT MAP (
Q => rst_dcm_geseco, --the reset signal for the rest of the design
A0 => '1', --determines length Shiftreg (15+1 bit)
A1 => '1',
A2 => '1',
A3 => '1',
CE => Locked_DCM_MBSYS, --release reset pulse (here when clock is stable)
CLK => CLK96, --its a synchronous reset
D => '0'); -- non-reset is '0' (high active reset)
Logische Resets
Neben dem physikalischen Reset, der meist alle FFs gleichzeitig in einen Startzustand versetzt, benötigen viele Applikationen einen logisch neutralen Zustand mit z. B. inaktiven Ausgängen, wodurch teilweise weitere Resetzustände definiert werden müssen. Meist wird hier eine Art Warmstart-Zustand definiert. Auch ist es oft wünschenswert, dass nur Schaltungsteile neu gestartet werden, wenn Fehlfunktionen detektiert wurden, oder die Schaltung in Bereitschaft gesetzt werden soll, während andere essenzielle Funktionen aufrechterhalten werden sollen. Pipelines, algorithmische Rechenblöcke und untergeordnete state machines sind z. B. solche Schaltungsteile.
Der logische Reset wird meist mit dem synchronen Reset zusammengefasst, sodass eine Schaltung einmal startet, dann als Überwacher agiert und bei Bedarf einzelne Schaltungen gesetzt und rückgesetzt werden, falls diese Fehlfunktionen aufweisen.
Resourcenbedarf
Aufgrund der besonderen Struktur von FPGAs, alle Logikfunktionen auf LUTs herunterzubrechen, kann der Einbau eines unnötigen Resets durchaus zu einem signifikanten Mehrverbrauch an Resourcen führen. Umgekehrt ist der synchrone Reset auf 0 oft schon durch anderweitig implementierte Funktionen der LUTs realisiert, d.h. eine Funktion, welche den Eingang eines Registers setzen kann, ist oft schon in der benötigten Form vorhanden und hat auch bereits statistisch den richtigen Wert. Bei der Optimierung der Schaltung geht damit die Anforderung dieses zusätzlichen enables oft im pool der realisierten Gleichungen "unter".
Siehe auch
Beiträge zum Thema im FPGA-Bereich des Forums:
- Effizienz unterschiedlicher Resets: http://www.mikrocontroller.net/topic/380526
- VHDL richtig beschreiben: http://www.mikrocontroller.net/topic/108606
- weitere Beiträge (Suche) : http://www.mikrocontroller.net/forum/9?filter=reset*