Forum: FPGA, VHDL & Co. TimeQuest PLL clocks lesbar benamsen


von Markus F. (mfro)


Lesenswert?

Hallo allerseits,

wenn man PLL-clocks im .sdc-File definieren will, hat man ja - zumindest 
soweit ich das verstanden habe - zwei Möglichkeiten:

- ganz und gar automatisch:

1
 derive_pll_clocks

-  oder 'von Hand' für jeden Takt:

1
 create_generated_clock -name xxx -source yyy zzz


Wobei Ersteres den Vorteil hat, daß die Taktparameter immer automatisch 
richtig sind (und dafür ebenso automatisch ellenlange, kryptische 
Taktnamen produziert), während man bei Letzterem die Clocks so benamsen 
kann, wie sie auch im Code heißen, aber selber aufpassen muß, daß die 
Parameter stimmen.

Jetzt wollte ich ein Projekt (mit 15 PLL clocks) von Methode 1 auf 
Methode 2 umstellen, weil ich mich ständig mit den kryptischen Taktnamen 
vertan habe (die subtilerweise nicht nur ellenlang sind, sondern sich 
auch noch nur in klitzekleinen Details unterscheiden).

Das funktioniert auch soweit für alle PLL-Takte, allerdings anscheinend 
dann nicht, wenn eine PLL den Ausgang einer anderen PLL als Takteingang 
verwendet (dann wird der Name des gerade definierten Takteingangs für 
die zweite PLL aus irgendeinem Grund nicht gefunden):
1
create_generated_clock -name clk_48 -source clk_main ...
2
create_generated_clock -name clk_video -source clk_48 ... (<- Zeile 64)
1
Ignored filter at xxx.sdc(64): clk_48 could not be matched with a port
2
Ignored create_generated_clock at xxx.sdc(64): Argument -source is an empty collection

Lustigerweise listet ein anschließendes "Report Clocks" clk_48 auf, wie 
wenn nichts gewesen wäre (das Ding ist also durchaus bekannt), aber 
clk_video fehlt natürlich trotzdem.
Die Knotennamen der PLL-Ausgänge stimmen (hab' ich ungefähr 100 Mal 
kontrolliert).

Weiß vielleicht jemand, woran das liegt, bzw. wie ich mein Ziel 
"lesbarer" Taktnamen trotzdem erreichen kann?

P.S.: bevor jemand fragt, ob ich wirklich 15 Clocks brauche: ja, brauch' 
ich.
PPS.: Quartus ist die letzte 13er-Version mit allen verfügbaren Patches.

: Bearbeitet durch User
von Hugo (Gast)


Lesenswert?

Ich lasse die Taktnamen automatisch vergeben und nutze in SDC-Files 
einfach eine Variable die mit dem entsprechenden String vorbelegt wird.

1. Design ohne SDC kompilieren
2. Aus Timequest die Clocknamen herausfinden
3. Variablen für jeden Takt erstellen und mit Wert belegen
4. Variablen nutzen

Ist vielleicht nicht die schönste Variante, dafür muss ich Änderungen 
bei den PLLs nicht mitziehen. Nachteil ist natürlich dass Timequest 
immernoch die kryptischen Namen in der GUI ausgibt.

von Hugo (Gast)


Lesenswert?


von Markus F. (mfro)


Lesenswert?

Hugo schrieb:
> so wie hier:
> http://www.fpgarelated.com/showthread/comp.arch.fpga/63832-1.php

Geht ja nicht (s.o.).

Und die Namensersetzung taugt nur für das .sdc-File - in allen Reports 
stehen immer noch die Rattenschwänze.

Danke trotzdem.

Den Post im Link habe ich übrigens schon selber gefunden, aber gehofft, 
da hätte sich mittlerweile was getan. Aber so flugs geht's dann doch 
nicht, ist ja schließlich erst acht Jahre her...

von Sigi (Gast)


Lesenswert?

Genaugenommen gibt es 3 Methoden, jeweils mit
In/Out-Clock und Manuell/Automatisch (IN automatisch
und OUT manuell ist natürlich Blödsinn).

1. Falls PLL1->PLL2 und PLL1.cx nur für PLL2 verwendet
wird (bzw. für mehrere PLLs), dann kannst du ja
für PLL1 die OUT-Clocks automatisch generieren lassen.
Für SDC bzw. TimeQuest spielen diese Clocks ja keine
Rolle (intern schon, kann dir aber egal sein, da sich ja
keine deiner Constraints darauf beziehen).

2. Stell doch mal den SDC-Ausschnitt mit der verkettenden
Clock hier rein, inkl. vollständigen Pfaden beider PLLs.
Ich vermute mal, TQ sieht die Verbindung beider Pins nicht,
vlt. wegen der manuellen Generierung.

von Markus F. (mfro)


Lesenswert?

Sigi schrieb:
> 2. Stell doch mal den SDC-Ausschnitt mit der verkettenden
> Clock hier rein, inkl. vollständigen Pfaden beider PLLs.
> Ich vermute mal, TQ sieht die Verbindung beider Pins nicht,
> vlt. wegen der manuellen Generierung.

Gerne:. Hier mal das ganze Clock-Geraffel im Original:
1
create_generated_clock -name {clk_48m0} -source [get_ports {clk_main}] -multiply_by 16 -divide_by 11 -master_clock {clk_main} [get_pins {*:i_pll1|*|*|*|clk[0]}] 
2
create_generated_clock -name {clk_fdc} -source [get_ports {clk_main}] -multiply_by 16 -divide_by 33 -master_clock {clk_main} [get_pins {*:i_pll1|*|*|*|clk[1]}] 
3
create_generated_clock -name {clk_24m576} -source [get_ports {clk_main}] -multiply_by 32 -divide_by 43 -master_clock {clk_main} [get_pins {*:i_pll1|*|*|*|clk[2]}] 
4
create_generated_clock -name {clk_sys} -source [get_ports {clk_main}] -multiply_by 4 -master_clock {clk_main} [get_pins {*:i_pll1|*|*|*|clk[3]}] 
5
create_generated_clock -name {clk_33m0} -source [get_ports {clk_main}] -master_clock {clk_main} [get_pins {*:i_pll1|*|*|*|clk[4]}] 
6
create_generated_clock -name {clk_ddr(0)} -source [get_ports {clk_main}] -multiply_by 4 -phase 240.000 -master_clock {clk_main} [get_pins {*:i_pll2|*|*|*|clk[0]}] 
7
create_generated_clock -name {clk_ddr(1)} -source [get_ports {clk_main}] -multiply_by 4 -phase 105.000 -master_clock {clk_main} [get_pins {*:i_pll2|*|*|*|clk[1]}] 
8
create_generated_clock -name {clk_ddr(2)} -source [get_ports {clk_main}] -multiply_by 4 -phase 180.000 -master_clock {clk_main} [get_pins {*:i_pll2|*|*|*|clk[2]}] 
9
create_generated_clock -name {clk_ddr(3)} -source [get_ports {clk_main}] -multiply_by 4 -master_clock {clk_main} [get_pins {*:i_pll2|*|*|*|clk[3]}] 
10
create_generated_clock -name {clk_ddr(4)} -source [get_ports {clk_main}] -multiply_by 2 -phase 270.000 -master_clock {clk_main} [get_pins {*:i_pll2|*|*|*|clk[4]}] 
11
create_generated_clock -name {clk_25m0} -source [get_ports {clk_main}] -multiply_by 25 -divide_by 33 -master_clock {clk_main} [get_pins {*:i_pll3|*|*|*|clk[0]}] 
12
create_generated_clock -name {clk_2m0} -source [get_ports {clk_main}] -multiply_by 2 -divide_by 33 -master_clock {clk_main} [get_pins {*:i_pll3|*|*|*|clk[1]}] 
13
create_generated_clock -name {clk_500k} -source [get_ports {clk_main}] -multiply_by 1 -divide_by 66 -master_clock {clk_main} [get_pins {*:i_pll3|*|*|*|clk[2]}] 
14
create_generated_clock -name {clk_2m4576} -source [get_ports {clk_main}] -multiply_by 25 -divide_by 336 -master_clock {clk_main} [get_pins {*:i_pll3|*|*|*|clk[3]}] 
15
create_generated_clock -name {clk_video} -source [get_ports {clk_48m0}] -multiply_by 2 -divide_by 1 -master_clock {clk_48m0} [get_pins {*:i_pll4|*|*|*|*clk[0]}]

"clock_video" ist konfigurierbar (vom Microcontroller aus über eine 
"altpll_reconfig"-Instanz), deshalb wird die wohl von Quartus etwas 
anders benamst und hat ein Sternchen extra.

von Markus F. (mfro)


Lesenswert?

Achso. So heißen die Dinger in der Synthese (mit 'derive_pll_clocks'):
1
altpll1:i_pll1|altpll:altpll_component|altpll_8v63:auto_generated|clk[0]
2
altpll1:i_pll1|altpll:altpll_component|altpll_8v63:auto_generated|clk[1]
3
altpll1:i_pll1|altpll:altpll_component|altpll_8v63:auto_generated|clk[2] 
4
altpll1:i_pll1|altpll:altpll_component|altpll_8v63:auto_generated|clk[3] 
5
altpll1:i_pll1|altpll:altpll_component|altpll_8v63:auto_generated|clk[4] 
6
altpll2:i_pll2|altpll:altpll_component|altpll_1r33:auto_generated|clk[0] 
7
altpll2:i_pll2|altpll:altpll_component|altpll_1r33:auto_generated|clk[1] 
8
altpll2:i_pll2|altpll:altpll_component|altpll_1r33:auto_generated|clk[2] 
9
altpll2:i_pll2|altpll:altpll_component|altpll_1r33:auto_generated|clk[3] 
10
altpll2:i_pll2|altpll:altpll_component|altpll_1r33:auto_generated|clk[4] 
11
altpll3:i_pll3|altpll:altpll_component|altpll_rf03:auto_generated|clk[0] 
12
altpll3:i_pll3|altpll:altpll_component|altpll_rf03:auto_generated|clk[1] 
13
altpll3:i_pll3|altpll:altpll_component|altpll_rf03:auto_generated|clk[2] 
14
altpll3:i_pll3|altpll:altpll_component|altpll_rf03:auto_generated|clk[3] 
15
altpll4:i_pll4|altpll:altpll_component|altpll4_altpll:auto_generated|wire_pll_clk[0]

Das ist direkt aus dem TQ-Report (ich hab' nur das Gelaber dazwischen 
rausgenommen).

Vielleicht sieht ja jemand was, was ich vor lauter Draufstarren nicht 
sehe...

von Sigi (Gast)


Lesenswert?

In der letzten Zeile

  create_generated_clock -name {clk_video} -source [get_ports 
{clk_48m0}] ..

wird "clk_48m0" als Port angenommen, wegen "get_ports".
Da "clk_48m0" aber von einer PLL erzeugt wird, müsste
eigentlich "get_pins" dort stehen (deshalb auch
"empty Collection" in Fehlermeldung, d.h. Name wird in
Port-Liste/Menge nicht gefunden). Probier's mal aus.

von Markus F. (mfro)


Lesenswert?

Sigi schrieb:
> Probier's mal aus.
1
Ignored filter at sdram.sdc(64): clk_48m0 could not be matched with a pin
2
Ignored create_generated_clock at sdram.sdc(64): Argument -source is an empty collection

Die Idee war nicht schlecht, danke.

Soweit ich mich erinnere (ich hab' schon so allerhand probiert, so daß 
ich gar nicht mehr sagen kann, was alles), hatte ich die aber schon.

von Sigi (Gast)


Lesenswert?

Probier's nochmal mit "get_clocks",
irgendwo muss das Ding ja drin sein?!

von Markus F. (mfro)


Lesenswert?

Sigi schrieb:
> Probier's nochmal mit "get_clocks",
> irgendwo muss das Ding ja drin sein?!

Nö, geht auch nicht. Ich glaube, ich habe schon so ziemlich alles, was 
mit get_ ... anfängt, ausprobiert.

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.