Forum: FPGA, VHDL & Co. Mehrere Takte aus Referenztakt teilen (PLL)


von Veribro (Gast)


Lesenswert?

Hallo,

mich würde mal im Allgemeinen interessieren wie man in Verilog die PLLs 
eines FPGAs anspricht bzw. wo etwas darüber zu finden ist.
Ich möchte nämlich aus einem Referenztakt heraus mir mehrere Takte für 
verschiedene Module erzeugen, da ich mit mehreren verschiedenen Takten 
arbeiten muss. Ich weiß, dass sowas über die PLLs möglich ist, aber ich 
habe noch nichts aufschlüssiges darüber gefunden bzw. Beispiele dazu 
gesehen. Würde mich freuen wenn mir jemand helfen kann.

von D. I. (Gast)


Lesenswert?

Xilinx CoreGen
Altera MegaWizard

Dort die Komponente erzeugen und einbinden

von Marten V. (marten-v)


Lesenswert?

Stichwort: DCM (Digital Clock Management)
Die Anzahl der verfügbaren DCM varriert nach FPGA Typ. Ein Blick in das 
Datenblatt des FPGA sollte dir da Klarheit verschaffen ;-)
Ansonsten kannst du Takte auch noch mittels T-FlipFlop oder Zählern 
teilen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Marten V. schrieb:
> Ansonsten kannst du Takte auch noch mittels T-FlipFlop oder Zählern
> teilen.
Ja, und das vergessen wir gleich mal wieder.
Denn so ein "Takt" wird dann mit "normalen" Verdrahtungsressourcen und 
entsprechndem Skew kreuz&quer im FPGA verteilt.

Die Xilinx Tools sagen dazu diplomatisch
"This is no good design practice"... ;-)

von Veribro (Gast)


Lesenswert?

Hallo,

danke schonmal vorab für die Antworten.
Aber irgendwie komm ich auf diese Weise nicht unbedingt weiter.
Ich möchte mal etwas konkreter werden:
Habe hier ein ML505-Evalboard von Xilinx mit nem Virtex-5 LX50T drauf. 
Dieses Board hat fest integrierte Takte drauf, welche 27, 33, 100 und 
differenziell 200MHz betragen. Nun habe ich schon einige Module 
geschrieben, die ich brauche und in der Testbench mit virtuellem 
Taktmanagement schon funktionsfähig gemacht.
Was ich aber jetzt für eine Synthetisierung brauche ist aus einem der 
vorhandenen Referenztakte einen Takt von GENAU 6,952 MHz zu erzeugen und 
davon brauch ich dann hier und da noch einige vielfache...
ich weiß jedoch nicht wie ich es schaffe das ganze auf so nen krummen 
Wert zu teilen. Habe mich jetzt bisschen auch durch den Corgen 
durchgeschlagen, aber was ich hier so an Optionen finde macht mich 
irgendwie nicht glücklich. Da dieser für das Clock Management immer 
ganze Zahlen zum teilen verlangt und auch bestimmte Grenzen aufweist und 
im Grunde genommen erzeugt er mir auch nur eine HDL-Datei, die ich 
einbinden muss.. das heißt ich werd wahrscheinlich selber was schreiben 
müssen - ich hätte halt nur gern die passende Referenz dazu - so eine 
Art DCM/PLL Tutorial in der sowas schon mal in einem Beispiel codiert 
wird, damit ich mir ein Bild davon machen kann.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Veribro schrieb:
> Aber irgendwie komm ich auf diese Weise nicht unbedingt weiter.
Dann hat offenbar noch Information gefehlt...

Veribro schrieb:
> brauche ... einen Takt von GENAU 6,952 MHz
Tja, das wirst du aus den vorhandenen Takten (erst mal) nicht schaffen. 
Mir fällt da auf Anhieb kein Multiplikaotr&Teilerpärchen ein, der aus 
einem der genannten Takte genau die 6952kHz macht.

> und davon brauch ich dann hier und da noch einige vielfache...
Das ist jetzt aber bedenklich...

Sag doch einfach mal, wofür du diesen Takt brauchst.
Und sag auch, ob der z.B. im Bereich von 5ns jittern darf (das wäre der 
Kehrwert von 200MHz)...

von Veribro (Gast)


Lesenswert?

Lothar Miller schrieb:
> Sag doch einfach mal, wofür du diesen Takt brauchst.
Für ein DVB-C Basisband (schreibt eine in Deutschland festgelegte Norm 
von 6,952 MSym/s vor) - d.h. ich werd nach meinem vorletzten Modul auf 
jeden Fall mit 6,952 MHz takten müssen. Für das IQ-Basisband am Ausgang 
selbst wird dann der halbe Takt davon verwendet.

> Und sag auch, ob der z.B. im Bereich von 5ns jittern darf (das wäre der
> Kehrwert von 200MHz)...
Wäre eigentlich nicht so toll, weil ich ein möglichst schönes Signal 
erzielen möchte, aber ich wäre froh wenn der Ansatz dafür da wäre den 
gewünschten Takt zu generieren.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Veribro schrieb:
> aber ich wäre froh wenn der Ansatz dafür da wäre den
> gewünschten Takt zu generieren.
Dann probier mal diesen DDFS Ansatz:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity CLKdiv is
6
    Port ( clk : in   STD_LOGIC;
7
           co  : out STD_LOGIC);
8
end CLKdiv;
9
10
architecture Behavioral of CLKdiv is
11
signal presc : unsigned (31 downto 0) := (others=>'0');
12
signal cdiv  : std_logic;
13
14
-- evtl. nötig, wenn die Synthese den neuen Takt nicht selber erkennt
15
-- attribute buffer_type: string; 
16
-- attribute buffer_type of cdiv: signal is "bufg"; 
17
18
begin
19
   process begin
20
      wait until rising_edge(clk);
21
      presc <= presc+149293063; -- (2**32/(200000000/6952000))
22
   end process;
23
24
   process begin
25
      wait until rising_edge(clk);
26
      cdiv    <= presc(31);  -- das MSB wird zum neuen Takt
27
   end process;
28
   
29
   co <= cdiv;
30
end Behavioral;
Damit hast du bei 200MHz Eingangstaktfrequenz einen Ausgangstakt co 
von 6951999,9 Hz... ;-)
Allerdings bleibt dir da wie erwähnt der Jitter von 5ns.

von Veribro (Gast)


Lesenswert?

vielen vielen Dank Lothar, das hat mir einiges an Erkenntnis gebracht, 
ich werde mir diesen Codeschnipsel mal zu Herzen nehmen und schauen wie 
ich jetzt an die ganze Sache rangehe.

von Sym (Gast)


Lesenswert?

5 ns Phasenjitter ist für ein analoges Signal komplett unbrauchbar. Wenn 
du keinen passenden Oszillator montieren möchtest (oder eben eine 
fractional-N PLL), so kannst du quasi nur das Eingangs- und 
Ausgangssignal resamplen. Z.B. den ADC/DAC mit 20 MHz laufen lassen und 
intern die Zwischenpunkte mit 6,952 MHz errechnen z.B. mit einem 
Farrow-Interpolator.

von Veribro (Gast)


Lesenswert?

Hallo,

ja ich habe leider auch feststellen dürfen, dass ich mit obriger Methode 
nicht an mein Ziel komme.
Hat jemand denn Erfahrung wie man auf dem ML505 bestückt mit einem 
Virtex-5 XC5VLX50T von Xilinx die PLL über die DCMs über eine HDL 
anspricht?
Ich weiß nur, dass da noch ein IDT genannter Clock Management Chip drauf 
ist, aber ich hab ehrlich gesagt keinerlei Ahnung über welche Prozeße 
ich den anspreche. Kann es sein, dass ich über die HDL hinaus andere 
Algorithmen anwenden muss bzw. über irgendein bestimmtes Tool die PLL 
ansteuere - weil so wie ich das verstehe kann ich mit einer HDL nur 
reine Bit2Bit-Übertragungen machen, aber mir fallen keine konkreten 
speziellen PLL-Befehle oder dementsprechende Libraries bzw. Befehle 
dafür ein die ich aufrufen muss...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Veribro schrieb:
> Hat jemand denn Erfahrung wie man auf dem ML505 bestückt mit einem
> Virtex-5 XC5VLX50T von Xilinx die PLL über die DCMs über eine HDL
> anspricht?
Ja, einfach das Datenblatt zu den DCM und die Templates nehmen...
Beitrag "VHDL code to infere DCM"

Aber wie gesagt: auch wenn du die DCM instantiiert bekommst (das ist gar 
nicht so schwer), du wirst immer noch das Problem haben, dass keiner 
deiner Takte mit den verfügbaren Teilern für die gewünschte Zielfrequenz 
taugt. Ich hatte das schon im 
Beitrag "Re: Mehrere Takte aus Referenztakt teilen (PLL)" angedeutet.

Fazit: schließ einfach einen passenden Takt (oder was vielfaches davon) 
extern an.

von Veribro (Gast)


Lesenswert?

Hab mich jetzt doch mal aufgerauft mich ein wenig mit dem Coregenerator 
zu befassen und ich denke ich bin mit den Funktionen die er mir liefert 
einigermaßen glücklich geworden.
Finde es nur merkwürdig, dass ich kaum einer Verilog-Referenz 
Aufrufbeispiel um solche Funktionen zu generieren angegeben sind. Habe 
bis jetzt noch nichts sinnvolles gefunden, was mir die genaue 
Funktionsweise von den in core-gen erzeugten Funktionen PLL_ADV, BUFG 
usw. anzeigt.
Aber wenn es nicht anders geht muss ich mich wohl damit beglücken...
danke für die zahlreichen Antworten

von Veribro (Gast)


Lesenswert?

Hallo,

ich hab zur Zeit Probleme mit der Synthetisierung meiner per PLLs 
erzeugten Takte. Naja eigentlich scheitert das ganze erst beim 
"Translation"-Prozeß, die nach der Synthese bei der Implementierung 
folgt.

Und zwar habe ich ja 3 PLLs nutzen müssen um alle 6 Takte zu erhalten 
die ich brauche. Habe aus einem Referenztakt von 200 MHz in der ersten 
PLL meine beiden Takte 27,808 und 6,952 MHz generiert. Und nun nutze ich 
die 27,808 MHz für PLL2 und PLL3 um damit meine anderen 4 Takte zu 
erzeugen.
Die Modulaufrufe sehen dann ungefähr so aus (wobei ich ja die PLL-Module 
im Core Generator erzeugt habe):

dvb_c_clk clock(.CLKIN1_N_IN(ref_clk_n),            //200MHz Reference 
clock negativ
                             .CLKIN1_P_IN(ref_clk_p), 
//200MHz Reference clock positiv
                             .RST_IN(reset),
                             .CLKOUT0_OUT(clk_up), 
//13.904MHz 2*baseband symbol clock
                             .CLKOUT1_OUT(samp_clk)); 
//27.808MHz upsampled clock

        [verilog]dvb_c_clk_qam1632 clock2(.CLKIN1_IN(samp_clk), 
//27.808MHz reference clock from PLL1
                                         .RST_IN(reset),
                                         .CLKOUT0_OUT(clk_si16), 
//3.476MHz clock for 16qam
                                         .CLKOUT1_OUT(clk_si32)); 
//4.345MHz clock for 32qam

        dvb_c_clk_qam64128 clock3(.CLKIN1_IN(samp_clk),    //27.808MHz 
reference clock from PLL1
                                         .RST_IN(reset),
                                         .CLKOUT0_OUT(clk_si64), 
//5.214MHz clock for 64qam
                                         .CLKOUT1_OUT(clk_si128)); 
//6.083MHz clock for 128qam[/verilog]


Wenn ich eben versuche diese zu implementieren bekomme ich folgende 
Fehlermeldungen:

ERROR:NgdBuild:770 - IBUFG 'clock2/CLKIN1_IBUFG_INST' and BUFG
   'clock/CLKOUT1_BUFG_INST' on net 'clk_out_OBUF' are lined up in 
series.
   Buffers of the same direction cannot be placed in series.
ERROR:NgdBuild:462 - input pad net 'clk_out_OBUF' drives multiple 
buffers:
     pin I on block clock2/CLKIN1_IBUFG_INST with type IBUFG,
     pin I on block clock3/CLKIN1_IBUFG_INST with type IBUFG,
     pin I on block clk_out_OBUF with type OBUF
ERROR:NgdBuild:924 - input pad net 'clk_out_OBUF' is driving non-buffer
   primitives:
     pin O on block clock/CLKOUT1_BUFG_INST with type BUFG
ERROR:NgdBuild:947 - input pad net 'clk_out_OBUF' is driving non-input
   buffer(s):
     pin O on block clock/CLKOUT1_BUFG_INST with type BUFG

Mir gehen auch wirklich die Ideen langsam aus, habe nämlich entsprechend 
dem Datenblatt die PLL-Ausgänge als globale Buffer definiert und auch 
sonst eigentlich mich an den Regeln gehalten. Aber anscheinend scheitert 
es daran, dass ich den Ausgang der einen PLL als Eingang für die andere 
nutze - obwohl das laut Datenblatt legitim ist. Ich hoffe jemand kann 
mir noch einen Rat geben.

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.