Forum: FPGA, VHDL & Co. 4x /Sec Frequenzmessung, bug im code?


von Max (stm3222)


Lesenswert?

Hallo

Ich möchte eine frequenz zählen(messen). Dazu nutze ich ein 100MHz clk 
und zähle die positiven Flanken über 25mio referenzclks. Das ergebnis 
wird dann um 2 bits geschoben um die korrekte Frequenz zu erreichen.

Nun habe ich folgende Probleme:
1. Die frequenzmessung weicht permanent ca 5% von der erwartung ab 
(Quarz ist 50ppm)? (alle identische Abweichung)
2. Jeder ca. 20. Wert weicht um 15% ab (einzelne Ausreisser)?

Code:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity Freqcount is
6
    port (
7
        clk:            in std_logic;
8
        rst_n:          in std_logic;
9
        data_i:       in std_logic; 
10
        countm:         out std_logic_vector(30 downto 0)
11
    );
12
end entity;
13
14
15
architecture rtl of Freqcount is
16
17
18
signal cnt:       std_logic_vector(27 downto 0);
19
signal cnt_time:   std_logic_vector(27 downto 0);
20
signal data_i_old: std_logic;
21
begin
22
    process (clk, rst_n)
23
    begin
24
      if rst_n = '0' then
25
      cnt_time <= (others => '0');
26
      cnt <= (others => '0');
27
      countm <= (others => '0');
28
      data_i_old <= '0';
29
    elsif rising_edge(clk) then
30
      if(to_integer(unsigned(cnt_time)) >= 25_000_000) then
31
        countm <= "0" & cnt & "00";
32
        cnt_time <= (others => '0');
33
        cnt <= (others => '0');
34
      else
35
        cnt_time <= std_logic_vector(to_unsigned(to_integer(unsigned(cnt_time))  +1,28));            
36
        if(data_i_old = '0' and data_i = '1') then
37
          cnt <= std_logic_vector(to_unsigned(to_integer(unsigned(cnt)) + 1, 28));
38
        else
39
          cnt <= cnt;
40
        end if;
41
      end if;
42
      data_i_old<=data_i;
43
    end if;
44
    end process;
45
end architecture;

: Bearbeitet durch Moderator
von Lars (rezyy)


Lesenswert?

Moin,

ein paar Hinweise und Fragen:

1. Du synchronisierst scheinbar nicht sauber ein (anhand dieses Moduls).
2. Weshalb rechnest du nicht direkt mit unsigned?
3. Der korrekte Endwert sollte >= 24_999_999 sein.
4. Was für eine Frequenz willst du messen? Liegt am Eingang ein Rechteck 
einer bestimmten Frequenz an oder einfach ein "analoges" sinusoides 
Signal, was über den Eingang stumpf auf 1 bit quantisiert wird? Bei 
langen Flanken solltest du zunächst analog etwas rect-förmiges erzeugen, 
um sauber zu zählen.
5. Für einen Zähler bis 25e6 reichen 25 bits.
6. Wenn du rising edges zählst, reichen dann für den Flankenzähler auch 
24 bit.

von Max (stm3222)


Lesenswert?

Danke für die Antwort.

1. Hmm sieht mir gem. Signaltap eigentlich gut aus, auch die tr/tf des 
signals ist schnell bezogen auf die 100MHZ clk. Aber ja ist direkt der 
pineingang der gezählt wird ohne weitere constraints.

2. Ich mag std_logic_vector :-)
3. Ok, danke für den Tipp. Ist korrigiert.
4. DC-5MHZ Rechteck, tr/tf ca. jeweils 5ns
5. Danke für den Tipp. Fittet so ohne Slack Probleme - kann ich lassen
6. Ok, platz ist genügend vorhanden.

von Lars (rezyy)


Lesenswert?

Moin,

ich gehe davon aus, dass die DC - 5 MHz dann absolut unsynchronisiert 
zur clock sind.. Naja, dann musst du auch korrekt einsynchronisieren, 
was du nicht machst. Bei den tr/tf und max. 5 MHz würde ich mind. einen 
3-stufigen Synchronisierer verwenden, gerne auch mehr. Stell dir vor, du 
tastest alle 10ns ab und allein die tr/tf sind schon 5ns. Da sind 
Metastabilitäten sehr wahrscheinlich, insbesondere bei 5 MHz.

Da du die rising edge detektieren willst, bräuchtest du im Falle eines 
3-stufigen Synchronisierers 4 Flipflops, da die Signale in dem Falle 
erst hinter dem 3. FF genutzt werden sollten. Die ersten 3 Flipflops 
sollten auch mit einem constraint oder Attribut ASYNC_REG (Xilinx) 
belegt werden, damit das sauber ist.. Anderenfalls ein max_delay 
constraint. So wie du das hier machst, können die FFs stets kippen und 
dein Ergebnis ist nicht sauber.

von Max (stm3222)


Lesenswert?

L. schrieb:
> ich gehe davon aus, dass die DC - 5 MHz dann absolut unsynchronisiert
> zur clock sind..

korrekt

L. schrieb:
> Bei den tr/tf und max. 5 MHz würde ich mind. einen
> 3-stufigen Synchronisierer verwenden, gerne auch mehr. Stell dir vor, du
> tastest alle 10ns ab und allein die tr/tf sind schon 5ns. Da sind
> Metastabilitäten sehr wahrscheinlich, insbesondere bei 5 MHz.

Überrascht mich etwas, aber alles deutet darauf hin, dass ich genau 
dieses Problem habe. Nur zum Verständnis:

Das Eingangssignal durch einige in reihe geschaltete FF laufen lassen? 
Dabei ist jedes dieser FF mit meinem Systemtakt (100MHZ) getaktet?

L. schrieb:
> Da du die rising edge detektieren willst, bräuchtest du im Falle eines
> 3-stufigen Synchronisierers 4 Flipflops, da die Signale in dem Falle
> erst hinter dem 3. FF genutzt werden sollten.

Ernst gemeinte Frage: Wieso genau ist dies nötig? (FF setup und hold 
time sind doch äusserst gering)

L. schrieb:
> Die ersten 3 Flipflops
> sollten auch mit einem constraint oder Attribut ASYNC_REG (Xilinx)
> belegt werden, damit das sauber ist.. Anderenfalls ein max_delay
> constraint. So wie du das hier machst, können die FFs stets kippen und
> dein Ergebnis ist nicht sauber.

Wie du aus meiner obigen Frage sicher entnehmen kannst habe ich 
Wissenslücken zum Thema constraints. Zwar wurde mir deren Wichtigkeit 
immer eingetrichtert aber wie/was genau ist mir bis heute unklar.
Wie mache ich das bei Altera? Sollte ich das bei allen asynchronen 
inputs machen? Wie genau constraine ich ein asynchronen GPIO Input?

von Max (stm3222)


Lesenswert?

Max schrieb:
> Das Eingangssignal durch einige in reihe geschaltete FF laufen lassen?
> Dabei ist jedes dieser FF mit meinem Systemtakt (100MHZ) getaktet?

Kleiner Nachtrag: Habe nun 6 FF genau so eingesetzt (ohne constraint 
parameter). Das Problem ist nun weg und die Sache läuft hervorragend. 
Daher war dein Tipp schon mal gold Wert.

Die Frage weshalb dies ohne diese FF derartig schief gieng bleibt 
natürlich.

von Rick D. (rickdangerus)


Lesenswert?

Max schrieb:
> Die Frage weshalb dies ohne diese FF derartig schief gieng bleibt
> natürlich.
Alle Eingangssignale, die an mehr als einer Stelle im FPGA gebraucht 
werden, müssen durch ein (oder mehrere) FFs gehen. Sonst sieht bei einem 
Flankenwechsl eine Stelle schon das neue Signal, während die andere noch 
den alten Zustand sieht. Das FF muß - wie du richtig erkannt hast - mit 
dem (Haupt-)Systemtakt arbeiten.

Das Suchstichwort für weitere Informationen ist 'clock domain crossing'.

von Klar P. (Firma: Reinigungsmittel) (klar_putz)


Lesenswert?

ich bin mir nicht sicher, ob da nicht die Zeile zur Generierung des FF 
zur Flankenerkennung um eine Zeile verrutscht ist. Sieht jedenfalls 
seltsam aus.
1
      end if;              -- Abschluss von elsif rising_edge(clk) then
2
      data_i_old<=data_i;  -- ist das noch getaktet??
3
    end if;                -- Abschluss von if rst_n = '0' then
4
    end process;

Ich wurde die Zeile schon aus Gründen der Übersichtlichkeit nach oben 
gleich nach der taktflanke schreiben.


Was sagt der Synthese-report ?

von Lars (rezyy)


Lesenswert?

Max schrieb:
> Das Eingangssignal durch einige in reihe geschaltete FF laufen lassen?
> Dabei ist jedes dieser FF mit meinem Systemtakt (100MHZ) getaktet?

Korrekt. Allerdings reicht das alleine für einen korrekte 
Synchronisation nicht aus. Die paths zwischen den FFs müssen auch 
vergleichsweise kurz sein, damit die Metastabilitäten aufgelöst werden 
können. Dafür ist das zusätzliche constraint notwendig. Wenn man das 
nicht macht, kann das Tool lange paths einbauen, wodurch keine Zeit zur 
Auflösung der Metastabilitäten mehr übrig bleibt. Dann kann der 
Einsynchronisierer failen. Ich habe schon oft gesehen, dass sehr viele 
FPGA-Entwickler das nicht wissen..

Max schrieb:
> Ernst gemeinte Frage: Wieso genau ist dies nötig? (FF setup und hold
> time sind doch äusserst gering)

Die tr/tf des Eingangssignals sind lang. Wenn dein FF in diesem Bereich 
abtastet, ist es metastabil, auch wenn die setup&hold des FFs 
vergleichsweise kurz ist.

Max schrieb:
> Wie mache ich das bei Altera? Sollte ich das bei allen asynchronen
> inputs machen? Wie genau constraine ich ein asynchronen GPIO Input?

Warum du constraints brauchst: siehe oben. Bei Xilinx wäre es
1
set_max_delay -datapath_only
 Bei Altera gibt es kein ASYNC_REG und auch das
1
-datapath_only
 nicht. Ich meine, dass Altera ein
1
set_data_delay
 hat, womit du das setzen kannst.

Max schrieb:
> Kleiner Nachtrag: Habe nun 6 FF genau so eingesetzt (ohne constraint
> parameter). Das Problem ist nun weg und die Sache läuft hervorragend.
> Daher war dein Tipp schon mal gold Wert.

Das ist schon deutlich besser, das constraint ist trotzdem notwendig. 
Wenn dein FPGA mal voll sein sollte und du neu synthetisierst, kann es 
sonst wieder failen. Deshalb das constraint.

von Lars (rezyy)


Lesenswert?

Klar P. schrieb:
> Ich wurde die Zeile schon aus Gründen der Übersichtlichkeit nach oben
> gleich nach der taktflanke schreiben.

Das ist da schon funktionell richtig. Ich würde das Einsynchronisieren 
aber sogar in einen eigenen Prozess schmeißen..

von Klar P. (Firma: Reinigungsmittel) (klar_putz)


Angehängte Dateien:

Lesenswert?

Lars schrieb:
> Klar P. schrieb:
>> Ich wurde die Zeile schon aus Gründen der Übersichtlichkeit nach oben
>> gleich nach der taktflanke schreiben.
>
> Das ist da schon funktionell richtig.

Mutige Ansage, aber was sagt Synthese-Report und Simulation?

> Ich würde das Einsynchronisieren
> aber sogar in einen eigenen Prozess schmeißen..

Das ist nicht das Einzige, das man an der Code-struktur/-style ändern 
sollte.

Ich hab das Ganze mal durch den beautifier gejagt und angehangen.
IMHO sollte man jeden counter extra beschreiben und sich dabei an die
Standards für VHDL-counter halten.

: Bearbeitet durch User
von Lars (rezyy)


Lesenswert?

Klar P. schrieb:
> Mutige Ansage, aber was sagt Synthese-Report und Simulation?

Die Aussage ist nicht mutig, ich brauche dafür keine Synthese oder 
Simulation. Die Zeile ist ganz klar noch getaktet und erzeugt das D-FF, 
da das "end if;" darunter direkt zum "elsif rising_edge(clk) then" 
gehört.

von Max (stm3222)


Lesenswert?

Danke für die Antworten

Nun ist es so dass aus Latenzgründen nicht immer mehrere FF 
hintereinander geschaltet werden können. Giebts da neben mit constraints 
auf kurze Laufzeiten noch eine andere Lösung welche ohne zusätzliche 
Delays auskommt?

Das set_data_delay müsste ich dann auf jedes io signal definieren. Was 
sind angemessene constraintparameter für ein Cyclone 3 (Cyc10 LP)?

Ich verstehe immer noch nicht ganz wie Metasabilitäten eine derartige 
Abweichung erzeugen konnten. Auch wenn der Zustand unbestimmt ist in 
einem einzelnen fall - würde dies der Zählerstand im ungünstigsten Fall 
um 1 verfälschen. Eine abweichung von 10% würde ja bedeuten dass 
mindestens 10% der Pulse metastabil waren, dies ist aber mit den 
gegebenen tr/tf bei einem Signal von 5MHZ eigentlich nicht möglich.

Nur damit ich das korrekt verstehe: Ihr lässt jeden asynchronen GPIO 
input ersmal durch einige FF laufen? (Wieviele?)

von Klar P. (Firma: Reinigungsmittel) (klar_putz)


Lesenswert?

Lars schrieb:
> Klar P. schrieb:
>> Mutige Ansage, aber was sagt Synthese-Report und Simulation?
>
> Die Aussage ist nicht mutig, ich brauche dafür keine Synthese oder
> Simulation. Die Zeile ist ganz klar noch getaktet und erzeugt das D-FF,
> da das "end if;" darunter direkt zum "elsif rising_edge(clk) then"
> gehört.

Jetzt wirds allmählich übermütig, was sagt der Synthesereport?

Abgesehen davon ist es kein  D-FF, sondern eines mit (unnötigen) 
asynchronen reset. Also ein FDC, kein FD.

> Nur damit ich das korrekt verstehe: Ihr lässt jeden asynchronen GPIO
> input ersmal durch einige FF laufen? (Wieviele?)

Zwei reichen normalerweise und weil in den (FPGA-) PAD's sowieso 
FF-Primitive sind, kriegste das erste quasi geschenkt.
Falls das GPIn mehr als ein Folge-FF treibt (bspw. FSM) ist das 
synchronisieren quasi verpflichtend. Man kann u.U. (Gray encoded) darauf 
verzichten, so wird es gern bei den FIFO-Macros gemacht. OK, das ist 
dann aber kein asynchroner Input, nur das übliche interne CDC.

https://www.intel.com/content/www/us/en/docs/programmable/683522/18-0/gray-code-counter-transfer-at-the-clock.html

: Bearbeitet durch User
von Rick D. (rickdangerus)


Lesenswert?

Max schrieb:
> Ihr lässt jeden asynchronen GPIO
> input ersmal durch einige FF laufen?
Ja.

> (Wieviele?)
Zwei.
Mit Flankenerkennung sind's drei.

von Max (stm3222)


Lesenswert?

Rick D. schrieb:
>> (Wieviele?)
> Zwei.

Klar P. schrieb:
> Zwei reichen normalerweise und weil in den (FPGA-) PAD's sowieso
> FF-Primitive sind, kriegste das erste quasi geschenkt.

Also im user Design noch eines? (Da HW bedingt eines ohnehin immer 
vorhanden ist)

von Lars (rezyy)


Lesenswert?

Klar P. schrieb:
> Jetzt wirds allmählich übermütig, was sagt der Synthesereport?

Herrje.. 1. Sein Problem hat sich schon gelöst. Wäre das kein FF nach 
Synthese, hätte er ganz andere Probleme. 2. Für diesen Popelkram 
benötigt man nun echt keine Simulation, um zu verstehen, dass es 
getaktet sein wird. Es kann lediglich wegoptimiert werden, falls nicht 
weiter genutzt.

Klar P. schrieb:
> Abgesehen davon ist es kein  D-FF, sondern eines mit (unnötigen)
> asynchronen reset. Also ein FDC, kein FD.

Und wie es immer noch ein D-FF ist. Ein D-FF mit asynchronem reset 
bleibt noch immer ein D-FF, nur mit weiterem Input. Nur weil die 
Hersteller für jede Art von FF einen eigenen Namen gewählt haben (was 
sie machen, damit man die Primitiven direkt unterscheiden kann, was auch 
gut ist), heißt das nicht, dass es eine ganz neue Art von FF ist.

Immer diese hochnäsigen Kommentare..

Max schrieb:
> Nur damit ich das korrekt verstehe: Ihr lässt jeden asynchronen GPIO
> input ersmal durch einige FF laufen? (Wieviele?)

Ja, jedes asynchrone Signal muss eingetaktet werden. 2 FFs sind das 
Minimum. Die Anzahl an benötigten FFs hängt auch vom Eingangssignal ab 
und welche MTBF man erreichen möchte/muss. Dazu gibt es viel 
Dokumentation. Einfach mal etwas einlesen.

Max schrieb:
> Nun ist es so dass aus Latenzgründen nicht immer mehrere FF
> hintereinander geschaltet werden können. Giebts da neben mit constraints
> auf kurze Laufzeiten noch eine andere Lösung welche ohne zusätzliche
> Delays auskommt?

Wie gesagt, 2 sind Minimum. Wenn du mit der daraus resultierenden MTBF 
für das zu erwartenden Eingangssignal leben kannst, dann ist das OK. 
Ansonsten musst du für ein sauberes Design mehr FFs nutzen. Die 
constraints verkürzen nicht das Delay, sondern nur nets. Die FFs sind 
noch immer getaktet und jedes FF fügt ein Delay eines clock cycles 
hinzu.

Max schrieb:
> Das set_data_delay müsste ich dann auf jedes io signal definieren. Was
> sind angemessene constraintparameter für ein Cyclone 3 (Cyc10 LP)?

Das constraint muss für jeden path/net zwischen den FFs in der 
Synchronisiererstufe gesetzt werden. Bei 10ns wäre ein typischer und 
guter Wert 2ns path delay, wenn das Tool so das P&R schafft. Dann 
bleiben 8ns, um die Metastabilität in jeder stage aufzulösen.

Max schrieb:
> Ich verstehe immer noch nicht ganz wie Metasabilitäten eine derartige
> Abweichung erzeugen konnten. Auch wenn der Zustand unbestimmt ist in
> einem einzelnen fall - würde dies der Zählerstand im ungünstigsten Fall
> um 1 verfälschen. Eine abweichung von 10% würde ja bedeuten dass
> mindestens 10% der Pulse metastabil waren, dies ist aber mit den
> gegebenen tr/tf bei einem Signal von 5MHZ eigentlich nicht möglich.

Da kann viel passieren. Du kannst bei der rising sowie falling edge des 
5 MHz-Signals abtasten, weshalb dein output metastabil wird. Außerdem 
fütterst du mit dem obigen code diese metastabilen Zustände quasi direkt 
in den enable input deines counters. Wenn der metastabil ist, ist auch 
der output deines counters nicht mehr sauber.

von Klar P. (Firma: Reinigungsmittel) (klar_putz)


Lesenswert?

> Und wie es immer noch ein D-FF ist. Ein D-FF mit asynchronem reset
> bleibt noch immer ein D-FF, nur mit weiterem Input. Nur weil die
> Hersteller für jede Art von FF einen eigenen Namen gewählt haben (was
> sie machen, damit man die Primitiven direkt unterscheiden kann, was auch
> gut ist), heißt das nicht, dass es eine ganz neue Art von FF ist.
>
> Immer diese hochnäsigen Kommentare..

Was ist an dem Hinweis, das da ein reset und darüber hinaus unnötig ist, 
"hochnäsig?"

Zu dem thema gibt es hochoffizielle White Paper, 
(https://docs.amd.com/v/u/en-US/wp272) also ist es nur berechtigt, das 
man Anfänger auf einen solchen Schnitzer hinweist.

von Lars (rezyy)


Lesenswert?

Klar P. schrieb:
> Was ist an dem Hinweis, das da ein reset und darüber hinaus unnötig ist,
> "hochnäsig?"

Wenn du nochmal liest, habe ich nicht kritisiert, dass der reset unnötig 
ist. Dass viele resets unnötig sind, ist absolut korrekt - damit hast du 
Recht. Hochnäsig ist, dass du mir erklären willst, dass es kein D-FF 
sei.

von Klar P. (Firma: Reinigungsmittel) (klar_putz)


Lesenswert?

> Klar P. schrieb:
>> Zwei reichen normalerweise und weil in den (FPGA-) PAD's sowieso
>> FF-Primitive sind, kriegste das erste quasi geschenkt.
>
> Also im user Design noch eines? (Da HW bedingt eines ohnehin immer
> vorhanden ist)

Hm, ich weiß jetzt nicht genau was du meinst, das FF ist zwar 
üblicherweise im IO-PAD, aber natürlich wird das Signal nur darüber 
geroutet wenn der das so im Source steht. Vielleicht erhellt Dich ein 
Blick in alte threads, das Thema FPGA-Einsynchronisation ist auch hier 
schon x-Mal durchgekaut worden:

* Beitrag "Einsynchronsieren mit 2 FFs"
* Beitrag "Zeitkritisches Einsynchronisieren asynchroner Signale"
* Beitrag "FPGA Synchronisation"
* Beitrag "Verständnisfrage Einsynchronisieren"
* Beitrag "Verständnisfrage Einsynchronisieren bei mehreren Taktdomains"
* Beitrag "Frage zum "Einsynchronisieren" und "RESET""

von Klar P. (Firma: Reinigungsmittel) (klar_putz)


Lesenswert?

Lars schrieb:
u
>  Hochnäsig ist, dass du mir erklären willst, dass es kein D-FF
> sei.

Sehe ich anders, es ist nicht hochnäsig, es ist sogar notwendig darauf 
hinzuweisen, das ein Delay-FlipFlop keine weiteren Eingänge als CLK und 
D hat.

von Lars (rezyy)


Lesenswert?

Klar P. schrieb:
> Lars schrieb:
> u
>>  Hochnäsig ist, dass du mir erklären willst, dass es kein D-FF
>> sei.
>
> Sehe ich anders, es ist nicht hochnäsig, es ist sogar notwendig darauf
> hinzuweisen, das ein Delay-FlipFlop keine weiteren Eingänge als CLK und
> D hat.

In der Basisvariante, ja. Schau halt bspw. in die Xilinx libraries für 
die Primitiven. Ob du nun FD, FDC, FDCE, FDR, FDRE, FDS, FDSE, FDP, FDPE 
oder was auch immer nimmst: Es bleiben alles D-FFs (u.U. mit weiteren 
Eingängen).

von Klar P. (Firma: Reinigungsmittel) (klar_putz)


Lesenswert?

> In der Basisvariante, ja. Schau halt bspw. in die Xilinx libraries für
> die Primitiven. Ob du nun FD, FDC, FDCE, FDR, FDRE, FDS, FDSE, FDP, FDPE
> oder was auch immer nimmst: Es bleiben alles D-FFs (u.U. mit weiteren
> Eingängen).

Dem Kürzel nach, aber nicht in der Funktion als delay-Element.

Hier zum Detektieren von '0' auf '1' - Wechsel am Input ist ein reines, 
simples D-FF nötig.
Andernfalls besteht das Risiko das bspw. beim system(re-)start 
fälschlicherweise ein Signalwechsel am Input signalisiert wird.
Bei Xilinx-Architekturen kommen noch ein paar Fallstricke hinzu die ggf. 
dazu führen, das mehr Resourcen benötigt werden und eben nicht das 
"kostenlose" PAD-FF zum einsynchronisieren genutzt werden kann, weil 
unnötigerweise einweiterer Eingang neben D und clk instrumentalisiert 
wird. Auch dazu gibt es eine WP.

von Lars (rezyy)


Lesenswert?

Klar P. schrieb:
> Hier zum Detektieren von '0' auf '1' - Wechsel am Input ist ein reines,
> simples D-FF nötig.

Das hat niemand anders behauptet.

Klar P. schrieb:
> Andernfalls besteht das Risiko das bspw. beim system(re-)start
> fälschlicherweise ein Signalwechsel am Input signalisiert wird.

Nicht, wenn der asynchrone reset mit einer reset bridge sauber erzeugt 
wird. Aber auch das machen viele nicht.

Klar P. schrieb:
> Bei Xilinx-Architekturen kommen noch ein paar Fallstricke hinzu die ggf.
> dazu führen, das mehr Resourcen benötigt werden und eben nicht das
> "kostenlose" PAD-FF zum einsynchronisieren genutzt werden kann, weil
> unnötigerweise einweiterer Eingang neben D und clk instrumentalisiert
> wird. Auch dazu gibt es eine WP.

Die Nutzung des IOB FFs ist auch nicht immer die beste Lösung, weil der 
path vom IOB FF zum zweiten FF in der chain länger wird und damit 
weniger Zeit für die Auflösung der Metastabilität bereitstellt. Es gibt 
viele Möglichkeiten und je nach Fall ist die eine oder andere besser. 
Allgemein zu sagen, dass das IOB FF genutzt werden sollte, ist halt 
nicht korrekt - es kommt auf den Anwendungsfall an.

Übrigens kann man mit den Xilinx 7-series FPGAs sogar einen Trick 
nutzen, wo direkt im IOB ein 2-stufiger synchronizer eingebaut wird, 
ohne dass man etwas constrainen muss. Wenn 2 Stufen reichen, ist auch 
das eine sehr gute (und kostenlose) Alternative.

von Klar P. (Firma: Reinigungsmittel) (klar_putz)


Lesenswert?

> Die Nutzung des IOB FFs ist auch nicht immer die beste Lösung, weil der
> path vom IOB FF zum zweiten FF in der chain länger wird und damit
> weniger Zeit für die Auflösung der Metastabilität bereitstellt.

Sorry aber das mit der längerern Pfadlänge klingt nicht besonders 
glaubhaft.
Der Pfad übers pad zu einem FF in der Fab ist IMHO immer länger als der 
Pfad übers Pad zu dem FF ins pad. Der Pfad vom PAD-FF zum Fab-FF dürfte 
nicht anders sein als der zwischen Fab-FF. Mglw. ist das von speedgrad 
zu speedgrade unterschiedlich.
Und IMHO ist die Gesamtwahrscheinlichkeit des Abklingens des 
metastabilen Zustandes das Produkt aus den einzelnen 
Wahrscheinlichkeiten des Auflösung des metastabilen Zustandes. Also wenn 
man die erste stage ungünstiger gestaltet um bei der zweiten eine 
günstiger Wahrscheinlichkeit zu haben ist das Endergebnis das selbe als 
wenn man die Wahrscheinlichkeiten vertauscht. und die erste stage 
schnell belässt, auch wenn das für die folgende zweite stage nachteilig 
sein sollte.

> Übrigens kann man mit den Xilinx 7-series FPGAs sogar einen Trick
> nutzen, wo direkt im IOB ein 2-stufiger synchronizer eingebaut wird,
> ohne dass man etwas constrainen muss. Wenn 2 Stufen reichen, ist auch
> das eine sehr gute (und kostenlose) Alternative.

Wenn man eine FIFO in den Pads hat, kann man diese auch nutzen. Oder 
sonstige IO-Pad specifica nutzen.

: Bearbeitet durch User
von Lars (rezyy)


Lesenswert?

Klar P. schrieb:
> Sorry aber das mit der längerern Pfadlänge klingt nicht besonders
> glaubhaft.
> Der Pfad übers pad zu einem FF in der Fab ist IMHO immer länger als der
> Pfad übers Pad zu dem FF ins pad.

Dieser Pfad ist auch absolut irrelevant. Natürlich ist der Pfad vom pad 
zum IOB FF kürzer, aber was bringt das für den synchronizer? Das ist nur 
ein allgemeines (kurzes) delay VOR dem synchronizer.

Klar P. schrieb:
> Der Pfad vom PAD-FF zum Fab-FF dürfte
> nicht anders sein als der zwischen Fab-FF.

Wieso sollte er nicht? Möglicherweise gibt es Architekturen, wo diese 
gleich sind, keine Ahnung. Generell ist das net vom IOB-FF zum ersten 
fabric FF aber etwas länger als wenn man fabric FFs direkt nebeneinander 
(in einem slice) platziert.

Klar P. schrieb:
> Und IMHO ist die Gesamtwahrscheinlichkeit des Abklingens des
> metastabilen Zustandes das Produkt aus den einzelnen
> Wahrscheinlichkeiten des Auflösung des metastabilen Zustandes. Also wenn
> man die erste stage ungünstiger gestaltet um bei der zweiten eine
> günstiger Wahrscheinlichkeit zu haben ist das Endergebnis das selbe als
> wenn man die Wahrscheinlichkeiten vertauscht. und die erste stage
> schnell belässt, auch wenn das für die folgende zweite stage nachteilig
> sein sollte.

Absolut korrekt. Dennoch kann der reine fabric FF synchronizer Vorteile 
haben, aber das ist sehr detailliert.

von Klar P. (Firma: Reinigungsmittel) (klar_putz)


Lesenswert?

Lars schrieb:
> Klar P. schrieb:
>> Sorry aber das mit der längerern Pfadlänge klingt nicht besonders
>> glaubhaft.
>> Der Pfad übers pad zu einem FF in der Fab ist IMHO immer länger als der
>> Pfad übers Pad zu dem FF ins pad.
>
> Dieser Pfad ist auch absolut irrelevant. Natürlich ist der Pfad vom pad
> zum IOB FF kürzer, aber was bringt das für den synchronizer? Das ist nur
> ein allgemeines (kurzes) delay VOR dem synchronizer.

Stimmt.
IMHO hat es aber denoch Vorteile das erste Sync-FF ins Pad zu legen.
Dieser Pfad ist im Gegensatz zum Fab-FF vom Routing und Placement 
unabhängig und damit bei jedem "VHDL-Compile" gleich, während bei FAB-FF 
je nach Ressourcenauslastung ein andere Pfad vom Pad zu irgendeinem 
Fab-FF "irgendwie" geroutet wird. Das "irgendwie" kann man durch 
constraint beeinflußen, es bleibt aber denoch variabel. Nur beim Pad-FF 
ist minimale und damit definierte Signallaufzeit gegeben. Natürlich 
sollte man sich durch einen Blick in den Pin-report vergewissern das für 
dieses signal das PAD-FF genutzt wird.

von Lars (rezyy)


Lesenswert?

Klar P. schrieb:
> Stimmt.
> IMHO hat es aber denoch Vorteile das erste Sync-FF ins Pad zu legen.
> Dieser Pfad ist im Gegensatz zum Fab-FF vom Routing und Placement
> unabhängig und damit bei jedem "VHDL-Compile" gleich, während bei FAB-FF
> je nach Ressourcenauslastung ein andere Pfad vom Pad zu irgendeinem
> Fab-FF "irgendwie" geroutet wird. Das "irgendwie" kann man durch
> constraint beeinflußen, es bleibt aber denoch variabel. Nur beim Pad-FF
> ist minimale und damit definierte Signallaufzeit gegeben. Natürlich
> sollte man sich durch einen Blick in den Pin-report vergewissern das für
> dieses signal das PAD-FF genutzt wird.

Gebe ich dir grundsätzlich auch Recht. Zumeist ist es auch besser. Für 
den Fall, dass man direkt in der fabric synchronisiert, sollte man - wie 
du sagst - zumindest ein set_max_delay spendieren und den Pfad auf 
wenige ns beschränken.

von Bernhard K. (bkom)


Lesenswert?

Da verlinke ich doch mal die Seite von lkmiller:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html

Zitat daraus:
"Warum müssen externe Signale einsynchronisiert werden?
Meist wird dabei auf das Hammerargument "Metastabilität" von Flipflops 
verwiesen und damit jede weitere Frage automatisch abgewürgt. In der 
Praxis ist Metastabilität aber weniger verbreitet als man denkt. Moderne 
FFs in FPGAs fangen sich nach kürzester Zeit wieder (<3ns) und haben 
dann am Ausgang einen stabilen Pegel. 333MHz? Da kann eigentlich nichts 
mehr schiefgehen. Damit sind wir also wieder bei der Frage:

Warum müssen externe Signale einsynchronisiert werden?
Externe Signale müssen einsynchronisiert werden, weil sie idR. zwar an 
einer Stelle (am Pin) ins FPGA hineingehen, dort aber dann im Routing 
wild hin- und herverdrahtet werden und u.U. über Kombinatorik an 
etlichen FFs ankommen. Und hier kann es dann durchaus sein, dass ein 
paar FFs bei der "nächsten" Taktflenke schon eine '1' erkennen, wenn 
andere noch meinen es gelte die vorhergehende '0'. Als Beispiel hier 
eine kleine State-Machine, die das verdeutlicht."

: Bearbeitet durch User
von Max M. (ff_ff)


Lesenswert?

Nun bei der Einsynchronisierung giebts anscheinend immer wieder 
Verwirrung. (Bei mir auch).

Könnte daher jemand einen kleinen VHDL code posten (input = pin signal, 
clk oder pll vielfaches von clk; output = signal synchronisiert) mit den 
zugehörigen signal contraint parameter  welche alle constraint werden 
müssen. (also einfach code welcher in die constraint Liste eingefügt 
werden muss (intel, amd)).

Wenn der systemclk 100MHz beträgt, könnte doch mit dem PLL ein 600MHZ 
Synchronisierclk generiert werden und die Synchronisierer damit getaktet 
werden über 6FF (um Metastabilitäten sicher aufzulösen) und das ganze 
bei einem clk systemtakt?

Zudem hat jeder VHDL block den asynchronen nrst. Diesen hänge ich 
einfach immer auf '1'! Ist dies fachgerecht? Wieso wird dies generell 
asynchron gemacht (hat doch potential gewaltig scheif zu gehen)? Nutzt 
dieser nrst überhaupt jemand?

von Gustl B. (-gb-)


Lesenswert?

Max M. schrieb:
> Zudem hat jeder VHDL block den asynchronen nrst.

Hä? Meine Komponenten haben den manchmal, aber sicher nicht immer. 
Manchmal braucht man den eben weil man einen definierten Zustand 
gewährleisten können muss auch wenn kein Takt vorhanden ist.

Max M. schrieb:
> Wenn der systemclk 100MHz beträgt, könnte doch mit dem PLL ein 600MHZ
> Synchronisierclk generiert werden und die Synchronisierer damit getaktet
> werden über 6FF (um Metastabilitäten sicher aufzulösen) und das ganze
> bei einem clk systemtakt?

Ja und nein. Klar kannst du das externe Signal in eine Taktdomäne mit 
hoher Frequenz einsynchronisieren. Aber wenn du das dann von dort wieder 
einer anderen Taktdomäne "übergeben" willst, dann kostet das auch dort 
wieder Takte. Will sagen du gewinnst erstmal nichts.
Aber wenn dein externes Signal nicht sauber ist, also analog, dann 
kannst du schon schnell abtasten und dann quasi eine Art Mittelwert über 
mehrere Samples bilden der dann verwendet wird.

von Markus F. (mfro)


Lesenswert?

Lars schrieb:
> Das constraint muss für jeden path/net zwischen den FFs in der
> Synchronisiererstufe gesetzt werden. Bei 10ns wäre ein typischer und
> guter Wert 2ns path delay, wenn das Tool so das P&R schafft. Dann
> bleiben 8ns, um die Metastabilität in jeder stage aufzulösen.

Das kapier' ich nicht. Warum sollte ich den internen Pfad zwischen zwei 
Flipflops - ohne irgendwelche Kombinatorik dazwischen - constrainen? 
Wenn die Timing-Analyzer der Toolsets irgendwas wissen, dann doch die 
Timing-Parameter der LEs, die sie bedienen? Die sollen das gefälligst 
selber machen...

Auch die Notwendigkeit (bzw. Nutzen) für mehr als zwei Register zum 
Einsynchronisieren entzieht sich meinem Verständnis. Quartus 
beispielsweise erkennt Synchronizer Chains, klaut sich aber u.U. (wenn 
Timing Driven Synthesis + Register Retiming aktiv und das Timing 
woanders knapp ist) nach meiner Erfahrung alle bis auf die zwei wirklich 
notwendigen (ich nehme an, dass ist bei der Konkurrenz ähnlich).

: Bearbeitet durch User
von Lars (rezyy)


Lesenswert?

Max M. schrieb:
> Wenn der systemclk 100MHz beträgt, könnte doch mit dem PLL ein 600MHZ
> Synchronisierclk generiert werden und die Synchronisierer damit getaktet
> werden über 6FF (um Metastabilitäten sicher aufzulösen) und das ganze
> bei einem clk systemtakt?

Ich habe mir mal Quartus angeschaut, habe damit noch nie gearbeitet. Die 
geben dir bei richtiger Einstellung die MTBF für deine synchronizer. Es 
scheint so, dass bei gutem placing 2 FFs absolut ausreichend sind. Lt. 
tool erhöht sich die MTBF um den Faktor 10 für jede 100ps Auflösezeit 
der Metastabilität (Cyc10 LP). Da sind 2 FFs bei 100 MHz mit mehreren ns 
Auflösezeit absolut ausreichend, man kommt damit sehr einfach schon auf 
riesige MTBFs, da die FFs die Metastabilitäten extrem schnell auflösen. 
Es geht auch um die Gesamtsumme der Auflösezeit. Wenn du 600 MHz mit 
mehreren Stufen nimmst, reduzierst du pro Stufe die Auflösezeit. Es geht 
nicht nur um die Anzahl der FFs.

Max M. schrieb:
> Könnte daher jemand einen kleinen VHDL code posten (input = pin signal,
> clk oder pll vielfaches von clk; output = signal synchronisiert) mit den
> zugehörigen signal contraint parameter  welche alle constraint werden
> müssen. (also einfach code welcher in die constraint Liste eingefügt
> werden muss (intel, amd)).

Quartus hat bei mir die sync. chains erkannt und hat die FFs direkt 
beieinander platziert. Falls das tool das immer übernimmt (keine 
Ahnung), bräuchtest du keine constraints. Bei Xilinx weist man das tool 
bspw. mit dem ASYNC_REG-Attribut darauf hin. Schau mal in deinem Design 
in den metastability report. Ansonsten habe ich halt das set_data_delay 
SDC constraint gefunden, was den max. path constrainen kann. Das kann 
man setzen, um sicherzugehen.

Max M. schrieb:
> Zudem hat jeder VHDL block den asynchronen nrst. Diesen hänge ich
> einfach immer auf '1'! Ist dies fachgerecht? Wieso wird dies generell
> asynchron gemacht (hat doch potential gewaltig scheif zu gehen)? Nutzt
> dieser nrst überhaupt jemand?

Manche Teile benötigen im FPGA einen reset, andere nicht. Das musst du 
entscheiden. Zumeist sind auch synchrone resets besser, wenn man welche 
benötigt. Sofern du einen asynchronen reset aktiv nutzt, musst du auch 
eine reset bridge einbauen. Dann ist das sicher und geht nicht mehr 
schief.

Markus F. schrieb:
> Das kapier' ich nicht. Warum sollte ich den internen Pfad zwischen zwei
> Flipflops - ohne irgendwelche Kombinatorik dazwischen - constrainen?
> Wenn die Timing-Analyzer der Toolsets irgendwas wissen, dann doch die
> Timing-Parameter der LEs, die sie bedienen? Die sollen das gefälligst
> selber machen...

Ein synchronizer arbeitet nur richtig, wenn die Metastabilität aufgelöst 
werden kann. Dafür darf der path nicht zu lang sein. Wenn das tool den 
synchronizer selbständig erkennt und den path entsprechend kurz 
implementiert, ist alles gut. Allgemein gilt bei Xilinx bspw. dass man 
das korrekt constrained, weil das tool sonst machen kann, was es will. 
Das normale timing wird bei constrainter clock natürlich eingehalten - 
das reicht aber nicht für den synchronizer. Der MUSS die Metastabilität 
auflösen und dafür DARF der path zwischen den sync.-Stufen nicht zu lang 
sein. Das tool versucht mit der STA erstmal nur keine setup&hold 
violations einzuführen und kann den path damit THEORETISCH bei vollem 
FPGA so lang werden lassen, dass die setup&hold timings gerade so 
eingehalten werden. Das gilt es für den synchronizer zu vermeiden. Wenn 
Quartus den synchronizer selbst erkennt und die paths kurz hält, 
brauchst du dich nicht darum kümmern. Das weiß ich nicht, würde aber 
nicht einfach darauf vertrauen.

Markus F. schrieb:
> Auch die Notwendigkeit (bzw. Nutzen) für mehr als zwei Register zum
> Einsynchronisieren entzieht sich meinem Verständnis. Quartus
> beispielsweise erkennt Synchronizer Chains, klaut sich aber u.U. (wenn
> Timing Driven Synthesis + Register Retiming aktiv und das Timing
> woanders knapp ist) nach meiner Erfahrung alle bis auf die zwei wirklich
> notwendigen (ich nehme an, dass ist bei der Konkurrenz ähnlich).

Hat alles was mit der MTBF und deinem Anwendungsfall zu tun. Die MTBF 
ergibt sich aus einigen Parametern, u.a. ist die Geschwindigkeit der FFs 
wichtig. Da die FFs mittlerweile sehr schnell sind, reichen 2 FFs sehr 
oft absolut aus. Aber halt nicht immer, das muss man halt durchrechnen 
(Quartus spuckt dir das ja im metastability report aus)!

von Markus F. (mfro)


Lesenswert?

Lars schrieb:
> Dafür darf der path nicht zu lang sein. Wenn das tool den
> synchronizer selbständig erkennt und den path entsprechend kurz
> implementiert, ist alles gut.

Dafür gibt es in Quartus eine passende Einstellung:

If a synchronization register chain is identified with the 'Forced' or 
'Forced if Asynchronous' option, then its registers are optimized for 
improved Mean Time Between Failure (MTBF) as long as the Optimize Design 
for Metastability option is turned on, and the Timing Analyzer reports 
the metastability MTBF for the chain if it meets the design timing 
requirements.

Einschalten und das Tool machen lassen.

von Max M. (fpga_eth)


Angehängte Dateien:

Lesenswert?

Max M. schrieb:
> Nun bei der Einsynchronisierung giebts anscheinend immer wieder
> Verwirrung. (Bei mir auch).
>
> Könnte daher jemand einen kleinen VHDL code posten (input = pin signal,
> clk oder pll vielfaches von clk; output = signal synchronisiert) mit den
> zugehörigen signal contraint parameter  welche alle constraint werden
> müssen. (also einfach code welcher in die constraint Liste eingefügt
> werden muss (intel, amd)).

bitte sehr

Markus F. schrieb:
> If a synchronization register chain is identified with the 'Forced' or
> 'Forced if Asynchronous' option, then its registers are optimized for
> improved Mean Time Between Failure (MTBF) as long as the Optimize Design
> for Metastability option is turned on, and the Timing Analyzer reports
> the metastability MTBF for the chain if it meets the design timing
> requirements.

Wie Markus bereits erwähnt hat sind diese constraints nicht mehr nötig, 
das tool machts automatisch

von Markus F. (mfro)


Lesenswert?

Max M. schrieb:
> Zudem hat jeder VHDL block den asynchronen nrst. Diesen hänge ich
> einfach immer auf '1'! Ist dies fachgerecht? Wieso wird dies generell
> asynchron gemacht (hat doch potential gewaltig scheif zu gehen)? Nutzt
> dieser nrst überhaupt jemand?

Beitrag "Re: Altera Reset Synchronizer richtig machen"

... und ob Du einen Reset überhaupt brauchst oder nicht (und ob der 
asynchron sein soll oder nicht), musst Du anhand deines Designs selbst 
entscheiden.

Die asynchronen Resets von Altera sind wohl ein wenig eine 
Philosophiefrage:  "wenn ich einen Reset brauche, soll ein Reset 
ausgeführt werden. Da will ich nicht erst auf eine Clock Edge warten".

Unabhängig davon, wie man zu dieser Philosophie steht, sind die 
asynchronen RST-Eingänge bei den Altera-Chips nun mal da und können ohne 
Extrakosten benutzt werden. Wie man sie richtig benutzt, steht in der 
AN545 (oder eben in obigem Link)

: Bearbeitet durch User
von Max M. (fpga_eth)


Lesenswert?

Wie siehts eigentlich mit den internen HW SERDES aus?
Genau betrachtet müssten dieser ja ebenfalls das das LSB des 
Deserialisers ein Metastabilitätsproblem haben?

von Peter D. (peda)


Lesenswert?

Ich hatte mal ein Projekt für einen Zähler geerbt, welches mal um 16 und 
seltener um 256 falsch zählte. Es waren 3 Stück 74AC193 kaskadiert und 
als Gate ein 74AC00 vor dem Zähleingang. Das Gate erfolgte also 
asynchron zum Zählimpuls und hat ihn manchmal zu sehr verkürzt.

Ich habe es dann umgeändert zu einem Asynchronzähler, d.h. /Q zum CLK 
des nächsten. Das Gatesignal ging dann auf J+K des ersten FF, d.h. nur 
der erste FF wurde angehalten. Damit funktionierte der Zähler 
einwandfrei.

Kommt von außen ein asynchrones Signal, darf man damit nur einen FF 
freigeben und nicht mehrere.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.