Ich hätte ein Problem mit der VHDL-Synthese bei Quartus:
Ich bauen einen Datenlogger eines Microcontrollers in einem FPGA, der
mit 20MHz läuft (LowPower System). Dessen 8Bit Werte müssen seriell
ausgegeben werden. Die laufen jetzt mit 8/10-codierung, deshalb gibt es
einen 200MHz-Takt, der das macht. Beide Datenströme sind kontinuierlich
ohne Pause.
Die Übergabe an den FPGA erfolgt durch den uc mit dem 20 MHz-Takt. Der
FPGA macht noch andere Sachen, arbeitet aber mit 20MHz.
Mit den 20MHz werden die 200MHz erzeugt, der somit alle 10 Takte mit der
Flanke des 200ers theoretisch identisch ist. Selbe PLL.
Ich bekomme jetzt natürlich das übliche Timingproblem. Der Synthesizer
meckert 0,2ns an, die er von Langsam zu Schnell nicht packt.
Wie kann ich das am Einfachsten entschärfen?
Inorieren möchte ich es nicht, weil wer weiss, wie die Takte wirklich
aussehen. Kann ich das mit einem MAX-Delay hinbekommen? Ich nehme an,
nicht, weil die Zeit nicht reichen wird, auch wenn ich versuche, den
200er um einen halben Takt zu schieben, dass die Flanken sich nicht
sehen.
Ich simple Lösung, alles mit 200MHz laufen zu lassen und enables zu
verwenden, scheidet aus. Wegen Power.
Die "normale" Lösung, einen asynchronen Fifo dran zu setzen, bläht das
design auf. Ich möchte lieber einen kleinen Puffer per Hand schreiben,
den ich n mal instanziiere (den Erzeuger gibt es 16 mal).
Wie müsste der arbeiten? Ich nehme an einen Wechselpuffer und den so
schreiben und lesen, dass sich die Takte aus dem Weg gehen?
Wie constraine ich den?
Berti schrieb:> Ich bekomme jetzt natürlich das übliche Timingproblem. Der Synthesizer> meckert 0,2ns an, die er von Langsam zu Schnell nicht packt.
Das ist nach deiner Schilderung weder natürlich noch üblich. Nach deiner
Schilderung sollte es kein constraint auf 200 ps geben und natürlich
meckert nicht die Synthese sondern die STA oder ggf Mapper/Fitter...
Setzt doch bitte mal das Logfile als Anhang hier rein das dürfte die
wichtigsten Fragen (FPGA-Typ, gesetzte constraints, Nutzung von IOB,
...)
beantworten.
--
>Die "normale" Lösung, einen asynchronen Fifo dran zu setzen, bläht das>design auf. Ich möchte lieber einen kleinen Puffer per Hand schreiben,>den ich n mal instanziiere (den Erzeuger gibt es 16 mal).
Neee, deine unfachmännische von Hand Lösung und Verniedlichung der
Problems mit Gänsefüßchen und "Üblich, natürlich, ullalla" bläht das
Problem auf.
Es ist nicht ganz klar was du überhaupt brauchst, wenn du nich
beschreibst wie die Gegen-Schnittstelle am µC aussieht.
Berti schrieb:> Synthesizer meckert 0,2ns an
Der Synthesizer? Nicht eher der Router?
> Synthesizer meckert 0,2ns an, die er von Langsam zu Schnell nicht packt.
Hört sich irgendwie an, als ob da schlimmstenfalls ein Registersatz als
"Fifo" dazwischen müsste. Oder was ist denn an Kombinatorik in dieser
Übergabe von "langsam" nach "schnell" mit drin?
Berti schrieb:> Mit den 20MHz werden die 200MHz erzeugt, der somit alle 10 Takte mit der> Flanke des 200ers theoretisch identisch ist. Selbe PLL.
Das ist etwas das du weisst, bzw. sicherstellst durch die Konfiguration
der PLL.
Der Synthesizer bzw. der Router weiss das dann aber (in den meisten
Tools) noch nicht.
Synplify kennt dazu eine "create_generated_clock" Constrained. Weiss
gerade nicht, ob andere Tools die auch kennen oder andere Methoden haben
um phasenstarre Clocks zu constrainen. (Du willst das Tool auch dazu
bringen, diese Clocks so zu Routen, dass du im Design annehmen kannst,
dass sie phasenstarr sind)
> Ich bekomme jetzt natürlich das übliche Timingproblem. Der Synthesizer> meckert 0,2ns an, die er von Langsam zu Schnell nicht packt.
[...]
> Die "normale" Lösung, einen asynchronen Fifo dran zu setzen, bläht das> design auf. [...]> Wie constraine ich den?
Mit "false_path" können Pfade aus der Timinganalyse ausgeklammert
werden. Damit wird dem Tool gesagt, dass du als Entwickler
sichergestellt hast, dass dieser Taktdomänenübergang 1. gewollt ist und
2. untersucht wurde, dass die gewählte Implementation passend ist.
Teilweise sieht man dann eine false_path Constraint in etwa so:
false_path -from clk20 -to clk200
Das ist zwar die Variante die wenig Aufwand gibt, aber nach meiner
Meinung unsauber. Es kann dazu führen, dass fehlerhafte Taktübergänge
unentdeckt bleiben.
Lothar M. schrieb:> Berti schrieb:>> Synthesizer meckert 0,2ns an> Der Synthesizer? Nicht eher der Router?
Synthesizer UND Router :-) Jedenfalls wenn man Synplify einsetzt, der
macht über das synthetisierte Design schon mal eine komplette
Timinganalyse bzw. optimiert danach und braucht entsprechend schon alle
Timingconstraints die der Router auch benötigt.
Lothar M. schrieb:>> Synthesizer meckert 0,2ns an, die er von Langsam zu Schnell nicht packt.> Hört sich irgendwie an, als ob da schlimmstenfalls ein Registersatz als> "Fifo" dazwischen müsste.
Bei 0.2 Nanosekunden passt kein Register dazwischen. O.2 Nanosekunden
wären 5 GHz Frequenz, ich schätze, da hat der TO einen ganz blöden
Fehler gemacht oder die Fehlermeldung Sinnentstellend wiedergegeben. Der
soll mal bitte,bitte den originalwortlaut der Fehlermeldung und seine
Constrained hier nennen.
Christoph schrieb:> Synplify kennt dazu eine "create_generated_clock" Constrained.
wenn im .sdc File ein "derive_pll_clocks"-Statement steht (was
normalerweise der Fall ist), macht Quartus das von ganz alleine.
Christoph schrieb:> Mit "false_path" können Pfade aus der Timinganalyse ausgeklammert> werden.
Das Statement heißt "set_false_path" und hat hier nichts verloren. Bei
einem Taktdomänenübergang, wo der eine Takt ein exaktes, synchrones
Vielfaches des anderen ist, muss man Quartus mit multicycles
(set_multicycle_path) "erklären", dass man selbst darauf achtet (z.B.
mit clock enables), dass die relevante Flanke nur an den Stellen kommt,
wo die andere Seite sie auch wahrnehmen kann.
Bit Spalter schrieb:> Bei 0.2 Nanosekunden passt kein Register dazwischen. O.2 Nanosekunden> wären 5 GHz Frequenz, ich schätze, da hat der TO einen ganz blöden> Fehler gemacht oder die Fehlermeldung Sinnentstellend wiedergegeben.
Die 0,2ns könnten aus der Jitteranalyse kommen. Ich hatte 100ps für
beide Takte gesetzt. Das ist nämlich mein Problem: Takte haben übers
FPGA unterschiedliche Laufzeiten und wegen jittering kommt der schnelle
Takt nur theoretisch (nicht aber praktisch1) ganz exakt auf derselben
Flanke.
Oder wird das berücksichtigt?
Nehmen wir an, das wäre irgendwie mit drin. Tatsache ist, dass das
timing nicht eingehalten wird. Das false path hilft mir ja nicht weiter.
Soweit war ich auch schon. Ich bräuchte einen Tipp, wie ich es bauen
muss? Brauche ich grey counter wie in den original FIFOs?
Oder reicht ein einfacher Wechselbuffer, links schreiben, rechts lesen
und bei Lesen der letzen Bits ist links schon geschrieben?
1
WriteReadSend
2
3
0LEFTRIGHT0"0"-start
4
1RIGHT1RIGHT0
5
2
6
3
7
4
8
5
9
6
10
7RIGHT7RIGHT6
11
8..RIGHT7
12
9.."1"-stopp
13
0RIGHTLEFT0"0"-start
14
1LEFT1LEFT0
15
2
16
3
17
4
18
5
19
6
20
7RIGHT7RIGHT6
21
8..RIGHT7
22
9.."1"-stopp
Meine Befürchtung ist, dass das Einschreiben auf den Buffer etwas zu
früh(zu spät) kommt, wenn der andere beim Wechseln zu spät(zu früh) ist
und gerade schon (noch) auf das falsche Byte schaut.
Aber angenommen, das geht trotzdem: Was verpasse ich dem Schreibetakt?
Ein multi cycle ist es irgendwie nicht, weil das in nächste
Schreibfenster hineingeht? So lange darf es nicht dauern. In einer
echten Schaltung hätte ich einfach den umgekehrten Takt zum Schreiben
genommen, aber falling_edge möchte ich nicht einsetzen.
Berti schrieb:> Wie müsste der arbeiten?
Der müsste trotzdem arbeiten, wie ein asynchroner FiFo.
> Ich nehme an einen Wechselpuffer
oder auch 3 oder noch mehr, wenn es die Takt/-Frequenz-Konstellation
erfordert. In deinem Fall reicht sicher ein Doppelregister und Lesen
nach dem gesampelten! fallenden Schreibtakt.
> Wie constraine ich den?
MAXPPATHDELAY von z.B. 0,75 Takten z.B.
Berti schrieb:> Oder wird das berücksichtigt?
Der Jitter wird selbstredend mit in Betracht gezogen, taucht an der
Stelle aber nicht auf. Das ist eine offset-Verschiebung. Gfs Taktquelle
<-> PLL.
> Meine Befürchtung ist, dass das Einschreiben auf den Buffer etwas zu> früh(zu spät) kommt, wenn der andere beim Wechseln zu spät(zu früh) ist> und gerade schon (noch) auf das falsche Byte schaut.
Das passiert nur, wenn der Lesetakt genau auf das Datum wechselt, das
geschrieben wurde und auch dann hat man noch das budget der Periode - x.
Das gleiche gilt für die Gegenbetrachtung. Wenn die Takte aus
unterschiedlichen Quellen kommen und gleich groß sind, hat man das
Problem.
Berti schrieb:> Ein multi cycle ist es irgendwie nicht, weil das in nächste> Schreibfenster hineingeht?
Vielleicht verstehe ich ja nicht, was Du eigentlich treibst, aber nach
meinem Verständnis hast Du ein Schieberegister, das mit 200 MHz getaktet
ist. Von den 10 Bit Daten, die Du empfängst, sind nur 8 echte Nutzdaten,
Du solltest dir beim Auslesen von der "langsamen" Seite aus also
eigentlich zwei zusätzliche "schnelle" Takte Zeit lassen können, während
denen sich die Daten nicht ändern?
Das hätte ich als hold-multicycle gesehen.
Das stimmt, sehe ich jetzt auch. Durch die 10/8 Codierung habe ich sogar
vorn und hinten einen Takt am Ausgang frei zum Wechseln eines Puffers.
Nur wie macht man es, wenn es nicht der Fall ist? Ist das wirklich kein
Problem mit den überlappenden Takten?
Ein Multi Cycle Constraint entspannt doch einfach nur die Takt Situation
und gibt dem Router freie Hand.