Forum: FPGA, VHDL & Co. VHDL-Zähler zählt hin und wieder falsch


von ArminD (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem mit einem VHDL-Code (Spartan XC3S500E, ISE 
9.2.04i): Es soll unter anderem ein langsames Clocksignal (ca. 40kHz) 
mit einem 8MHz-Takt ausgemessen werden.

Grundsätzlich funktioniert es so wie geplant, nur habe ich festgestellt, 
daß einer der Zähler nicht immer korrekt zählt und Sprünge macht, weil 
beim Zählen ein oder mehrere Bits (ausschliesslich die Bits 0, 1, 4 des 
Zählers) nicht richtig gesetzt bzw. gelöscht werden.
Zählvorgang z.B. 44, 45, 46, 47, 35, 36, 37...
Bei dem Wechsel auf 47 folgend sollte Bit4 nach High gehen und Bit0 und 
Bit1 nach Low. Das tun sie aber nicht. Vermutlich ist in diesem Moment 
eine Setup/Hold-Bedingung in den betreffenden Registern 0, 1, 4 
verletzt, so daß nicht richtig gezählt wird, in den anderen Registern 
(2, 3, ...) scheint die Bedingung wohl ok zu sein, sonst würden diese 
nicht korrekterweise auf 0 gehen. Scheint wohl mit Laufzeiten zu tun
haben.

Kann mir jemand einen Tipp geben wie ich das Problem lösen kann. Wie 
gesagt, es  passiert nur hin und wieder und danach wird korrekt 
weitergezählt. Die Zählertiefe ist übrigens 16 Bit.

Vielen Dank für Antworten.

Gruß,
Armin

von Jan M. (mueschel)


Lesenswert?

Tritt der Fehler in Hardware oder in der Simulation auf?
Wenn ersteres, ist es ein timing-Fehler, wenn zweiteres stimmt 
wahrscheinlich eine sensitivity list nicht.

In jedem Fall wuerde der Quellcode sehr viel dabei helfen, dir zu 
helfen...

von Klaus F. (kfalser)


Lesenswert?

Kommt das zu messende Signal von außen ?
Vielleicht sind die Flanken zu wenig steil.
Du mußt das Signal sicher auch einsynchronisieren, sonst kommt es, wenn 
die Zeitdifferenz Flanke des Signals zum Meß-Takt zu klein ist, zu 
Hold-Time und Setup Verletzungen.

von ArminD (Gast)


Lesenswert?

Danke für die Antwort.

Der Fehler tritt in der Simulation nicht auf sondern nur
in der realen Hardware, zumindest sporadisch.

Wie meinst Du das genau mit der sensitivity list ?

Ich habe den Code im Moment nicht hier, werde das aber
nachholen wenn ich zu Hause bin.

von Jan M. (mueschel)


Lesenswert?

Wenn der Fehler in Hardware auftritt ist es sicher ein Timing-Problem. 
Signale von aussen erst durch zwei Ebenen Flipflops leiten, bevor sie 
verwendet werden.

An der sensitvity list kann es in diesem Fall nicht liegen, da diese ja 
nur in der Simulation eine Rolle spielt.

von ArminD (Gast)


Lesenswert?

@Klaus Falser

Vielen Dank für Deine Antwort.

Das zu messende Signal kommt von aussen. Sowohl die Rise-
als auch die Fall-Time sind in der Größenordnung von 15 ns.

Vermutlich ist das zusätzliche Einsynchronisieren mein Problem.
Das leuchtet ein. Das heißt, ich brauche zusätzlich einen Takt,
der deutlich größer ist als mein Messtakt von 8Mhz. So was habe
ich aber von außen nicht zur Verfügung. Gibt es sowas bereits
auf dem XILINX und falls ja, wie kann ich das benutzen ?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> ... langsames Clocksignal (ca. 40kHz)
> mit einem 8MHz-Takt ausgemessen werden.
:
> Das heißt, ich brauche zusätzlich einen Takt,
> der deutlich größer ist als mein Messtakt von 8Mhz.
Nein, du brauchst nur 2 FFs, die mit den 8MHz getaktet werden, und durch 
diese beiden muß dein Signal durch. Erst dann darfst du es innerhalb des 
FPGAs verwenden.

von ArminD (Gast)


Lesenswert?

@Lothar,

danke für den Hinweis, ich denke jetzt wird es klar.
Ich muß lediglich die zum Zählen invertierte Flanke
für das Eintakten des zu messenden Signals nehmen.

Habe ich früher ja auch so gemacht als man noch Schematics
gezeichnet hat, nur bei HDLs habe ich es vergessen.

Ich werde es heute abend mal ausprobieren.

von Morin (Gast)


Lesenswert?

> Ich muß lediglich die zum Zählen invertierte Flanke
> für das Eintakten des zu messenden Signals nehmen.

???

Einfach das Signal durch 2 FFs durch, so als wolltest du es um 2 Takte 
verzögern.

Nach dem Einsynchronisieren musst du das Signal evtl. entprellen. Dazu 
verzögerst du das Signal um 1 (System-)Takt und vergleichst den 
verzögerten mit dem unverzögerten Wert. Nebenher zählt ein Zähler mit, 
der resettet wird wenn die beiden Werte verschieden sind. Am Ausgang des 
Entprellers sitzt ein weiteres Register, welches den Signalwert erst 
dann lädt, wenn der Zähler einen bestimmten Wert erreicht hat (der sich 
nach der zu erwartenden Prelldauer ergibt). Vorher wird das 
Ausgangsregister nicht geladen, d.h. der alte Wert wird behalten, so 
dass das Prellen nach innen nicht sichtbar ist.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

> danke für den Hinweis, ich denke jetzt wird es klar.
> Ich muß lediglich die zum Zählen invertierte Flanke
> für das Eintakten des zu messenden Signals nehmen.
Nein, ich glaube du hast es noch nicht soooo ganz richtig verstanden ;-)

Du hast einen FPGA-Takt von 8 MHz.
Und du hast ein zweites Signal mit 40kHz, von dem du die Zeit zwischen 
zwei steigenden (oder auch fallenden) Flanken basierend auf diesen 8 MHz 
zählen willst.

Also mußt du
1. das externe Signal auf den Takt synchronisieren
2. die Flanken in dem synchronisierten Signal erkennen
3. die Zeit zwischen zwei dieser Flanken messen und
4. diesen ermittelten Wert abspeichern

Machs z.B. so:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Frequenzmesser is
6
    Port ( clk8M : in  STD_LOGIC;
7
           sig   : in  STD_LOGIC;
8
           cnt   : out  STD_LOGIC_VECTOR (15 downto 0));
9
end Frequenzmesser;
10
11
architecture Behavioral of Frequenzmesser is
12
signal counter   : integer range 0 to 65535 := 0;
13
signal countmerk : integer range 0 to 65535 := 0;
14
signal sigsr : std_logic_vector(2 downto 0) := "000";
15
begin
16
   -- Einsynchronisieren
17
   process begin
18
      wait until rising_edge(clk8M);
19
      sigsr <= sigsr(1 downto 0) & sig;
20
   end process;
21
22
   -- Flankenerkennung und Zähler
23
   process begin
24
      wait until rising_edge(clk8M);
25
      counter <= counter+1;
26
      if (sigsr(2 downto 1)="01") then -- steigende Flanke
27
         countmerk <= counter;
28
         counter   <= 0;
29
      end if;
30
   end process;
31
32
   -- Zählerwert zurückgeben
33
   cnt <= std_logic_vector(to_unsigned(countmerk,16));
34
end Behavioral;

Im Anhang die (recht kompakte) Testbench zum Projekt.

von ArminD (Gast)


Lesenswert?

@Morin, Lothar Miller

Vermutlich habe ich mich sehr mißverständlich ausgedrückt, ich
meinte zwei FFs.
Ich synchronisiere den auszuwertenden Takt indem ich ihn durch
2 FFs durchschicke, diese FFs clocke ich mit der invertierten
Flanke des 8MHz-Taktes, also invertiert zum darauf folgenden Zähler.
So wird immer gewährleistet daß die S/H-Zeiten für die Register des
Zählers eingehalten werden.
Damit ist das Zählerproblem behoben.


@Lothar Miller

Danke für den geposteten Code.

von Morin (Gast)


Lesenswert?

> Ich synchronisiere den auszuwertenden Takt indem ich ihn durch
> 2 FFs durchschicke, diese FFs clocke ich mit der invertierten
> Flanke des 8MHz-Taktes, also invertiert zum darauf folgenden Zähler.
> So wird immer gewährleistet daß die S/H-Zeiten für die Register des
> Zählers eingehalten werden.

Die 2 FFs sind so okay. Für die invertierte Flanke sehe ich aber den 
Grund noch nicht... soweit ich weiß nimmt man dafür die selbe Flanke wie 
für alle anderen FFs auch. Wenn z.B. das zweite Synchro-FF tatsächlich 
beim Laden mal metastabil wird, dann hat es bei deiner Lösung 
(invertierte Clock für die Synchro-FFs) nur eine halbe Taktperiode Zeit 
zum "Umkippen", beim nichtinvertierten Takt eine ganze.

von Klaus F. (kfalser)


Lesenswert?

@Morin
Du hast natürlich recht, aber die Chance, dass bei einem 8 MHz Takt der 
Ausgang des 1. FF nach 125 ns noch metastabil ist, dürfte jenseits 
unserer aller Lebenserwartungen liegen :-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> dürfte jenseits unserer aller Lebenserwartungen liegen :-)
Also, ich nehme auch immer eine Bombe mit ins Flugzeug, denn die 
Wahrscheinlichkeit, dass zwei Bomben in einem Flugzeug sind.... ;-)

Es ist ganz einfach so, dass das Design an dieser Stelle 
(unnötigerweise) doppelt so schnell sein muß. Und wenn man das bei 8 MHz 
lernt, dann könnte es sein, dass man es auch bei 200 MHz noch so 
macht.

von Der Besucher (Gast)


Lesenswert?

Hallo,

ich bin zufällig hier vorbeigestolpert.

Ich empfehle auch, die 2 synchronisierungs Flipflops auf der selben 
Taktflanke laufen zu lassen, wie der Rest der Schaltung, wenn auch aus 
anderen Gründen. Ich setze mal voraus, dass es sich um eine komplett 
synchrone Schaltung handelt.
Vorteile sind (zum Teil schon erwähnt und manches bei FPGA unnötig):
* die kombinatorische Logic des Zählers hat eine ganze Taktperiode 
anstatt nur einer halben lang Zeit (kann bei hoher Temperatur schon mal 
wichtig werden)
* Scanpfad einfügen ist einfacher
* nur ein Clock-Tree
Desweiteren sollte man über einen Signal-Debouncer nachdenken, wenn ein 
externes Steuersignal genutzt wird.

Vielleicht kann man ja mal den Code sehen?

@Lothar Miller
Dein Code ist zwar "behavioral", aber mal 3 Fragen
* auf einen Reset wird absichtlich verzichtet?
* ist das synthetisierbar? Wenn ja mit welchem Tool? (Ich frage wegen 
der waits)
* ein Überlauf des Counters wird absichtlich in Kauf genommen?
Aber das ist rein interessehalber.

Der Besucher

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Der Besucher wrote:
> @Lothar Miller
> Dein Code ist zwar "behavioral", aber mal 3 Fragen
> * auf einen Reset wird absichtlich verzichtet?
Ja, Reset nur dort, wo unbedingt nötig. Und dann auch nur synchron.
Dazu gibt es ein schönes Whitepaper von Xilinx.
Siehe dazu den Beitrag "Xilinx und die Resets"

> * ist das synthetisierbar? Wenn ja mit welchem Tool? (Ich frage wegen
> der waits)
Xilinx XST
(Ausprobiert ab ISE 8, vorher hab ich das auch noch als if-Abfrage 
geschrieben).
Damit wird dann auch (fast zwingend) das ganze Design synchron.

> * ein Überlauf des Counters wird absichtlich in Kauf genommen?
Es ist übersichtlicher, wenn ich davon ausgehe, dass vorher wieder eine 
Flanke kommt. Besser ist es natürlich, den Zähler einfach zu sättigen:
1
:
2
:
3
   -- Flankenerkennung und Zähler
4
   process begin
5
      wait until rising_edge(clk8M);
6
      if (counter/=65535) then 
7
         counter <= counter+1; 
8
      end if;
9
      if (sigsr(2 downto 1)="01") then -- steigende Flanke
10
         :
11
      :

EDIT:
Zum Thema "Reset"
Beitrag "Re: Reset für mehrere Komponenten"
Und
Beitrag "Hardware mit VHDL "richtig" beschreiben."

von Der Besucher (Gast)


Lesenswert?

@Lothar Miller
Danke für die antworten.
Das Paper lese ich mir mal durch. Ich nutze normalerweise Resets, die 
asynchron ausgelöst werden und synchron freigegeben werden.
Das mit den synthetisierbaren waits ist neu für mich. Und wird leider 
nicht von den Tools unterstützt, die ich nutze. Auch die initiale 
Zuweisungen in der Signaldeklaration kenne ich als Fehlerfall.

Kleiner Verbesserungsvorschlag: zum sparen von Gatter einfach 
defaultmässig 0 auf den counter addieren (kann natürlich auch in einen 
else Zweig. Da spart man sich so manchen Multiplexer. Aber keine Ahnung, 
ob das bei FPGAs was bringt.

:
:
   -- Flankenerkennung und Zähler
   process begin
      wait until rising_edge(clk8M);
      -- default
      counter <= counter+0;

      if (counter/=65535) then
         counter <= counter+1;
      end if;
      if (sigsr(2 downto 1)="01") then -- steigende Flanke
         :
      :

Der Besucher

von Klaus F. (kfalser)


Lesenswert?

> Da spart man sich so manchen Multiplexer
Kaum, am Ende kommt bei der Synthese und Optimierung sicher dasselbe 
heraus, weil es ja keine Multiplexer gibt, sondern die kombinatorische 
Funktion minimiert wird und in ein oder mehrere LUTs gepresst wird.
Kombinatorisch sind die Beschreibungen ja identisch.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Aber keine Ahnung, ob das bei FPGAs was bringt.
Ich habs kurz ausprobiert: es ändert sich nichts am Syntheseergebnis.
Die Beschreibung ist auch funktionsgleich mit
1
   -- Flankenerkennung und Zähler
2
   process begin
3
      wait until rising_edge(clk8M);
4
      if (counter/=65535) then
5
         counter <= counter+1;
6
      else
7
         counter <= counter+0;
8
      end if;
9
      if (sigsr(2 downto 1)="01") then -- steigende Flanke
10
         :
11
      :
--> die Addition der 0 wird rausoptimiert.


Sinn macht diese Defaultzuweisung in kombinatorischen Prozessen, denn 
sonst hat man schnell ein Latch an der Backe  ;-)

von Klaus F. (kfalser)


Lesenswert?

> Sinn macht diese Defaultzuweisung in kombinatorischen Prozessen, denn
> sonst hat man schnell ein Latch an der Backe  ;-)
Eine Default-Zuweisung schon, aber eine Addition mit 0 ???

von Der Besucher (Gast)


Lesenswert?

>> Sinn macht diese Defaultzuweisung in kombinatorischen Prozessen, denn
>> sonst hat man schnell ein Latch an der Backe  ;-)

Hier wird ohne die default Anweisung aber kein Latch eingebaut. Das ist 
also nicht der Grund. Na ich versuche es mal zu erklären, was ohne die 
+0 gebaut wird:
Bei nichtausführung der Incrementierung werden die Ausgänge der FFs auf 
ihre Eingänge zurückgekoppelt. Das macht pro FF einen Multiplexer.
(Entweder Ergebnis der Incrementierung oder alter Wert)

>Eine Default-Zuweisung schon, aber eine Addition mit 0 ???

Zum sparen der Multiplexer. Jetzt wird nur noch ein einziger Multiplexer 
verwendet, der entscheidet, ob eine 1 oder eine 0 addiert wird. Aber die 
Eingänge der FFs sehen nur noch den Ausgang des Addierers. Bei 16 Bit 
sparrt man so mal auf die schnelle 15 Muxe.

Der Besucher

von Klaus F. (kfalser)


Lesenswert?

Wie gesagt, bei einem FGPA gibt es keine Multiplexer. Alle Funktionen 
werden in LUTs realisiert, und die Funktion dieser LUTs ist identisch 
mit oder ohne Addition.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Bei 16 Bit spart man so mal auf die schnelle 15 Muxe.
Das ist bei einem (Spartan3-)FPGA aber so, dass für Incerement (+1) oder 
kein Increment (+0) nur der Carry-In des Addierers mal auf 1 oder 0 
gesetzt wird.

Wie gesagt:
>> Ich habs kurz ausprobiert: es ändert sich nichts am Syntheseergebnis.

von Der Besucher (Gast)


Lesenswert?

Nunja, bei FPGAs bringt es dann wohl nichts. Aber da keine LE mehr 
verwendet wird und funktional identisch ist, ist es auch sicherlich kein 
Fehler. Im Standardzellenentwurf sparen solche Tricks jedenfalls 
wertvolle Fläche.
Aber hier wird wohl nur über HDL in programmierbare Logik diskutiert?

Der Besucher

von Klaus F. (kfalser)


Lesenswert?

> Aber hier wird wohl nur über HDL in programmierbare Logik diskutiert?

ASICs können sich die meisten nicht leisten ...

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

Klaus Falser wrote:
> Wie gesagt, bei einem FGPA gibt es keine Multiplexer. Alle Funktionen
> werden in LUTs realisiert, und die Funktion dieser LUTs ist identisch
> mit oder ohne Addition.

Und wie werden dann die Verbindungen zwischen den LUTs und FFs geroutet, 
ohne Multiplexer?

von ArminD (Gast)


Lesenswert?

Auch auf die Gefahr gesteinigt zu werden weil ich die Sync-FFs mit der
negativen Flanke ansteuere möchte ich erklären warum ich das tue.
Vielleicht habe ich ja ein grundsätzliches Verständnisproblem welches
ausgeräumt werden sollte.

Das ursprüngliche Problem war dass ein Zähler, der mit der steigenden
Flanke des 8Mhz-Taktes abhängig von einem externen Takt hin und wieder
falsch zählt. Da dieser externe Takt nicht auf den 8Mhz-Takt 
synchronisiert war, konnte er sich also zeitlich beliebig zum 8MHz-Takt 
verändern. Deswegen kam es hin und wieder zu Verletzungen  von 
Setup/Hold-Zeiten der Zählerregister, abhängig von internen Laufzeiten 
zu den Zählerregistern und natürlich der Phasenlage des externen Taktes.

Also mußte ich natürlich das externe Signal auf den 8Mhz-Takt 
synchronisieren. Warum ? Damit der Wert des externen Taktes sich um die 
steigende Flanke des 8MHz-Taktes herum nicht ändert, damit weder die 
Setup-Zeit (also vor der steigenden Flanke des 8MHz-Taktes) als auch die 
Holdzeit (nach der steigenden Flanke des 8MHz-Taktes) nicht verletzt 
werden. Also muß man doch logischerweise mit der invertierten Flanke des 
8MHz-Taktes synchronisieren, damit der Wert des externen Taktes, der in 
das Zähler-Schaltwerk geht, sowohl vor als auch nach der steigenden 
Flanke des 8MHz-Taktes stabil bleibt. Also insgesamt jeweils eine 
8Mhz-Periode, eine halbe vor, eine halbe nach der steigenden Flanke.

Wenn ich die steigende Flanke zum Synchronisieren nehmen würde, dann
hätte ich doch genau die gleichen unsicheren Verhältnisse wie ohne 
Synchronisation: das externe Signal, jetzt zwar einsynchronisiert, kann 
sich zeitlich um die steigende Flanke des 8Mhz-Taktes herum verändern. 
Abhängig von Laufzeiten zu den einzelnen Registern kommt es also hin und 
wieder zu Zeitverletzungen und somit zu falschen Zählergebnissen.

Mit Synchronisation durch fallende Flanke ist das Fehlverhalten auf alle 
Fälle weg, mit steigender werde ich es noch testen.

Wo bitte liegt denn mein Denkfehler wenn jeder hier behauptet die
Richtung der Flanke zum Einsynchronisieren wäre egal ?

von Klaus F. (kfalser)


Lesenswert?

OK, statisch konfigurierte Multiplexer zum Routen der Signale im CLB 
gibt es schon.
Aber es gibt keine dedizierten, umschaltbare Multiplexer als logische 
Funktion. Alle Funktionen werden in LUTs als Funktion von 4 oder 5 
Eingangssignalen erzeugt.

von Der Besucher (Gast)


Lesenswert?

> Wenn ich die steigende Flanke zum Synchronisieren nehmen würde, dann
> hätte ich doch genau die gleichen unsicheren Verhältnisse wie ohne
> Synchronisation: das externe Signal, jetzt zwar einsynchronisiert, kann
> sich zeitlich um die steigende Flanke des 8Mhz-Taktes herum verändern.
> Abhängig von Laufzeiten zu den einzelnen Registern kommt es also hin und
> wieder zu Zeitverletzungen und somit zu falschen Zählergebnissen.

Wenn dem so wäre, dann würde kein synchrones Design funktionieren, da ja 
immer irgendwelche kombinatorische Logik zwischen 2 FFs steckt.
Bei einem synchronen Design werden alle FFs zur gleichen Zeit getaktet 
(+- einiger hundert ps clock skew). Wenn Setup und Hold Time 
berücksichtigt werden, tritt kein Problem auf. Nur das erste 
Synchronisations-FF kann eine Timing-Violation haben. das kann zu 
Metastabilität führen. Deswegen auch das 2. FF, da man i.d.R annehmen 
kann, dass sich innerhalb einer Taktperiode das erste FF eingeschwungen 
hat (entweder auf den neuen, oder den alten Wert).

Der Besucher

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

Klaus Falser wrote:
> OK, statisch konfigurierte Multiplexer zum Routen der Signale im CLB
> gibt es schon.
> Aber es gibt keine dedizierten, umschaltbare Multiplexer als logische
> Funktion. Alle Funktionen werden in LUTs als Funktion von 4 oder 5
> Eingangssignalen erzeugt.

Und wie ist es bei diesen FPGAs von Actel, welche die Logik 
ausschliesslich mit Multiplexern erzeugen und gar nicht über SRAM 
verfügen?

von Klaus F. (kfalser)


Lesenswert?

Ach ja, die gibts auch noch ...
I'm a Xilinx guy ...

von Morin (Gast)


Lesenswert?

> Nunja, bei FPGAs bringt es dann wohl nichts. Aber da keine LE mehr
> verwendet wird und funktional identisch ist, ist es auch sicherlich kein
> Fehler.

Das hat nichts mit FPGAs zu tun:

> Im Standardzellenentwurf sparen solche Tricks jedenfalls
> wertvolle Fläche.

Dito bei FPGAs, aber die Tools machen solche Umformungen im Hintergrund 
ohne dass du dich drum kümmern musst. Und das schon seit Jahren.

> Aber hier wird wohl nur über HDL in programmierbare Logik diskutiert?

Da scheinst du der einzige zu sein, der das so sieht.

von Morin (Gast)


Lesenswert?

> Deswegen kam es hin und wieder zu Verletzungen  von
> Setup/Hold-Zeiten der Zählerregister, abhängig von internen Laufzeiten
> zu den Zählerregistern und natürlich der Phasenlage des externen Taktes.

Richtig. (genauer: Das ist eine begründete Vermutung für die Ursache des 
Problems. Für andere Vermutungen siehe z.B. meinen Kommentar über das 
Entprellen)

> Also mußte ich natürlich das externe Signal auf den 8Mhz-Takt
> synchronisieren. Warum ? Damit der Wert des externen Taktes sich um die
> steigende Flanke des 8MHz-Taktes herum nicht ändert, damit weder die
> Setup-Zeit (also vor der steigenden Flanke des 8MHz-Taktes) als auch die
> Holdzeit (nach der steigenden Flanke des 8MHz-Taktes) nicht verletzt
> werden.

Auch richtig.

> Also muß man doch logischerweise mit der invertierten Flanke des
> 8MHz-Taktes synchronisieren, damit der Wert des externen Taktes, der in
> das Zähler-Schaltwerk geht, sowohl vor als auch nach der steigenden
> Flanke des 8MHz-Taktes stabil bleibt. Also insgesamt jeweils eine
> 8Mhz-Periode, eine halbe vor, eine halbe nach der steigenden Flanke.

Das ist zwar keine falsche Lösung, aber auch nicht die beste. Zwei 
hintereinandergeschaltete FFs können ein Datensignal durchreichen, ohne 
dass Setup- / Hold-Zeiten verletzt werden. Auch die 2 Synchro-FFs 
können, wenn sie einfach vor den Zähler gehängt werden und mit dem 
nichtinvertierten Takt betrieben werden, das Datensignal richtig 
durchgeben. Setup-/Hold-Zeiten sind bei gleichphasig angesteuerten 
Registerketten keim Problem (passiert ja im FPGA drinnen auch die ganze 
Zeit).

Der einzig kritische Fall ist nur, wenn das Eingabesignal die 
Setup-/Hold-Zeit des ersten FFs verletzt. Dass das ein vorgeschaltetes 
Synchro-FF sein sollte ist klar, damit der Zähler nicht 
durcheinanderkommt. Aber auch so kann das Synchro-FF metastabil werden, 
d.h. einen Zwischenwert zwischen 0 und 1 speichern und weitergeben. 
Einen Takt später kann dann prinzipiell das zweite Synchro-FF den 
Zwischenwert übernehmen, und noch einen Takt später kommt es beim Zähler 
an -> Sense.

Der Zwischenwert ist aber nicht stabil, sondern tendiert dazu, 
"umzukippen", d.h. das Register "fällt" in den 0- oder 1-Zustand. Die 
Wahrscheinlichkeit für das Umkippen steigt radikal mit der Vergangenen 
Zeit. Schaltet man mehrere Synchro-FFs hintereinander, so sinkt die 
Wahrscheinlichkeit, dass der Zwischenzustand das Ende der Kette erreicht 
exponentiell mit der Kettenlänge. Deshalb 2 Synchro-FFs statt nur 1.

Kippen die Synchro-FFs rechtzeitig um, so macht das gleichphasige 
Ansteuern von Synchro-FFs und Zähler kein Problem. Kippen sie nicht 
rechtzeitig um, hilft gegenphasiges Ansteuern auch nicht. ABER: Das 
gegenphasige ansteuern reduziert die Zeit zum Umkippen auf 1/2 
Taktperiode statt einer ganzen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Also insgesamt jeweils eine 8Mhz-Periode, eine halbe vor,
> eine halbe nach der steigenden Flanke.
Innerhalb des FPGAs hat jedes einzelne  FF das Problem, dass sich kurz 
nach dem Takt die Daten an seinem Eingang ändern (angeschlossen über 
z.B. nur einen Draht, ohne Logik, an den Ausgang des vorhergehenden 
FFs).
D.h. die FFs benötigen nur eine sehr kurze Hold-Zeit.
Dann bleibt für das ganze FPGA wieder ein ganzer Takt Zeit, bis sich die 
Logik mit den neuen Werte z.B. für SM und Zähler beruhigt hat.
Dann kommt wieder ein Takt.

Wenn du die Hold-Zeit auf Kosten der Setup-Zeit für die Eingangs-FFs 
änderst, bleibt es innerhalb des FPGAs trotzdem gleich.

> Also insgesamt jeweils eine 8Mhz-Periode, eine halbe vor,
> eine halbe nach der steigenden Flanke.
Das müsstest du ja dann auch innerhalb des FPGAs für jede FF-Stufe 
alternierend machen. Nein, für den Anfang einfach:
Ein (1) Takt mit einer (1) aktiven Flanke und kein (globaler und/oder 
asynchroner) Reset.

von ArminD (Gast)


Lesenswert?

Der Vollständigkeit halber: die Schaltung funktioniert mit
Sync über die positive Flanke. Nochmals Danke für die Erklärungen.

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.