Ich arbeite mit verschiedenen Chips von Lattice mit Lattice Diamond und
hätte gerne etwas Orientierung, welche Constraints für asynchrone Inputs
notwendig sind. Mir geht es weniger um einen spezifischen Fall als eher
um ein "how to it right".
Leider ist die Dokumentation von Lattice spärlich bis nicht vorhanden
bzw. das was ich gefunden habe enthält nicht wirklich praktische
Beispiele.
Eine gute Quelle diesbezüglich, die auch auf Lattice spezifische Details
eingeht, wäre wirklich hilfreich.
Für asynchrone Eingänge verwende ich typischerweise einen zweistufigen
Synchronizer (asynchrones Eingangssignal: input, synchronisiertes
Ausgangssignal: output(1)):
1
process(clk,rst)
2
begin
3
ifrst='0'then
4
output<=(others=>'0');
5
elsifrising_edge(clk)then
6
output<=output(0)&input;
7
endif;
8
endprocess;
Die Eingangssignale sind sehr unterschiedlich und reichen von
mechanischen Inputs (weniger als 1 Flanke pro Sekunde) zu read/write
Handshake Signalen eines parallelen Memory Bus, die nur einige Sample
Clock Cycles lang sind.
Die Fragen die ich mir Stelle sind:
- Muss ich hier keep Attribute im Code verwenden damit die Toolchain die
Flipflops nicht wegoptimiert? Falls ja, wie würden diese aussehen?
- Wie verhindere ich, dass bei hohem Fanout die Flipflops dupliziert
werden, insbesondere das erste Flipflop output(0)? Gibt es dafür
überhaupt eine Möglichkeit?
- Welche Timing Constraints benötige ich bzw. benötige ich überhaupt
welche? Muss ich den Einfang als false path definieren?
Was passiert mit Eingängen, die im Constraint File weder als false path
definiert sind, noch setup/hold constraints haben? Werden die einfach
als asynchron angenommen und in der STA ignoriert?
- Habe ich irgendwelche Constraints übersehen die notwendig wären?
Hi,
warum willst du an das asynchrone Signal ein Constraint machen? Das
Signal bleibt doch asynchron, heißt es hat keinen Bezug zum Clock. Das
kannst du dir sparen.
Deinen Prozess für das Einsynchronisieren würde ich anders machen:
1
process()
2
begin
3
waituntilrising_edge(clk);
4
ifrst='0'then
5
output<=(others=>'0');
6
else
7
output<=output(0)&input;
8
endif;
9
endprocess;
Bei deiner Version bleibt der Reset asynchron. Das macht bei der
Synthese Probleme und bringt dir die tollsten Effekte, die du
stundenlang suchst.
Grüße, Jene
Ist halt die Frage, was du mit constraints erreichen kannst, in der
Regel halt nur das Placement der FF und das ist hier eher egal.
Es gibt je nach Hersteller spezielle Constraints für IO's, wie
IO-Standard oder Pull/UP/Down da sollte man mal reinschauen, ob man was
braucht.
Und mancher timing analyse muss man extra sagen, das dieser Eingangspfad
asynchron ist - mit einem "false_path" constraint.
Für synchronizer wird manchmal empfohlen, das timing constraint zwischen
diesen (bei dir (0) und (1) eng zu machen) das reduziert nochmals die
Wahrscheinlichkeit des reinwanderns eines Metastabilen Zustandes. Die
ist aber schon bei einem einfachen Snchronizer sehr gering.
Wichtiger ist die funktionale Beschreibung, also der VHDL/Verilog-Code,
also nicht das nachgeschaltete debouncing vergessen.
https://nandland.com/project-4-debounce-a-switch/
Was den reset betrifft, hier vielleicht komplett weglassen ?! Oder
weningtens für den aller ersten (bei dir output( 0))?!. Das ist ja eine
Input-line, da kann und soll sowieso alles mögliche reinkommen. Und
schau dir mal die Schaltung des IO-Pads an (Anhang) gibt es da eine
reste-line?! Ohne Reset kann das synthesetool für den synchronizer auch
Shiftregister verwenden. Wichtig ist, das die nachfolgende Schaltung
nicht ausser Tritt kommt.
* https://www.fdi.ucm.es/profesor/mendias/DAS-ise-spartan/docs/wp272.pdf
* https://docs.amd.com/v/u/en-US/wp275
Und es kann je nach Herstelelr/fpga-typ einen Unterschied aus machen, ob
man asynchronen oder synchronen Reset verwendet.
IO-PAD -FF ist auch so ein Thema, möglicherweise auch bei Lattice. Man
sollte versuchen, das physisch erste FF zu benutzen, also das im Pad, Da
gibt es manchmal constraints um das zu erzwingen, da muss man mal zur
Kontrolle im Routing/Report nachschauen.
Diode E. schrieb:> - Muss ich hier keep Attribute im Code verwenden damit die Toolchain die> Flipflops nicht wegoptimiert?
Nein.
> - Wie verhindere ich, dass bei hohem Fanout die Flipflops dupliziert> werden, insbesondere das erste Flipflop output(0)?
Man kann schauen ob das Signal auf ein 'global net' geführt wird. Das
steht im Synthesereport unter 'Global Clocks', auch wenn es kein
Taktsignal ist.
Oder man macht die FF-Kette bewußt länger und läßt
Registervervielfachung zu (Remove Duplicate Registers = FALSE).
> - Welche Timing Constraints benötige ich bzw. benötige ich überhaupt> welche?
Solange das externe Signal keinen Bezug zum Takt hat, braucht es kein
Constraint:
https://www.latticesemi.com/en/Blog/2021/06/07/18/52/ImportanceofTimingConstraints> Eine gute Quelle diesbezüglich, die auch auf Lattice spezifische Details> eingeht, wäre wirklich hilfreich.
Das angehängt Dokument hatte ich mal aus dem Netz gefischt. Vielleicht
hilft es Dir ja.
Danke für die Antworten. Um die Reset Problematik werde ich mich separat
kümmern, vieles davon habe ich zumindest schon mal gehört.
Rick D. schrieb:> Diode E. schrieb:>> Muss ich hier keep Attribute im Code verwenden damit die Toolchain die>> Flipflops nicht wegoptimiert?>> Nein.
Ich glaube dir das, aber findet man diese Information irgendwo? Das
Dokument von Lattice kenne ich und habe ich durch, den Link auf die
Lattice Page auch. Da steht in meinen Augen nichts explizit zu
asynchronen Eingängen drin, oder übersehe ich das? Die grundlegenden
Befehle für synchrone Inputs kenne ich, es scheitert dann oft an den
Details (vor allem: wo finde ich die Namen der benötigten Netze auf die
ich Constraints anwenden soll?).
Ich verwende solche 'Spezial'-Constraints verhältnismäßig sparsam.
Wichtig ist der Takt und logischerweise die Pinzuordnung.
Außerdem will Lattice immer wissen mit welcher Spannung ich die IOs
betreibe.
Ab- und zu kommt noch DRIVE/PULLMODE/SLEWRATE hinzu.
Ich kann mich nicht erinnern, daß mir der Synthesizer schon mal Logik
wegoptimiert hat, die gebraucht wurde.
Diode E. schrieb:> Da steht in meinen Augen nichts explizit zu> asynchronen Eingängen drin, oder übersehe ich das?
Richtig. Für asynchrone Signale gibt es einfach keine Constraints, nur
für synchrone.
> (vor allem: wo finde ich die Namen der benötigten Netze auf die> ich Constraints anwenden soll?)
Öhm, die Namen für die IO-Ports legst Du doch selbst fest.
Ansonsten schaut man aufmerksam durch die verschiedenen Synthesereports
oder öffnet das Design im 'Netlist Analyzer' oder im 'Netlist Viewer'.
Wenn das alles nicht hilft, suchst Du Dein Netz im 'Physical View'.
Hier als Beispiel ein Ausschnitt aus einem Map-Report:
1
Number of clocks: 1
2
Net clk_c: 317 loads, 317 rising, 0 falling (Driver: PIO clk )
3
Number of Clock Enables: 6
4
Net N_53: 32 loads, 0 LSLICEs
5
Net un1_state_15_0_i: 75 loads, 59 LSLICEs
6
Net un1_state_9_0_i: 7 loads, 7 LSLICEs
7
Net state_22_d: 79 loads, 79 LSLICEs
8
Net un1_state_14_0_i: 91 loads, 75 LSLICEs
9
Net state_21_d: 9 loads, 9 LSLICEs
10
Number of LSRs: 4
11
Net state_d[13]: 19 loads, 19 LSLICEs
12
Net state[0]: 1 loads, 0 LSLICEs
13
Net quadrant_0_sqmuxa: 1 loads, 1 LSLICEs
14
Net quadrant_0_.fb: 1 loads, 1 LSLICEs
15
Number of nets driven by tri-state buffers: 0
16
Top 10 highest fanout non-clock nets:
17
Net x_pipe_2: 114 loads
18
Net state_22_d: 97 loads
19
Net un1_state_14_0_i: 91 loads
20
Net state[0]: 84 loads
21
Net un1_state_15_0_i: 75 loads
22
Net N_1039: 67 loads
23
Net state[1]: 59 loads
24
Net gain[1]: 57 loads
25
Net re_cf[15]: 51 loads
26
Net gain[7]: 48 loads
Falls Du wirklich ein Problem mit wegoptimierten Netzen bzw. Logik hast,
liegt es vermutlich schlicht und ergreifend daran, daß die Ausgänge aus
dieser Logik nicht verwendet werden oder einen konstanten Wert
darstellen.