Ich möchte in einem getakteten Prozess ein externen signal einlesen,
welches als trigger für einen ADC im fpga dient. Dieser trigger kommt
von extern und ist asynchron. Der Prozess läuft mit 60MHz. Muss ich
solche Signale synchronisieren? Im schlimmsten Fall kann doch passieren,
dass der etwas zu spät erkannt wird, was mir egal ist, denn der trigger
ist deutlich langsamer als der ADC.
Du musst vor allem sicherstellen, dass das externe Signal nur mit genau
einem Register in die 60 Mhz Taktdomäne übernommen wird. Zwei Register
direkt hintereinander schaden auch nicht. Metastabilität ist aber nicht
wirklich ein relevantes Problem. Erst nach dem Samplen kannst du das
synchronisierte Signal an beliebig viel weitere Logik verteilen.
Welchen FPGA verwendest Du?
rossi schrieb:> Metastabilität ist aber nicht> wirklich ein relevantes Problem.
Metastabilität hat mich schon zu viele Stunden bei der Fehlersuche
gekostet, als dass ich diese Aussage noch unterstützen könnte. Es ist
'Best Practice', asynchrone Signale immer über zwei Registerstufen
einzusamplen. Das kostet praktisch keine Ressourcen und das Thema MS ist
damit statistisch für die nächsten 100000 Jahre vom Tisch.
Vancouver schrieb:> Metastabilität hat mich schon zu viele Stunden bei der Fehlersuche> gekostet, als dass ich diese Aussage noch unterstützen könnte.
Allerdings wird richtige Metastabilität eben oft mit fehlendem
Einsynchronisieren verwechselt. Heute sind Flipflops im FPGA nach ein
paar ns sicher irgendwo hingekippt und nicht mehr zwischen 0 und 1
floatend:
http://www.lothar-miller.de/s9y/archives/62-Testaufbau-Metastabilitaet.html> Es ist 'Best Practice', asynchrone Signale immer über zwei> Registerstufen einzusamplen.
Das Hauptproblem (das hier auch immer wieder aufschlägt) sind fast
ausschließlich solche Effekte mit unterschiedlichen Laufzeiten von nicht
synchronisierten Eingangssignalen im FPGA:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Und die Ausrede: "Ich habe da gar keine FSM!" fällt dann meist ganz
schnell, wenn man sich vergegenwärtigt, dass auch schon ein simpler
Zähler ein Zustandsautomat ist...
rossi schrieb:> dass das externe Signal nur mit genau einem Register in die 60 Mhz> Taktdomäne übernommen wird.
Und weil sich da ggfs. der Synthesizer mit per Register-Duplication doch
Freiheiten herausnimmt, sind 2 Register hintereinander der Weg zum Ziel.
Denn dann wird das erste FF sicher nicht dupliziert und es gibt nur 1
Laufzeit bis zum 1. Register. Ab da kann dann beliebig dupliziert
werden.
Philipp S. schrieb:> Ich möchte in einem getakteten Prozess ein externen signal einlesen
Du denkst in Software. Ein Prozess "liest" kein Signal ein. Sondern ein
Prozess beschreibt bestenfalls ein Flipflop, das den Zustand eines
externen Signals abhängig von einem internen Takt speichern soll.
Lothar M. schrieb:> Allerdings wird richtige Metastabilität eben oft mit fehlendem> Einsynchronisieren verwechselt.
Den Eindruck habe ich auch. Jeder bachelor der mal etwas von FPGAs
gehört hat, bekommt von seinem schlecht informierten
Was-bin-ich-so-stolz-dass-ich-mich-Professor-nennen-darf Lehrmeister an
der dualen Hochschule etwa von Meta erzählt und findet es toll, dass er
es bekämpfen kann.
Dabei wird verkannt, dass es oft falsch einsynchronisierte Busse und
Signalgruppen sind, deren Zustand durch ein scheinbar technisch
richtiges- aber aus Logiksicht unzureichendes Eintakten zerpflückt wird.
Schlecht, wenn man nicht in der Lage ist, Problemstellungen zu erfassen
und einzuordnen.
> Heute sind Flipflops im FPGA nach ein> paar ns sicher irgendwo hingekippt und nicht mehr zwischen 0 und 1> floatend
"Picosenkunden" wolltest du sicher schreiben. Nano wäre etwas langsam
:-)
Ja, vermutlich ist die fehlende Synchronisation meistens die
Fehlerursache. Aber wir hatten vor einigen Jahren im Labor mal echte
Metastabilität fabriziert, auf einem Virtex-5, der CPU-Steuersignale in
eine 100MHz-Domain einsamplen sollte. Hin und wieder erschien satt des
Signalzustandes auf dem Logi völlig wirres Zeug und der FPGA verhielt
sich teilweise, sagen wir... indeterministisch und die Stromaufnahme
stieg drastisch an. Eine FSM blieb z.B. in einem ungültigen Zustand
hängen usw. Blieb nur der Reset. Das Problem verschwand, nachdem ich
meine Hausaufgaben gemacht und alle Signale 2-stufig einsynchronisiert
hatte.
Das Problem mit der Metastabilität ist, dass sie sich, auch wenn sie nur
kurz dauert, mit einer gewissen Wahrscheinlichkeit in die nächste Stufe
überträgt und dann zur Logik-Demenz führt.
Vancouver schrieb:> Das Problem mit der Metastabilität ist, dass sie sich, auch wenn sie nur> kurz dauert, mit einer gewissen Wahrscheinlichkeit in die nächste Stufe> überträgt und dann zur Logik-Demenz führt.
"Kurz" sind aber wirklich nur Nanosekunden oder noch viel weniger. Schon
1997 hat Xilinx bei damals aktuellen FPGAs in 0.5 Mikron Technik keine
Probleme bei < 100 MHz Takt gesehen. [XAPP 094 November 24, 1997
(Version 2.1)] Da war der metastabile Zustand lange aufgelöst, bevor die
nächste Taktflanke kommt.
Das echte Problem ist die automatische Register-Duplizierung, die Lothar
M. angesprochen hat und das selbst bei trivialen Sachen das asynchrone
Signal einen Fanout größer 1 hat.
1
process(clk)
2
begin
3
ifrising_edge(clk)then
4
if(trigger_async='1')then
5
next_adc_sample<=adc_data(15downto0);
6
endif;
7
endif;
8
endprocess;
Sowas kann schon schief gehen, wenn trigger_async zu unterschiedlichen
Zeiten an den einzelnen Registern für die Bits ankommt.
Fuer externe (!) Triggereingaenge nehme ich gerne sowas (allerdings
architekturabhaengig):
1
entity pulsestrobe is
2
port (
3
trigger : in std_ulogic;
4
strobe : out std_ulogic;
5
en : in std_ulogic;
6
clk : in std_ulogic
7
);
8
end entity pulsestrobe;
9
10
architecture myhdl_emulation of pulsestrobe is
11
-- Local type declarations
12
-- Signal declarations
13
signal pset : std_ulogic := '0';
14
signal pout : std_ulogic := '0';
15
signal clk_fb97 : std_ulogic;
16
signal reset : std_ulogic;
17
begin
18
19
trigger_strobe:
20
process(clk_fb97, reset)
21
begin
22
if reset = '1' then
23
pset <= '0';
24
elsif rising_edge(clk_fb97) then
25
if (en = '1') then
26
pset <= '1';
27
end if;
28
end if;
29
end process;
30
31
trigger_ff:
32
process(clk)
33
begin
34
if rising_edge(clk) then
35
pout <= pset;
36
end if;
37
end process;
38
clk_fb97 <= trigger;
39
reset <= pout;
40
strobe <= pout;
41
end architecture myhdl_emulation;
Nimmt allerdings auch jeden Glitch mit und 'verschwendet' allenfalls
etwas Clock-Routing-Resourcen, somit ist es nicht optimal portabel. MS
kann natuerlich von pset -> pout noch auftreten.
Ansonsten moechte man vielleicht sowieso entprellen, damit hat sich
obige Thematik erledigt.
Mach dir doch nicht ins Hemd wegen Trigger glitches. Da passiert nichts
und da muss auch nichts einsynchronisiert werden. EInen Trigger in einem
getakteten Prozess zu nutzen ist vollkommen in Ordnung.