Hallo zusammen,
ich bin neu in der FPGA/VHDL-Welt (und entsetzt, wie viel Wissen und
Verständnis sich in einem Berg aus "Informationen" verbigt).
Nach ersten kleineren Programmiererfolgen wollte ich nun die
Clock-Erzeugung meines Spartan 6 MicroBoard (LX9 - Package CSG324) in
Betrieb nehmen und habe dafür den Clock Wizard der XILINX-ISE zu Hilfe
genommen.
Nach meinem Verständnis erzeugt dieser Wizard vorgefertigten VHDL-Code,
den man dann Verwenden kann. Nur das I/O-Panning muss noch manuell
vorgenommen werden. Geplant war meinerseits die Instanz einer PLL zu
verwenden/erzeugen, um einfach mal einen beliebige Clock aus meinem
Eingangs-Takt 100 MHz zu erzeugen und auszugeben. Später möchte ich so
in verschiedenen entitys unterschiedliche Taktraten erzeugen können.
1. Frage: Ist dieses Vorgehen korrekt?
Leider erhalte ich nach dem Pin-Planning (durch PlanAhead unterstützt)
im "Implement Design"-Prozess immer folgende drei Fehlermeldungen
(genauer Wortlaut ganz unten):Place 1205, Place 1136, Pack 1654
Was nützt ein Wizard, wenn er Code ausspuckt, der nicht funktioniert? ^^
... daher meine 2. Frage : Ist dies vielleicht ein bekannter oder
leicht zu behebender Fehler? Was machte ich faksch oder sollte ich
anders machen?
Falls für die Beantwortung weitere Informationen nötig sein sollten
reiche ich diese natürlich sofort nach. In jedem Fall wäre ich für eine
hilfreiche Antwort sehr dankbar!
Fehlercode:
_________________________________________________________
ERROR:Place:1205 - This design contains a global buffer instance,
<clkout1_buf>,
driving the net, <CLK_OUT1_OBUF>, that is driving the following
(first 30)
non-clock load pins off chip.
< PIN: CLK_OUT1.O; >
This design practice, in Spartan-6, can lead to an unroutable
situation due
to limitations in the global routing. If the design does route there
may be
excessive delay or skew on this net. It is recommended to use a Clock
Forwarding technique to create a reliable and repeatable low skew
solution:
instantiate an ODDR2 component; tie the .D0 pin to Logic1; tie the
.D1 pin to
Logic0; tie the clock net to be forwarded to .C0; tie the inverted
clock to
.C1. If you wish to override this recommendation, you may use the
CLOCK_DEDICATED_ROUTE constraint (given below) in the .ucf file to
demote
this message to a WARNING and allow your design to continue. Although
the net
may still not route, you will be able to analyze the failure in
FPGA_Editor.
< PIN "clkout1_buf.O" CLOCK_DEDICATED_ROUTE = FALSE; >
ERROR:Place:1136 - This design contains a global buffer instance,
<clkout1_buf>,
driving the net, <CLK_OUT1_OBUF>, that is driving the following
(first 30)
non-clock load pins.
< PIN: CLK_OUT1.O; >
This is not a recommended design practice in Spartan-6 due to
limitations in
the global routing that may cause excessive delay, skew or unroutable
situations. It is recommended to only use a BUFG resource to drive
clock
loads. If you wish to override this recommendation, you may use the
CLOCK_DEDICATED_ROUTE constraint (given below) in the .ucf file to
demote
this message to a WARNING and allow your design to continue.
< PIN "clkout1_buf.O" CLOCK_DEDICATED_ROUTE = FALSE; >
ERROR:Pack:1654 - The timing-driven placement phase encountered an
error.
Nee, ganz so einfach ist das nicht. Der Spartan 6 hat ziemlich begrenzte
Clocking Ressourcen, beliebig viele PLLs gehen nicht, da die auch
physisch auf dem Chip vorhanden sein müssen. Auch gehen nicht alle
Teiler und Vervielfacher einzustellen. Schau dir mal den Clocking User
Guide an, das ist zwar ziemlich viel für einen Anfänger, aber gerade
beim Clocking muss man echt wissen, wie der FPGA da arbeitet.
Ganz abgesehen davon, steht ja auch da, was das Problem ist: Du gehst
mit dem Takt auf ein Nicht-Takt-Netz (dein Ausgang) und das klappt nicht
bei Xilinx. Und es steht sogar was du machen sollst: Ein ODDR FlipFlop
instanziieren, das den Takt an einen Ausgang des FPGA weiterleitet.
Vielen Dank für diese schnelle Antwort!
Die begrenzte Clocking Ressourcen machen mir erst mal keine Sorgen,
solange ich überhaupt mal Clock-Signale erzeugen und ausgeben kann.
Was ich bisher weiter verstanden habe (oder glaube verstanden zu haben)
ist, dass es ein FPGA-interntes Clock-Signal-Netz gibt, auf das die PLL
sein Ausgangssignal gibt. Von diesem internen Netz komme ich nicht so
ohne weiteres auf einen IO-Pin.
Frage 1 dazu: Könnte ich das interne Clock-Netzwerk-Signal zu einer
weiteren entity leiten und dort nutzen oder von dort an einen IO-Pin
ausgeben?
Frage 2: Wie lege ich einen ODDR-FlipFlop an, um das Signal direkt
auszugeben (und was tut diese FlipFlop)? Seite 224 von
http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_4/spartan6_hdl.pdf
gibt zwar ein generelles Template an, doch wie kann ich dieses auf meine
konkrete Situation anpassen?
Verstehen und Ändern fällt mir hoffentlich leichter, wenn überhaupt mal
irgendwas klappt. Ich wäre daher über einen Lösungsansatz sehr dankbar!
p.s.: Der Clock Wizard hat das Ausgangssignal wie folgend formuliert:
-- Output buffering
-------------------------------------
clkf_buf : BUFG
port map
(O => clkfb,
I => clk2x);
clkout1_buf : BUFG
port map
(O => clk_out1_internal,
I => clk2x);
CLK_OUT1 <= clk_out1_internal;
engineer_on_tour schrieb:> Was ich bisher weiter verstanden habe (oder glaube verstanden zu haben)> ist, dass es ein FPGA-interntes Clock-Signal-Netz gibt, auf das die PLL> sein Ausgangssignal gibt. Von diesem internen Netz komme ich nicht so> ohne weiteres auf einen IO-Pin.
Korrekt. Dein FPGA-internes Clock-Signal liegt auf 'speziellen'
Draehtchen im FPGA. Die gehen erstmal nur zu den einzelnen
Logikelementen, nicht nach draussen...
>> Frage 1 dazu: Könnte ich das interne Clock-Netzwerk-Signal zu einer> weiteren entity leiten und dort nutzen oder von dort an einen IO-Pin> ausgeben?
Erster Teil vor dem ODER: Ja! Genau dazu ist das Clock-Netzwerk da!
Dieser Takt ist fuer jedes Logikelement, bestehend aus Look-Up-Table und
FFs verfuegbar.
Nach deinem ODER: Den Takt auf einen Ausgangspin zu geben, das ist
wieder etwas spezielles. Da muessen dann auch die Draehte auf dem Chip
vorhanden sein...
>> Frage 2: Wie lege ich einen ODDR-FlipFlop an, um das Signal direkt> auszugeben (und was tut diese FlipFlop)? Seite 224 von> http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_4/spartan6_hdl.pdf> gibt zwar ein generelles Template an, doch wie kann ich dieses auf meine> konkrete Situation anpassen?
So ein ODDR nimmt dein Signal (evtl. einen Takt, falls die
Routing-Resourcen das erlauben) und gibt es am Pin einfach aus...
Probier doch einfach mal 'Logik'! Du nimmst deinen internen Takt (siehe
Punkt 1), machst damit etwas (im einfachsten Fall einen Zaehler oder
sowas), und gibst ein Bit deines Zaehlers aus. Also nicht das Taktnetz,
sondern ein daraus abgeleitetes Signal aus einem Logikflipflop... Dann
sollte das Verhalten eines FPGA klar werden...
super! .... dann probier ich das (morgen früh leider erst) mal aus ...
mal sehen, wie ich an den "internen Takt" der PLL ran komme.
Bisher habe ich einfach die außen anliegende Clock als Eingangssignal
einer entity genutzt, runter geteilt und konnte was machen (z.B. LED
toggeln).
Mal sehen, wie ich an das Signal des internen Clock-Netzwerks ran komme
und wie/ob ich die PLL-Instanz dazu noch umbauen muss (bisher weiß ich
noch nicht sooo genau, was der Wizard da für Code ausgespuckt hat bzw.
wo das Signal hin geht und wie ich da wieder in ner anderen entity ran
komme)
Das ist eigentlich recht einfach. Wenn du von einem externen Eingang
am FPGA auf das Taktnetz willst, musst du einen IBUFG nehmen. Erzeugst
du die PLL mit dem CoreGenerator, wird das automatisch gemacht. Nach der
PLL muss jedes Taktsignal erst durch einen BUFG um auf das Taktnetzwerk
zu kommen.
Diesen Takt (nach dem BUFG) kannst du dann Chip-weit verwenden, um
FlipFlops, BlockRAMs usw. zu takten. Also am CLK Eingang der FlipFlops
anschließeb bzw. mit rising_edge() beschreiben. as geht natürlich auch
in alle Module (entities) rein.
Willst du das Clock Signal aber mal direkt und ohne herunterteilen
ausgeben, dann geht das sinnvoll nur über ein ODDR Register ausgeben,
wie das angeschlossen wird, steht ja sogar in der MAP Fehlermeldung
oben.
klingt einfach ... mal sehen wie das in der Praxis aussieht ... mein
Versuch VHDL "mal eben" an einem Tag zu lernen ist jedenfalls mindestens
auf den zweiten Tag verlängert ;)
ODDR oder BUFG sind nach meinem jetzigen Verständnis Funktionen aus der
XILINX-Library und nichts, was man selber schreiben muss. Satt dessen
werden diese Komponenten innerhalb einer entity instanziiert (ähnlich
des PLL-Codes), richtig?
Ja, das sind Hardware-Elemente auf dem FPGA, die durch das Instanziieren
verdrahtet werden. Du wirst noch sehr sehr viel mehr Tage benötigen für
VHDL :)
engineer_on_tour schrieb:>> ODDR oder BUFG sind nach meinem jetzigen Verständnis Funktionen aus der> XILINX-Library und nichts, was man selber schreiben muss. Satt dessen> werden diese Komponenten innerhalb einer entity instanziiert (ähnlich> des PLL-Codes), richtig?
ODDR: ja muss instanziiert werden
BUFG: nicht ganz, bei Verwendung von Komponenten wie der PLL o.ä ja.
Bei getaktete Prozessen in synthesefähigem Code macht das die
FPGA-synthese-tool chain meist selbst.
Wenn z.B. hier der CLK pin über einen FPGA-Pin ohne PLL zu
so einem Prozess käme:
[vhdl]
name:process(CLK) -- Select input address
begin
if(rising_edge(CLK)) then
reg <= red2 oder sonstewas usw
[\vhdl]
Hallo zusammen,
ich bin heute sehr gut weiter gekommen und habe durch ein gutes pdf
(http://astro.uni-tuebingen.de/groups/electronics/VHDL.pdf) nun auch
etwas besser verstanden, wie man ein (zumindest etwas) komplexeres
VHDL-Projekt aufzieht.
Vielen Dank an dieser Stelle noch mal für eure guten Tipps und
Erklärungen!
Ich bin jetzt soweit, dass ich eine componente habe,
entity cCLOCK_PLL is
port(
CLK : in std_logic;
CLK_PLL : out std_logic
);
end cCLOCK_PLL;
an der ein Clock-Signal von außen anliegt. Dieses wird innerhalb der
componente in einer instanzierten PLL genutzt. Das Ausgangssignal der
componente ist (bzw. soll sein) ein FPGA-internes Clock-Signal
"CLK_PLL_SIG", dass zu anderen components weiter geleitet wird.
Das Ausgangssignal "CLK_PLL : out std_logic" wird nur innerhalb der
Schaltung über das interne Signal "signal CLK_PLL_SIG : std_logic;" mit
der Zuweisung "CLK_PLL => CLK_PLL_SIG" genutzt.
Christian R. Schrieb: "Diesen Takt (nach dem BUFG) kannst du dann
Chip-weit verwenden".
Das war mein Ziel. Die Fehler treten jedoch immer noch auf und sind nur
durch ein ODDR2-Register (habe noch nicht geschafft, dieses in Betrieb
zu nehmen, da ich gehofft hatte, dies umgehen zu können) zu vermeiden.
clkout1_buf : BUFG
port map
(O => CLK_PLL, -- verursacht den Fehler!!!
I => clkout0);
Muss ich in jedem Fall ein ODDR2-Regiter instanzieren oder funktioniert
die FPGA-interne Verbreitung der durch die PLL erzeugten Signals doch
noch mal anders?
Ich habe noch drei kurze, sich daran anschließende Fragen zu ODDR2(falls
es keine andere und elegante(re) Methode gibt, dass PLL-Signal
FPGA-intern zu verwenden/verbreiten):
Meine Konfiguration des ODDR" sieht so aus:
Q => CLK_PLL, -- 1-bit output data
C0 => clkout0, -- 1-bit clock input
C1 => (not clkout0), -- 1-bit clock input
CE => '1', -- 1-bit clock enable input
D0 => '0', -- 1-bit data input (associated with C0)
D1 => '1', -- 1-bit data input (associated with C1)
R => '0', -- 1-bit reset input
S => '0' -- 1-bit set input
1. Benötige ich den BUFG noch, wenn ich ein ODDR2 nutze?
2. Das invertierte Clocksignal an C1 des ODDR2 wollte ich so generieren:
C1 => (not clkout0)
Dann kommt folgende Warnung: WARNING:HDLCompiler:946 -
"C:\Users\uidg3368\Test7\clock-Komponente.vhd" Line 112: Actual for
formal port c1 is neither a static name nor a globally static expression
Muss ich wirklich ein extra Signal einführen, dieses invertieren und
kann dieses dann erst auf C1 geben? (notclkout0 <= not clkout0;)
3. Den Code bekomme ich synthetisiert, doch dann erscheint folgender
Error und ich komme nicht weiter:
ERROR:Pack:2531 - The dual data rate register
"ClockGeneration/ODDR2_inst"
failed to join the "OLOGIC2" component as required. The output
signal for register symbol ClockGeneration/ODDR2_inst requires general
routing to
fabric, but the register can only be routed to ILOGIC, IODELAY, and
IOB.
Habt ihr ne Idee, was da los ist?
Das ODDR ist nur für extern. Intern brauchst und darfst du das natürlich
nicht. Wenn du die PLL mit dem Core Generator erzeugt hast, kannst du
dort gleich einstellen, dass der BUFG reingebaut wird, dann darfst du
keinen zweiten mehr dran machen.
DAS war der entscheidende Hinweiß :D
ich hab den BUFG raus geschmissen und es geht ... ich kann das Signal
jetzt intern weiter verwenden :D
Bei Zeiten werd ich "PLL -> BUFG -> ODDR2 -> Direkt raus" auch noch mal
testen .... aber da ich nur interne Signale brauche reicht mir diese
Lösung erst mal.
VIELEN Dank!
Hallo zusammen,
ich hab eine sich hierran anschließende Frage: Wenn ich statt der PLL
die vom ClockWizard generierte DCM_SP-Instanz verwenden möchte (immer
noch nur intern!) treten wieder Place:1205,1136 und
Pack:1654-Error-Meldungen auf.
Welche Buffer sind bei der internen DCM-Verwendung notwenig, die für die
PLL nicht benötigt werden?