Hallo, ich habe mal wieder ein kleines Problemchen. Vorgeschichte: Ich habe ein Videosignal (ITU.656) mit 27 MHz Pixeltakt und 8bit Datenbreite. Es werden hierbei Luminanz- und Chrominanzdaten alternierend geschickt. Ich selbst arbeite jedoch intern nur mit dem Luminanzanteil (schwarz-weiß) und daher mit 13,5 MHz Pixeltakt. Problem: Mein verarbeiteter Luminanzanteil kommt mit 13,5 MHz aus meiner Verarbeitungspipeline und soll nun an den Videoencoder mit 27 MHz übergeben werden. Hierfür ist es notwendig, dass der Chrominanzanteil "blanked" übertragen wird. Einfachste Lösung wäre wahrscheinlich ein asynchrones FIFO, dass mir die 16bit->8bit Wandlung (8 bit Luminanz und 8 bit Chrominanz "blanked") und den Taktübergang (13,5 MHz -> 27 MHz) abnimmt. Diese Lösung möchte ich aber vermeiden, da mir der Blockram langsam ausgeht. Gibt es eine Lösung für mein Problem, die ohne Blockram auskommt? Bin für jeden Tipp dankbar Gruß Marcus
> Gibt es eine Lösung für mein Problem, die ohne Blockram auskommt?
Distributed Ram ;-)
Sind die beiden Takte synchron zueinander? Wird ein Takt aus dem anderen
gewonnen? Falls ja: warum dann für diese Wandlung überhaupt ein Fifo? Da
würde offenbar ein einfacher MUX ausreichen...
Hallo Lothar,
nochmal kurz mein Vorhaben:
Daten kommen mit 13,5 MHz und 16bit breit an und müssen mit 27 MHz und
8bit breit wieder raus.
Den 27 MHz Takt erzeuge ich per DCM aus dem 13,5 MHz Takt.
Die Distributed RAM FIFOs, die der Xilinx Coregen erzeugen kann
akzeptieren leider keine unterschiedlichen Eingangs/Ausgangsbreiten.
> Da würde offenbar ein einfacher MUX ausreichen...
Stimmt, theoretisch wäre es ein einfacher MUX (bzw. eigentlich eine Art
SERDES), aber ich weiß nicht wie ich das realisieren soll.
(Das FIFO ist mir nur als schneller Workaround eingefallen)
Wenn ich die 16bit mit dem 13,5 MHz Takt aktualisier und dann mit 27 MHz
je high- und lownibble übernehme, wie stelle ich sicher dass das 16bit
Signal schon stabil anliegt wenn die nächste steigende 27 MHz Flanke
kommt (zeitgleich zur fallenden 13,5 MHz Flanke)?
Oder mach ich mir hier zu viele Gedanken und die Xilinx-Tools erkennen
was ich vorhab?
Gruß
> Oder mach ich mir hier zu viele Gedanken und die Xilinx-Tools erkennen > was ich vorhab? Wenn die Takte über einen DCM zusammenhängen und du die entsprechenden Constraints gesetzt hast, tun sie das.
Das geht dann wirklich über einen einfachen Mux. Die Phasenbeziehung zwischen Eingangs- und Ausgangstakt des DCM ist ja fest (sofern du kein PhaseShift machst) und da kannst du das ganz einfach umschalten. Ich würde aber den Takt außerdem noch vervierfachen (CLKFX) und damit wieder ein FlipFlip ansteuern, dessen Ausgang den Muxer schaltet. ISE mag es nicht, wenn der Takt für Kombinatorik verwendet wird, weil der Router dann keine dedizierten CLock Leitungen benutzen kann. Den doppelten Takt für das weitere System bekommst du aus dem CLK2X des DCM dann... Nutzt du direkt den 2-fachen Takt zum Muxen bekommst du das: LIT:176 - Clock buffer is designated to drive clock loads. BUFG symbol "Clock/BUFG_inst" (output signal=BusCLK2) has a mix of clock and non-clock loads. The non-clock loads are: ... Und das Route:455 - CLK Net:BusCLK2 may have excessive skew because 0 CLK pins and 2 NON_CLK pins failed to route using a CLK template.
Hi, hier mein erster Versuch:
1 | reg: process(CLK_0) |
2 | begin
|
3 | if rising_edge(CLK_0) then |
4 | mux <= DI_16b; |
5 | end if; |
6 | end process; |
7 | |
8 | mux: process(CLK_2X) |
9 | begin
|
10 | if rising_edge(CLK_2X) then |
11 | if nibble = '0' then |
12 | DO_8b <= mux( 7 downto 0); |
13 | else
|
14 | DO_8b <= mux(15 downto 8); |
15 | end if; |
16 | nibble <= not(nibble); |
17 | end if; |
18 | end process; |
Problematisch ist hier allerdings, dass Beziehung vom nibble zum CLK_0 nicht sichergestellt ist. Wie kann ich sicherstellen, dass während CLK_0 = '1' das untere nibble rausgeht und während CLK_0 = '0' das obere? > Ich würde aber den Takt außerdem noch vervierfachen (CLKFX) und damit > wieder ein FlipFlip ansteuern, dessen Ausgang den Muxer schaltet. Hab mir das mal aufgezeichnet, aber verstehe nicht, was ich mit dem vierfachen Takt schalten soll. Ich glaub ich steh grad etwas auf dem Schlauch :)
Achso, 4-facher Takt ist nicht nötig, da hab ich mich wohl vertan (Das kam aus einem Design bei uns hier....sorry). So wie du es jetzt hast, sollte es doch gehen? Oder nicht? Der 2-fache Takt ist durch den DCM in Phase mit dem CLK_0. Was sagt denn der Simulator dazu?
> wie du es jetzt hast, sollte es doch gehen?
Es geht leider nur gelegentlich.
Die Takte sind zwar in Phase, aber es gibt da noch eine Fehlerquelle:
Das Design muss nach der steigenden Flanke der CLK_0 zuerst das untere
nibble rausschieben und dannach das obere. Das ist derzeit nicht
sichergestellt, da der Wert von "nibble" bei der steigenden CLK_0 Flanke
entweder 1 oder 0 sein kann. Das hängt wahrscheinlich vom Start der DCM
ab, am Anfang können da ja noch krumme Takte auftreten.
Der Simulator sagt zu dem Fall nchts, denn die DCM ist ja beim Start
etwas vom Zufall beherrscht.
Soo, hab eine Lösung gefunden, die anscheinend auch funktioniert :)
1 | reg: process(CLK_0) |
2 | begin
|
3 | if rising_edge(CLK_0) then |
4 | sv_mux <= DI_16b; |
5 | sl_tog <= not(sl_tog); |
6 | end if; |
7 | end process; |
8 | |
9 | mux: process(CLK_2X) |
10 | begin
|
11 | if rising_edge(CLK_2X) then |
12 | if(sl_nibble = '1') then |
13 | DO_8b <= sv_mux( 7 downto 0); |
14 | else
|
15 | DO_8b <= sv_mux(15 downto 8); |
16 | end if; |
17 | sl_tog_p <= sl_tog; |
18 | if(sl_tog /= sl_tog_p) then |
19 | sl_nibble <= '1'; |
20 | else
|
21 | sl_nibble <= '0'; |
22 | end if; |
23 | end if; |
24 | end process; |
Am Schalten von sl_tog kann ich die Flankenbeziehung zwischen den beiden Takten zurückgewinnen und so den MUX richtig synchronisieren. Nur noch eine Frage: Brauche ich um dieses Modul abzusichern noch eine Timing Constraint? Muss ich ISE mitteilen, dass sl_tog (durch CLK_0 geschaltet) bis zur nächsten steigenden Flanke von CKL_2X geschalten haben muss? Wenn ja, wie mach ich das? ;)
Naja, die Quick´n´Dirty Lösung ginge ja auch noch:
1 | ...
|
2 | if CLK_0 = '1' then DO_8b <= mux( 7 downto 0); |
3 | else DO_8b <= mux(15 downto 0); |
4 | ...
|
Allerdings gibts dann diese Warnungen. Bei 27Mhz sollte es aber keine Timing-Probleme am Ende geben. Das beste wäre, wenn man ein DDR Register intern verwenden könnte....aber das geht ja schlecht, weil die direkt auf den IOB sitzen.
Hallo Markus, Du hast hier ja schon eine menge Möglichkeiten aufgezeigt bekommen, wie Du die 13,5MHz wieder aus 27MHz bekommst und die Daten dazu muxen kannst. Was mir bei der ganzen Diskussion fehlt ist die Frage, warum Du aus deinen 27MHz erst 13,5MHz machst, wenn Du am Schluss doch wieder 27MHz benötigst... Du hast jetzt nicht geschrieben welche Targettechnologie Du verwendest, aber es sollte eigentlich kein Problem darstellen, die Datenverarbeitung intern mit 27MHz laufen zu lassen. Im Bedarfsfall hast Du auch die Möglichkeit bei den getakteten Teilen über den Clockenable das Ding sozusagen auf 13,5 Mhz runterzufahren und dies auch dem Synthesetool mitzugeben ( Multicycle Constraints ). was meist nicht mitspielt, sind Xilinx Corecomponenten... Aber bevor ich mir Gedanken mache meinen Takt erst zu halbieren und dann wieder zu verdoppeln... Gruß Andreas
Hallo Andreas, also das ganze war eigentlich mal so geplant: Die Daten sollten vom Decoder über einen 16bit Bus mit 13,5 MHz kommen, durch einen Verarbeitungsblock laufen und anschließend über einen 16bit Bus mit 13,5 MHz zum Encoder laufen. Der neue Encoder kann jetzt allerdings nur mit einem 8bit Datenbus, mit 27 MHz umgehen. Um möglichst wenig am Design zu ändern dacht ich mir, ein asymmetrisches asynchrones FIFO löst das Problem schnell und einfach, dann hab ich aber bemerkt, dass der BRAM schon am Ende ist. Daher nun die Sache mit dem MUX. Es kommt also derzeit vom Decoder Daten und Takt mit 13,5 MHz rein. Intern wird dann per DCM der 27 MHz Takt für den Ausgang generiert. Würde ich jetzt den Eingang aber mit der "clock enable" Methode abtasten wollen, so müsste ich auch hier die Flankenbeziehung zwischen dem 13,5 MHz und dem 27 MHz Takt wissen (ich darf ja nur bei 13,5 MHz rising_edge abtasten). Ich hätte also das Problem nur vom Ausgang zum Eingang verlagert. > Aber bevor ich mir Gedanken mache meinen Takt erst zu halbieren und dann > wieder zu verdoppeln.. Ich hab mich im ersten Post leider etwas missverständlich ausgedrückt > Daten kommen mit 13,5 MHz und 16bit breit an und müssen mit 27 MHz und > 8bit breit wieder raus. Danke für eure Mithilfe, mit meinem geposteten Schnipsel funkionierts jetzt so wie es soll (ohne Warnungen ;). Gruß Marcus
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.