Hallo zusammen,
ich habe für einen Altera Cyclone V folgendes Constraint vorgegeben:
set_max_delay -from [get_ports {PORTNAMEN}] -to [get_registers *] 5.000
Die Ports sind asynchron zum internen Takt.
Mit diesem Constraint sollte doch vorgegeben sein, dass das Signal vom
Port bis zum ersten Register maximal 5ns dauern darf.
Quartus könnte die Register der IO-Cell verwenden und damit dieses
Constraint einhalten. Stattdessen platziert es die Register mitten in
den Chip und reportet, dass das Constraint nicht gehalten wird.
Wie kann ich den Fitter dazu bewegen, die Register der IO-Cell zu
verwenden? (außer manuelles Platzieren)
Thomas U. schrieb:> Das ging doch mit dem Constraint Editor selber per "Fast Output", bzw> "Fast Output Enable" Register, wenn es ein Buffer war.
Natürlich kannst Du das auch mit dem Constraint Editor machen.
Ich finde es einfach bequemer, wenn ich das entsprechende Register
einfach per Entity im Design drin habe, ohne mich dann noch kümmern zu
müssen wie der Pfad nun im Detail heisst und wo ich wieder was im
GUI-Klicki-Bunti setzen muss.
Hallo!
Vielen Dank! Der Hinweis hat mich auf die richtige Fährte gebracht.
Habe im QSF-File FAST_INPUT_REGISTER auf ON gestellt und nun sind die
Register da, wo sie sein sollten.
Aber mal ehrlich: Der Fitter ist ja schon ein bisschen doof, oder?
Wenn ich ihm eine maximale Zeit vorgebe, dann würde ich erwarten, dass
er weiss, dass der Chip IO-Register hat und dann von selbst auf die Idee
kommt, diese zu verwenden.
Mäxle Delay schrieb:> Aber mal ehrlich: Der Fitter ist ja schon ein bisschen doof, oder?> Wenn ich ihm eine maximale Zeit vorgebe, dann würde ich erwarten, dass> er weiss, dass der Chip IO-Register hat und dann von selbst auf die Idee> kommt, diese zu verwenden.
Doof ja, er arbeitet ja nur "mechanisch". Aber IO-Zellen
kennt er schon und nutzt sie auch. Es muss also an Deiner
HDL-Beschreibung liegen. Stell sie doch mal hier rein,
evtl. auf's notwendige gekürzt. Dann kann man Dir erkären,
woran es lag.
Meine Vermutung: eine oder mehrere Register werden noch
durch Logik angesteuert. Ob er dann aber den Versuch
komplett abbricht, keine Ahnung?
Es sind wirklich nur ganz einfache Sample-Register ohne jegliche Logik
drumrum. Selbst der Reset ist asynchron, da hier bei einer
Setup-Violation nichts passieren kann. Primitiver geht es eigentlich gar
nicht.
Hier mal der vereinfachte Code:
addr_x ist das Register, addr ist der Eingang
1
process(clk50,reset)
2
begin
3
ifreset='0'then
4
addr_x<=(others=>'0');
5
....
6
elsifrising_edge(clk50)then
7
addr_x<=addr;
8
...
9
endif;
10
endprocess;
Ich habe leider schon öfter die Erfahrung gemacht, dass der Fitter von
Altera nicht gerade mit Intelligenz gesegnet ist.
Er hat mir schon einmal nen Pfad von einem Pin zu einem Register kreuz
und quer über den gesamten Chip geroutet.
Mäxle Delay schrieb:> Selbst der Reset ist asynchron,..
Also direkt vom Pin getrieben?
Aber in Deinem Code wird Reset mit '0'
verglichen, d.h. da hast Du erstens schon
mal Logik. Und dann musst Du verstehen,
dass dieses Reset-Signal ja für alle
addr_x-Register verwendet wird. Das ganze
ist also nur innerhalb des FPGA synthbar.
Sigi schrieb:> Also direkt vom Pin getrieben?
More or less..
Ne Kombinatorik aus LOCK der PLL und externem Pin.
Sigi schrieb:> Aber in Deinem Code wird Reset mit '0'> verglichen, d.h. da hast Du erstens schon> mal Logik.
Im Code ja, aber letztendlich wird einfach nur der asynchrone Reset des
Registers mit dem Reset-Signal verdrahtet. Also keine Logik
Sigi schrieb:> Und dann musst Du verstehen,> dass dieses Reset-Signal ja für alle> addr_x-Register verwendet wird.
Genau so ist es ja auch gewünscht. Für jede Adressleitung ein Register,
dessen ASYNC-Eingang mit dem Reset-Signal beaufschlagt wird.
Sigi schrieb:> Das ganze> ist also nur innerhalb des FPGA synthbar.
Da soll es ja auch hin ;-)
Zusammegefasst kann ich sagen:
Durch Aktivieren von FAST_INPUT_REGISTER macht der Fitter genau das, was
ich von ihm erwartet habe. Er baut in der FPGA-Fabric einen
kombinatorischen, asynchronen Reset und führt diesen an den RST-Eingang
der Register in den IO-Cells. An die D-Eingänge der Register wird dann
das jweilige Pad angeschlossen.
Der Chip "kann" also, was ich will. Nur der Fitter ist zu doof, trotz
knappem Constraining des Pfades zwischen Pad und Register von selbst auf
die Idee zu kommen, das IO-Register zu benutzen.
Ich glaube, der Altera Fitter ist wirklich doof, oder was mache ich
falsch?
Folgender concurrend Code (Teil eines asnychronen Bus-Interface):
1
-- Tristate the Output-Pin
2
data<=rd_data_qwhen(OEn='0'andCSn='0')else
3
(OTHERS=>'Z');
Der virtuelle Takt für die externen Signale beträgt 200 Mhz
und für den Pfad ist ein Multicycle von 3 constrained.
SDC:
create_clock -name virtual_clk -period 5
set_multicycle_path -from [get_ports {OEn CSn}] -to [get_ports {data*}]
3
Der Pfad dürfte also maximal 15ns lang sein (3 * 5ns)
Die Logik kann in einer LUT abgevespert werden und die Pins liegen
räumlich nahe beieinander.
Sollte also locker zu schaffen sein.
Das Ergebnis ist allerdings haarsträubend:
Fast 30ns werden für diesen lächerlichen Pfad benötigt.
Die Betrachtung im Chip-Planner ergibt, dass in der Tat auch nur eine
LUT herangezogen wird und der Rest für´s Routing drauf geht.
Mit der Option "Show Routing" im Chip Planner wird dann das Drama
sichtbar. Das Signal wird kreuz und quer über den gesamten Chip hin und
her geroutet.
Die Zeitvorgabe von 15ns ist eigentlich relativ relaxed und sollte gut
zu schaffen sein. Aber der Fitter/Router zieht es vor, das Signal wild
über den ganzen Chip zu Routen und dann eine Setup-Violation zu melden.
Hat jemand von euch sowas auch schon mal beobachtet?
Das liegt daran, dass du kein Multicycle für die Hold-Beziehung
angegeben hast. Dadurch hat der Fitter absichtlich lange Routing delays
eingefügt, um das Hold-Timing zu schaffen. Bei set_multi_cycle kann man
mit -hold und -setup angeben, ob man den Wert für die Setup oder
Hold-Beziehung angeben möchte. Wenn man nichts angibt ist es automatisch
Setup.
Versuch mal folgendes:
Danke, Da Dieter.
Ich habe das gerade geändert und lasse alles nochmal durchlaufen.
Das dauert jetzt leider ne Weile.
Letztendlich macht mir hier generell Probleme, dass ich nicht weiss, wie
ich einen asynchronen Pfad constraine.
Das betrifft rein kombinatorische Pfade, als auch Pfade von Pads zu den
Sampleregistern.
So wie es sich für mich darstellt, kann Timequest einfach nichts
asynchrones berechnen, sondern es wird immer ein Quell- und ein Zieltakt
benötigt.
Das macht dann solche Pfade wie den o.g. nur constrainbar, indem man mit
einem Takt arbeitet, den es eigentlich gar nicht gibt.
Es würde reichen, wenn man angeben könnte, dass der maximale Delay von X
nach Y eben soundso lang ist.
Genauso ist es mit den Pfaden zu den Sampleregistern.
Ein Asynchroner Eingang, der im Sampleregister synchronisiert wird,
führt an diesem zu Setup- und Hold-Violations, das liegt einfach in der
Natur der Dinge.
Man könnte diese Pfade jetzt als FALSE_PATH constrainen, aber dann gibt
man jegliche Kontrolle ab. Der Pfad könnte dann auch beliebig lange
werden.
Sobald ich aber den Pfad in seiner Länge begrenzen will, geht das nur
über SET_MAX_DELAY oder SET_INPUT_DELAY. Und beide stellen dann aber
einen Phasenbezug vom Pad zum Register her, den es in Wirklichkeit nicht
gibt.
Lässt sich dieses Thema irgendwie elegant lösen?
Mäxle Delay schrieb:> Lässt sich dieses Thema irgendwie elegant lösen?
Such mal nach "Quartus II TimeQuest Timing Analyzer Cookbook",
das ist eine schöne kompakte Einführung in das Thema
Constraints. Dazu noch das Kapitel zu TimeQuest im
Quartus-Manual und Du müsstest wunschlos glücklich
werden(?).
(Im Cookbook werden grundlegende Techniken plus
Prakmatiken vorgestellt, die etwa 99% der allgem.
Probleme abdecken.)
Och Sigi,
genau das machen die von Dir vorgeschlagenen Pamphlete eben nicht. Suche
doch bitte einmal nach dem User RSYC. Hier findest Du nutzbare
Tutorials. Generell bleiben Dir falsepath und multicycle.
Ich schrieb:> genau das machen die von Dir vorgeschlagenen Pamphlete eben nicht.
Stimmt nur zum Teil. Ich habe noch "TimeQuest Terminology and Concepts"
vergessen, ist glaube ich im Quartus Manual enthalten. Trotzdem ist
das Cookbook in diesem Fall sehr hilfreich!
So, ich habe mir das mal angeschaut. Informativ, aber die Frage, die ich
habe, konnte ich damit auch nicht beantworten.
Mir geht es letztendlich um das Handling von asynchronen Eingängen.
Annahme:
An einem Pad kommt ein asynchrones Signal.
Dieses geht auf ein Register und wird dort synchronisiert.
Dann "Verarbeitung" in n Takten
Dann Ausgabe auf ein Pad.
Die Zeit, die das Signal vom Anlegen am Pin, bis zur Ausgabe des
Ergebnis benötigt, soll nun auf einen Maximalwert begrenzt werden.
Die maximal-Zeit setzt sich dann folgendermaßen zusammen:
1.) Signallaufzeit vom Pad bis zum Eingang des ersten Registers
2.) "Unschärfe" durch Abtastung (maximal 1 Systemtakt)
3.) n Takte Verabreitungsdauer
4.) Laufzeit vom Ausgabereigster bis zum Pad.
Die Phasenlage des Taktes zum Signal bzw. der Clock-Skew innerhalb des
FPGA spielen bei dieser Betrachtung keine Rolle. Es ist unrelevant, wie
des Skew des Taktes am 1. Register zur Taktquelle ist.
Und hier liegt mein Problem.
Mit den "klassischen" Methoden wie SET_INPUT_DELAY oder SET_MAX_DELAY
wird immer der Skew des Taktes im FPGA mit berücksichtigt. Und das
verfälscht das Ergebnis.
Wenn ich z.B. die maximale Laufzeit von Punkt 1.) auf 3ns begrenzen
möchte und das mit SET_MAX_DELAY mache, dann wird das immer in Relation
zum Takt gesehen. Ist der Clock-Skew am Sampleregister z.B. 5ns, und die
Signallaufzeit statt der constrainten 3ns z.B. 4ns, dann führt das nicht
zu einer Timing-Violation, da tsu noch gehalten wird.
Sprich: Weder der Fitter/Router ist bemüht, es in den 3ns "hin zu
bekommen", noch Timequest reported eine Violation, da es keine gibt.
Aber dennoch wurde mein "Wunsch", die Signallaufzeit auf 3ns zu
begrenzen, nicht erfüllt.
Bei Xilinx wird sowas über DATAPATHONLY gelöst.
Bei Lattice heißt das Zauberwort DATAPATH_ONLY..
Bei Altera......?