Hallo,
ich bekomme von aussen 50MHz ins FPGA rein und will 65MHz wieder
ausgaben für einen externen ADC.
Also Eingänge beschrieben:
1
entityblahis
2
port(CLK:instd_logic;
3
ADC_Clock_out:outstd_logic);
4
endblah;
Dann den Clockmanager generiert:
1
COMPONENTclk_65mhzis
2
port
3
(-- Clock in ports
4
clk:instd_logic;
5
-- Clock out ports
6
clk65:outstd_logic;
7
clk25:outstd_logic
8
);
9
ENDCOMPONENT;
Den dann verdrahtet:
1
clk0:clk_65mhzPORTMAP(
2
clk=>CLK,
3
clk65=>ADC_Clock_out,
4
clk25=>CLK25);
Und auch im .UCF (ISE) die Signale mit Pads verbunden:
1
NET"CLK"LOC="P14";#50MHz
2
NET"ADC_Clock_out"LOC="P17";
Das FPGA ist ein XC6SLX9-2TQG144C, der Pin P17 ist laut Datenblatt des
Modulherstellers (Bitrecords) ein "IO_L43P_GCLK23_3". Also ein Taktpin.
Lasse ich aber alles durchlaufen mit routen und so, dann bekomme ich
einen Fehler:
1
ERROR:Place:1205 - This design contains a global buffer instance,
2
<clk0/clkout1_buf>, driving the net, <ADC_Clock_out_OBUF>, that is driving
3
the following (first 30) non-clock load pins off chip.
4
< PIN: ADC_Clock_out.O; >
5
This design practice, in Spartan-6, can lead to an unroutable situation due
6
to limitations in the global routing. If the design does route there may be
7
excessive delay or skew on this net. It is recommended to use a Clock
8
Forwarding technique to create a reliable and repeatable low skew solution:
9
instantiate an ODDR2 component; tie the .D0 pin to Logic1; tie the .D1 pin to
10
Logic0; tie the clock net to be forwarded to .C0; tie the inverted clock to
11
.C1. If you wish to override this recommendation, you may use the
12
CLOCK_DEDICATED_ROUTE constraint (given below) in the .ucf file to demote
13
this message to a WARNING and allow your design to continue. Although the net
14
may still not route, you will be able to analyze the failure in FPGA_Editor.
Wie umgehe ich das? Also wie schaffe ich es, dass der Takt direkt über
ein Taktnetz auf das Pad geroutet wird? Ich hab schon viel dazu gesucht
aber da finde ich nur Zeug zu Takteingängen ...
Danke!
die übliche Lösung steht in der Fehlermeldung mit dabei:
Gustl B. schrieb:> 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.
Du belässt den 65MHz-Takt also auf dem Taktnetz, und du taktest damit
ein DDR-Ausgangsregister, das mit der steigenden Takflanke eine 1 und
mit der fallenden Flanke eine 0 nach außen treibt.
Gustl B. schrieb:>> Wie umgehe ich das? Also wie schaffe ich es, dass der Takt direkt über> ein Taktnetz auf das Pad geroutet wird? Ich hab schon viel dazu gesucht> aber da finde ich nur Zeug zu Takteingängen ...>
Den Ausgang als ODDR konfigurieren. Auszugebende Daten "01" oder "10" je
nach gewünschter Phase.
Das ist noch nicht die Lösung denke ich, denn Du treibst da nicht so,
wie es physikalisch vorgesehen ist. Die saubere Mimik ist die Folgende:
Clock Capable Input Pin -> IBUF -> ClockInSig
1) ClockInSig -> BUFG -> Design, z.B. Reset-Schaltung
2a) ClockInSig -> ohne BUFG an PLL-INPUT 50MHz
oder
2b) ClockInSig an ODDR_p (mittels Inverter an ODDR_n)
Statt Version 2 auch so:
ClockInSig -> PLL-INPUT, PLL´
Pll-Ouput -> BUFG -> ClockSigBuffered
Pll-Ouput180 -> BUFG -> ClockSigBufferedInv
ClockSigBuffered -> Design
ClockSigBuffered -> ODDR_P
ClockSigBufferedInv -> ODDR_N
Konkret bei Dir muss als Ausgang ein "normaler" Pin genommen werden.
Dazu ein ODDR. "CC" nur für Eingänge
Und, man muss aufpassen ob man den CoreGen richtig gesetzt hat, ob er
also Buffer hinzufügen soll oder nicht und ob man das bei der Synthes
richtig eingeschaltet hat. Gfs kriegt man nämlich einen Buffer zu wenig
oder einen zuviel.
Ok, Danke! In meiner Vorstellung dachte ich man könnte das Taktnetz da
direkt an einen Ausgang geben und muss dafür auch einen speziellen IO
Pin verwenden. Aber gut, werde das mal anders probieren.
Edit:
Hab das jetzt so gemach:
1
clk0:clk_65mhzPORTMAP(
2
clk=>CLK,
3
clk65=>ADC_Clock_intern,
4
clk25=>CLK25);
5
6
oddr2_inst:ODDR2
7
genericmap(
8
DDR_ALIGNMENT=>"C0",
9
INIT=>'0',
10
SRTYPE=>"ASYNC")
11
portmap
12
(D0=>'1',
13
D1=>'0',
14
C0=>ADC_Clock_intern,
15
C1=>notADC_Clock_intern,
16
CE=>'1',
17
Q=>ADC_Clock_out,
18
R=>'0',
19
S=>'0');
Funktioniert, sieht am Oszi leicht anders aus wie vorher wo ich das oder
das ODDR2 gemacht habe. Den Pin musste ich nicht wechseln.
Gustl B. schrieb:> In meiner Vorstellung dachte ich man könnte das Taktnetz da> direkt an einen Ausgang geben
Dies würde eine Verbindungsoption erfordern, die es in FPGAs nicht
(mehr) gibt. Bei PLDs gibt (und bei den ersten FPGAs gab) es da keinen
Unterschied. Man konnte munter gaten Takte verunden und verordern und
quer durchs Design hin und her routen und auch ausgeben.
Bei hohen Taktfrequenzen erfordern synchrone Designs aber echte
dedizierte FF-Architekturen mit gut balancierten Taktnetzbäumen. Da kann
man nicht einfach irgendwie viel dranhängen und herumgaten. Mithin sind
Taktnetze in einigen FPGAs / ASICs auch differenziell ausgelegt.
Ausgangspins lassen sich somit nur über Kombinatorik mit/ohne FF
betreiben und die einzige Möglichkeit, ihn mit voller Taktfrequenz zu
tooglen ist, ihn als DDR zu nutzen. Daher macht man das so. Wenn Du den
Takt, mit dem Du das DDR-FF antreibst, aus einer PLL gewinnst, kannst Du
die Phase beliegt zu den Daten verschieben, wie es der DAC braucht.