4x /Sec Frequenzmessung, bug im code?

OP #7631879
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;
#7631962
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.
OP #7632098
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.

#7632106
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.

OP #7632231
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?

OP #7632243
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.

#7632582
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'.

Gast #7632605
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 ?

#7632609
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.

Gast #7632620
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.

Angehängte Dateien:
OP #7632972
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?)

Gast #7632991
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

#7633024
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.

Gast #7633029
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.

Gast #7633041
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:

Gast #7633049
Lesenswert?

Lars schrieb im Beitrag #7633034: 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.

#7633057
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).

Gast #7633089
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.

#7633121
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.

Gast #7633145
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.

#7633172
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.

Gast #7633180
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.

#7633186
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.

#7633211
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."

#7635035
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?

#7635345
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.

#7635401
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).

#7635892
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)!

#7636148
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.

#7636981
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

Angehängte Dateien:
#7637000
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)

#7637217
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren