Forum: FPGA, VHDL & Co. Takt generieren


von FPGA-Neuling (Gast)


Lesenswert?

Hallo zusammen,

meine Frage als FPGA-Neuling:

Für den Betrieb eines FPGA benötigt man einen Quarz zur
Taktgenerierung.

Bei vielen VHDL-Modellen (z.B. Beschreibung eines RAM-Controllers)
benötigt man nun ein Clock-Signal. Woher bekommt das CLK-Signal.
Generiert man es mittels einer VHDL-Beschreibung eines Clockgenerators
oder greift man auf den physikalischen Takt des Quarzes zurück (falls
dies der Fall sein sollte, wie realisiert man dies).

Falls man ein VHDL-Clockgenerators benutzt, kennt einer einen Code
dafür bzw. einen Link ?

Wie kann man sich das alles vorstellen.

Danke

von FPGA-User (Gast)


Lesenswert?

Praktisch wird ja am FPGA ein Clock anliegen.

Für die Simulation des VHDL-Codes nimmst Du ein
VHDL-Modell, das z.B. genau dieselbe Taktfrequenz
wie Dein "echter" Quarzoszillator generiert.

VHDL-Code für 10 MHz-Oszillator :

   GEN_CLK : process
   begin
      while true loop
         clk <= '0';
         wait for 50 ns;
         clk <= '1';
         wait for 50 ns;
      end loop;
   end process;

Den Code platzierst Du in einer Testbench, z.B.
tb.vhd
Darin wird Dein FPGA-Component instanziiert plus
evt. ein Stimuli-Component oder Du schreibst die
Erzeugung der Stimulis direkt ins File tb.vhd.
Hoffe das hilft weiter.

von FPGA-Neuling (Gast)


Lesenswert?

OK, für die Simulation habe es verstanden.

Aber wie sieht es in meiner realen Schaltung aus. Nehmen wir an ich
benötige für irgendein SRAM einen Takt von 20 MHz (nur Annahme) und
mein FPGA wird von außen mit einem 40 Mhz-Oszillator betrieben.

Wie komme ich zu meinem Takt von 20Mhz ? Kann ich dann in einem
VHDL-Code auf irgendeinen Pin zugreifen, an dem die 40Mhz-Oszillator
anliegen, und mir mittels eines Frequenzteilers dann den benötigten
Takt bauen ?

Sorry, bestimmt ist die Vorstellung komplett falsch, aber ich bin
Anfänger ;-)

HILFE....(Danke)

von Johnny (Gast)


Lesenswert?

ne mann teilt den tackt im code durch tacktteiler.
ist schon richtig was du gesagt hast.
zb:

if rising_edge(clk) then
   clk_halb <= not clk_halb;
end if;

das wäre der takteiler. ein einfacher t-flipflop
bin auch anfänger.
hab aber schon einiges programmiert.
momentan experementiere ich mit diesem modelsim herum um meine funkuhr
zu testen.
mfg

von FPGA-User (Gast)


Lesenswert?

korrekt, also ein externer Takt, der z.B. an Pin 1
anliegt kann durch einen Teiler wie im obigen Bsp.
heruntergeteilt werden.
Man muß hier nur aufpassen, wenn man nachher beide Takte
verwenden will (wie im Beispiel 40MHz /20MHz).
Diese beiden Takte sind dann nicht mehr synchron!

Eine sichere Variante ist z.B. den heruntergeteilten Takt
nur als Clock-Enable Signal zu verwenden und trotzdem alle
Register mit dem schnellen Takt (z.B. 40MHz) zu takten:

process(clk)
begin
   if rising_edge(clk) then
      -- Taktteiler / 2
      half_clk_q <= not half_clk_q; -- Typ boolean

      if half_clk_q then -- glob. Enable für gesamte folgende Logik

         case SRAM_STATE is
            when IDLE =>
            ...

      end if;
   end if;
end process;

In den Timing-Constraints kann man nun die Laufzeit Register-Register
für alle FFs, die das "langsame" Enable-Signal haben verdoppeln,
da sich ihre Ausgänge ja nur noch mit der halben Frequenz ändern
können.

Falls vorhanden, kann auch eine DLL oder PLL im FPGA
verwendet werden. Da speist man einfach den externen
Takt ein, legt in den Eigenschaften der PLL/DLL die
Multiplikatoren/Teiler fest und erhält am Ausgang die neue
Taktfrequenz. Vorteil: alle Takte am Ausgang der PLL sind
synchron.

Um keine Probleme durch asynchrone Takte zu bekommen, die
vielleicht auch nur Temperatur-abhängig auftreten und schwer
zu finden sind, würde ich empfehlen, mit so wenig Takten wie
möglich zu arbeiten, wenns geht nur 1 Takt und evt. dazu
Clock-Enable-Signale verwenden.

von johnny (Gast)


Lesenswert?

aha den weiß ich ja auch gleich mehr.
ich habe jetzt mehrer zähler.(soll ne uhr werden)
die bekommen alle jeweils von der vorgängerstufe ihren tackt.
also wäre es jetzt besser wenn ich das mit clock enable mache.
na den schreib ich mal um.
danach muss ich erst mal die simulation schreiben.
danke.
mfg

von johnny (Gast)


Lesenswert?

so hab den ganzen code umgeschrieben.
jetzt kommen aber diese beiden fehlermeldungen
-------------
WARNING:Xst:1988 - Unit <dcf_uhr>: instances <Mcompar__n0640>,
<Mcompar__n0370> of unit <LPM_COMPARE_5> and unit <LPM_COMPARE_4> are
dual, second instance is removed

WARNING:Xst:1988 - Unit <dcf_uhr>: instances <Mcompar__n0369>,
<Mcompar__n0189> of unit <LPM_COMPARE_3> and unit <LPM_COMPARE_2> are
dual, second instance is removed
-------------
kannst du damit was anfangen?
weil da steht ja keine zeile oder wie das signal oder die variable
heißt.
noch was anderes: jetzt ist die maximum frequenz  von 80mhz auf 20
gefallen.
muss ich da jetzt noch was in die ucf datei schreiben,
von wegen welche sigale schnell sein müssen oder so.

mfg

von johnny (Gast)


Lesenswert?

mal noch was anderes. mir ist grad aufgefallen das er aus meinen zählern
jetzt addierer und subtrahierer gemacht hat.
ist das normal??
oder fehlt mir ne libary.
hab momentan diese drinne:
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;

mfg

von johnny (Gast)


Lesenswert?

mir ist grad mal durch probieren aufgefallen, das wenn ich mit einer
variable einen zähler machen will, wird daraus ein adierer aber mit
einem signal bleibt es ein zähler.
kann mir das einer erklären????

von FPGA-Neuling (Gast)


Lesenswert?

@FPGA-User...

ich habe noch ein paar Fragen zu deinem Beitrag:

Kannst du mir das mit den Clock Enable genauer erklären ? Ich brauche
doch ein vollständiges Clock-Signal, z.B. um ein SRAM anzusteuern.
Hast du noch einen anderen Beispiel-Code, in dem das ersichtlicher
wird. (z.B. mit externer Clock-Pin-Zuweisung, Pll und/oder
Clock_Enable).
Nett wäre auch ein Beispiel von so einer PLL-Realisierung in VHDL ?
Hast du so etwas ? So ganz nebenbei was ist ein DLL ?

Außerdem könntest du mir das mit den Timing-Constraints und den
Laufzeit Registern noch erklären. Habe da null Peilung...(wäre echt
nett).

Kann man einen externen Takt (z.B. von einem Oszillator) an einen
beliebigen Input-Pin des FPGAs legen ? Ich habe in Datenblättern
gesehen, dass der FPGA einen speziellen Takt-Eingang hat, ähnlich dem
eines Microcontrollers. Kann ich also sagen, ich kann in meinem
VHDL-Code sagen: clk <= P1 ??? (kann ich mir gar nicht vorstellen, aber
vielleicht...) ?
Braucht es dazu noch andere Einstellungen (z.B. in den
Constraint-Dateien, in denen glaub ich die Pin-Zuweisungen gemacht
werden) oder muss man den entspr. Pin speziell als Takt-Pin definieren
???

Sorry, für meine (dummen) Fragen....

@jonny....

ich würde einfach einen eigenen Beitrag im Forum erstellen. Da bekommst
du schneller geholfen ;-)

von Johnny (Gast)


Lesenswert?

naja habsch gedacht da fpgh-user ja anscheinend viel weiß kann mann ihn
gleich auch noch fragen, da gleiches thema.

externer tackt: ich habe meine cpld´s die ich programmiert habe über
einen oszilator verbunden.
angeschlossen werd der tackt an den gclk pins. das sind globale clock
pins die im ganzen cpld, fpgh verfügbar sind. kann schnell drauf
zugegriffen werden.

tackt: sein beispiel ist doch ganz ok.
---------------
process(clk)
begin
   if rising_edge(clk) then
      -- Taktteiler / 2
      half_clk_q <= not half_clk_q; -- Typ boolean
-----------------------
als erstes erstellste das enable signal. ds ist hier ein einfacher
tackteiler. bei jeder zweiten tacktflanke von clk ist half_clk_q true.
-----------------------
      if half_clk_q then -- glob. Enable für gesamte folgende Logik
=======================
das enable signal fragst du dann einfach noch mal ab. wenn half_clk_q
jetzt true ist und steigende flanke von clk, dann kann/können die
logic/flipflop´s die dahinter geschaltet sind was machen. das ist ja
bloß jede 2te flanke von clk.
         case SRAM_STATE is
            when IDLE =>
            ...

      end if;
   end if;
end process;
----------------

        _   _   _   _   
____| |_| |_| |_| |_| |_| |_   <--  clk
     __     ___     __
____|   |___|   |___|   |___  <-- half_clk_q

    |   |
    |   2ter tacktimpuls half_clk_q wird low
    1ter tackimpuls half_clk_q wird high

        |       |       |
        hier bekommt die darauf folgende logic ihren tacktimpuls.
durch die low high flanke von clk und dem noch high sein von half_clk_q
hast du einen kurzen impuls für die darunter ligende logic.

das mit dem timing hab ich auch noch nicht verstanden, habe es aber
schon in einer ucf datei gesehen.
mfg

von FPGA-User (Gast)


Lesenswert?

also die obige Erklärung mit graf. Darstellung von
Johnny ist schon super - das dürfte ja jetzt klar sein.
Anstelle half_clk_q kann man natürlich auch ein Counter-Signal
nehmen mit CLK-Frequenz/10 o.ä.

Eine DLL ist übrigens eine Delay-Locked-Loop, darunter kann
man sich eine digital einstellbare Verzögerungsleitung vorstellen.
Gibts in einigen XILINX-FPGA-Typen, wird zur Taktaufbereitung
verwendet. Völlig anderes Prinzip als PLL, aber am Ende
bekommt man seine Takte phasenstabil zu einem Input-Takt,
mit veränderter Frequenz, wenn man will größer oder kleiner,
so wie bei einer PLL auch.

Hier mal ein Beispiel für eine PLL im FPGA.
Bei ALTERA benutzt man zum generieren den sog.
"Mega Wizard Plugin Manager", den man von der graf. Oberfl.
aufruft, dort wird werden Name und Parameter eingegeben, am Ende
spuckt das Teil ein paar Files aus.
Im VHDL wird dann zuerst ein component deklariert,
(steht in einem von den generierten Files) z.B.:

   component pll1
      PORT (
         inclock  : IN STD_LOGIC;
         clock0    : OUT STD_LOGIC;
         clock1    : OUT STD_LOGIC
      );
   end component;

und in der architecture dann instanziiert :

architecture blabla of example is
begin
...
   pll1_inst : pll1
      port map (
         inclock => clk,
         clock0   => clk_0,
         clock1   => clk_2x
   );

..
end;

in dem Beispiel waren die Parameter so eingestellt, dass
inclock der globale 33 MHz-Takt des FPGAs ist (an einem
globalen Clock-Pin, der eine PLL treiben kann),
clk_0 ist ein Ausgang mit 33 MHz und clk_2x hat 66 MHz.
Ich nutze im Design clk_0 und clk_2x.
Da beide Takte synchron sind, muss ich mir bei der
Übergabe von Daten ziwschen Registern, die mit 33 und 66 MHz
getaktet sind nur wenig Gedanken machen (vorausgesetzt ich
arbeite immer mit rising_edge(clk) :
FF 33 MHz -> FF 66 MHz : Laufzeit muss <= 15 ns sein
FF 66 MHz -> FF 33 MHz : Laufzeit muss <= 15 ns sein
Das sollte die Software aber schon selbst erkennen und
evt. Timing-Probleme melden. Dafür muss man m.E. keine
Constraints mehr setzen.
Zu Timing-Constraints und UCF-File später was.

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.