Forum: FPGA, VHDL & Co. Altera Fitter igoriert Constraint


von Mäxle Delay (Gast)


Lesenswert?

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)

von P. K. (pek)


Lesenswert?

Ich mache es jeweils so, dass ich entsprechende Register in separate 
Entities isoliere und dann mit folgenden Attributes arbeite:

In:
1
  attribute altera_attribute          : string;
2
  attribute altera_attribute of InxD  : signal is "-name FAST_INPUT_REGISTER ON";

Out:
1
  attribute altera_attribute          : string;
2
  attribute altera_attribute of OutxD : signal is "-name FAST_OUTPUT_REGISTER ON";

Natürlich darf zwischen dem Pad und dem Register keine Logik sein...

von T.U.Darmstadt (Gast)


Lesenswert?

Das ging doch mit dem Constraint Editor selber per "Fast Output", bzw 
"Fast Output Enable" Register, wenn es ein Buffer war.

von P. K. (pek)


Lesenswert?

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.

von Mäxle Delay (Gast)


Lesenswert?

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.

von Sigi (Gast)


Lesenswert?

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?

von Mäxle Delay (Gast)


Lesenswert?

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
  if reset = '0' then
4
    addr_x <= (others => '0');  
5
    ....
6
  elsif rising_edge(clk50) then
7
    addr_x <= addr;
8
    ...
9
  end if;
10
end process;


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.

von Sigi (Gast)


Lesenswert?

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.

von Mäxle Delay (Gast)


Lesenswert?

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.

von Mäxle Delay (Gast)


Lesenswert?

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_q when (OEn = '0' and CSn = '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?

von Da D. (dieter)


Lesenswert?

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:
1
set_multicycle_path -setup -from [get_ports {OEn CSn}] -to [get_ports {data*}] 3
2
set_multicycle_path -hold  -from [get_ports {OEn CSn}] -to [get_ports {data*}] 2

von Mäxle Delay (Gast)


Lesenswert?

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?

von Sigi (Gast)


Lesenswert?

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

von Ich (Gast)


Lesenswert?

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.

von Sigi (Gast)


Lesenswert?

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!

von Mäxle Delay (Gast)


Lesenswert?

Vielen Dank schonmal für die Infos.

Ich werde mir das mal zu Gemüte führen. Allerdings komme ich heute nicht 
mehr dazu.

von Mäxle Delay (Gast)


Lesenswert?

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......?

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.