Hallo Miteinander. Ich habe folgendes Problem und bitte nun um ein paar Denkanstöße. Es soll synthetisierbar sein. Ich habe mir ein FiFo gebastelt mit den folgenden Eingängen: DataIn (std_logic_vector) DataOut (std_logic_vector) WriteClk (std_logic) ReadClk (std_logic) SysClk (std_logic) Aufgabe des FiFo's ist es 2 Teile mit verschiedenen Clocks zu verbinden. Ich habe mir die Übernahme der Daten in das FiFo mit der steigenden Flanke von WriteClk vorgestellt und das Auslesen mit ner steigenden Flanke von ReadClk. Mit dem Takt SysClk habe ich das FiFo intern synchronisiert (Also so, dass mit dem SysClk in das FiFo geschrieben und aus dem FiFo gelesen wird). Allerdings habe ich die Signale ReadClk und WriteClk bisher nur auf = '1' abgefragt. Somit habe ich ein Problem wenn die Signale ReadClk oder WriteClk länger als ein Takt (SysClk) anstehen. Mein Lösungsvorschlag wäre einfach auf SysClk und ReadClk bzw. WriteClk abzufragen. Aber da gibt mir das ISE eine Fehlermeldung bezüglich mehrerer Clocks aus (...appears to be controlled by multiple clocks.) (Was ja auch stimmt) Hätte vielleicht jemand einen Vorschlag wie ich das ganze lösen könnte? Vielen Dank schon mal im voraus VG Martin R.
Mit drei Takten ist das nirgends synthetisierbar. Fuer zwei Takte benutzt du am besten den core generator von ISE - da kannst du sicher sein, dass es funktioniert. Eigene Codes mit zwei getrennten Clocks sind machbar, aber im Aufwand nicht zu unterschaetzen. Es gibt auch eine Application Note von Xilinx mit passenden vhdl-Quellen: xapp258.
Merk dir den alten Zustand der beiden Takte und reagiere auf
> if WriteClkOld='0' and WriteClk='1' then --- steigende Flanke
Ich hoffe, du hast die Schreib- und Lesetakte schon einsynchronisiert?
Oder setze mit der steigenden Flanke von WriteClk ein Merker-FF und
setze das mit dem eigentlichen Lesevorgang zurück.
Aber ich würde an deiner Stelle mal ganz tief in mich gehen, und
kontrollieren, ob da wirklich 3 Takte nötig sind. Alles ungleich 1 Takt
ist ein potenzieller Kündigungsgrund ;-)
Hallo Miteinander Danke für die schnellen Antworten. Das mit dem Core-Generator... Hätte es lieber selbst geschrieben, dann weiß ich genau wie das Ding funktioniert. Außerdem 100 Seiten Beschreibung für nen FiFo ist schon ein bisschen viel. Ich nehm das mal als letzte Möglichkeit. Ich denke, dass ich zuerst das mit dem MerkerFF nochmal ausprobiere. Aber ich würde an deiner Stelle mal ganz tief in mich gehen, und kontrollieren, ob da wirklich 3 Takte nötig sind. Alles ungleich 1 Takt ist ein potenzieller Kündigungsgrund ;-) Naja. 2 Takte habe ich ja schon..... Da dachte ich mir: Einer mehr oder weniger... Wegen dem: Oder setze mit der steigenden Flanke von WriteClk ein Merker-FF und setze das mit dem eigentlichen Lesevorgang zurück. Was für einen Lesevorgang meinst Du? VG Martin R.
> Naja. 2 Takte habe ich ja schon..... > Da dachte ich mir: Einer mehr oder weniger... So hast du aus 2 möglichen Domänenübergängen (hin- und zurück) gleich 6 gemacht. Aber wie heißt es so schön: "Ist der Ruf erst ruiniert, lebt sichs völlig ungeniert" ;-)
Lothar Miller wrote: > So hast du aus 2 möglichen Domänenübergängen (hin- und zurück) gleich 6 > gemacht. Aber wie heißt es so schön: > "Ist der Ruf erst ruiniert, lebt sichs völlig ungeniert" ;-) Ich bin noch jung und unerfahren... Das mit dem MerkerFF sieht dann so aus? pEdgeDetect : process (sSysClk, spoWriteClk, sTemp) is begin if rising_edge (sSysClk) and spoWriteClk = '1' and sTemp = '0' then sTemp <= '1'; sWriteClk <= '1'; else sTemp <= '0'; sWriteClk <= '0'; end if; end process; Jetzt habe ich schon wieder ein : Signal sWriteClk cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
> if rising_edge (sSysClk) and spoWriteClk = '1' and sTemp = '0' then Nein, sowas findest du sicher in keinem Buch gängiger Lehrmeinung. Obwohl das u.U. als Clock-Enable synthetisierbar wäre, wie die Meldung > is not supported in the current software release schon vermuten lässt ;-) Zäumen wir das Pferd mal von vorne auf: Welches FPGA? Wie sind deine (3) Takt-Frequenzen? Ist der Sys-Clock der sonst überall verwendetete FPGA-Clock? Ist der Read-Clock synchron zum Sys-Clock?
http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO2.pdf beantwortet alle etweige Fragen zu asynchronen Fifos.
Hallo ich habe das jetzt mit einer händisch beschriebenen Flanke (mittels zweier Signale) gemacht. Ich hab halt jetzt den Nachteil, dass das Signal mindestens 2 Takte stail anliegen muss. Auf der Seite B habe ich ein einen MicroBlaze. Dieser läuft mit 100MHz. Dieser Takt (SysClk) habe ich auch wieder phasensynchron herausgeführt und wird überall verwendet. Der MB soll die Daten aus dem FiFo lesen sobald Daten darin stehen. --> Somit kommt der ReadClk synchron zum SysClk. Aber nicht jedes mal. Auf der Seite A ist ein Teil, dass die Daten in das FiFo reinschreibt. Das Schreiben erfolgt auch synchron zum SysClk. Aber nicht bei jedem SysClk. Im Moment läuft das auf einem Virtex5. Soll aber auf allen möglichen Xilinx-Fpga's funktionieren. Ich hoffe ich konnte nun alle Fragen beantworten und bedanke mich für die Hilfe. VG Martin R.
> Dieser Takt (SysClk) habe ich auch wieder phasensynchron herausgeführt > und wird überall verwendet. > Der MB soll die Daten aus dem FiFo lesen sobald Daten darin stehen. > --> Somit kommt der ReadClk synchron zum SysClk. Aber nicht jedes mal. Zusammenfassung: Wenn er kommt, dann synchron. > Auf der Seite A ist ein Teil, dass die Daten in das FiFo reinschreibt. > Das Schreiben erfolgt auch synchron zum SysClk. > Aber nicht bei jedem SysClk. Zusammenfassung: Wenn er kommt, dann synchron. Über alles: du hast offenbar ein Synchrones Design. Gut. Dann solltest du den ReadClk und den WriteClk einfach nicht als Clock, sondern als Enable nehmen (ReadEnable und WriteEnable). Fertig: keine Latency, alles synchron. Ich habe mir da mal so ein Template gebastelt, das funkt ganz gut:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity FIFO is |
6 | Generic ( |
7 | Addrbreite : natural := 8; -- Speicherlänge = 2^Addrbreite |
8 | Wortbreite : natural := 8 |
9 | );
|
10 | Port ( Din : in STD_LOGIC_VECTOR (Wortbreite-1 downto 0); |
11 | Write : in STD_LOGIC; |
12 | Dout : out STD_LOGIC_VECTOR (Wortbreite-1 downto 0); |
13 | Read : in STD_LOGIC; |
14 | Empty : out STD_LOGIC; |
15 | Full : out STD_LOGIC; |
16 | CLK : in STD_LOGIC |
17 | );
|
18 | end FIFO; |
19 | |
20 | architecture Behavioral of FIFO is |
21 | |
22 | signal wrcnt : integer range 0 to (2**Addrbreite)-1 := 0; |
23 | signal rdcnt : integer range 0 to (2**Addrbreite)-1 := 0; |
24 | type speicher is array(0 to (2**Addrbreite)-1) of unsigned(Wortbreite-1 downto 0); |
25 | signal memory : speicher; |
26 | signal full_loc : std_logic; |
27 | signal empty_loc : std_logic; |
28 | |
29 | begin
|
30 | process begin |
31 | wait until rising_edge(CLK); |
32 | if (Write='1' and full_loc='0') then |
33 | memory(wrcnt) <= unsigned(Din); |
34 | wrcnt <= wrcnt+1; |
35 | end if; |
36 | if (Read='1') then |
37 | Dout <= std_logic_vector(memory(rdcnt)); -- Adresse getaktet --> BRAM |
38 | rdcnt <= rdcnt+1; |
39 | end if; |
40 | end process; |
41 | |
42 | full_loc <= '1' when rdcnt = wrcnt+1 else '0'; |
43 | empty_loc <= '1' when rdcnt = wrcnt else '0'; |
44 | Full <= full_loc; |
45 | Empty <= empty_loc; |
46 | |
47 | end Behavioral; |
Hallo Lothar Tut mir leid, dass ich mich erst jetzt wieder melde. Ich habe Dein Code simuliert. Dieser übernimmt jedesmal die Daten am DIN wenn ein Clk kommt und WriteEnable = 1 ist. Das hat mein Code am Anfang auch. Dachte, dass wäre ein Fehler und deswegen hab ich mit der Flankenerkennung rumgespielt. Das hat dann nicht so richtig geklappt weil ich das Timing der anliegenden Daten nicht so recht beeinflussen konnte. Ich habe dann den Block auf der Seite A mal genau simuliert und da kam heraus, dass das Data-Ready-Signal erst kommt wenn die Daten schon fertig sind und nicht erst mit der fallenden Flanke ready sind. Außerdem kommt es genau einen Takt. usw usw. Auf jedenfall kann ich nun das Data-Ready-Signal so nehmen wie es ist ohne mir einen Kopf machen zu müssen. Dein FiFo würde übrigends auch bei mir gehen. Manchmal muss man wohl einfach mal probieren und dann nachbessern als vorher denken und alles unnötig aufblähen... Nochmals VIELEN DANK Martin
Hallo, wie ich sehe, zählt "rdcnt" (als Integer definiert) ohne Max-Wert-Abfrage o.Ä. Was passiert, wenn (im gezeigten Fall für "Adressbreite=8") der Zähler auf 9 springen möchte ? Gruß SuperWilly
>Was passiert, wenn (im gezeigten Fall für "Adressbreite=8") der Zähler >auf 9 springen möchte ? Dann kann er das tun. Der Speicher ist ja erst bei 2**Addrbreite zuende. Da das eine Zweierpotenz ist, laeuft der Zaehler automatisch nach 0 ueber (wenn er die richtige Breite hat, was die Synthese so erzeugen sollte). Vielleicht sollte man sich aber trotzdem nicht darauf verlassen, dass die Synthese genau die richtige Vektorbreite verwendet, schliesslich gibt man mit range nur eine Mindestgroesse an.
Ja sorry, meinte eigentlich: Was passiert, wenn der Zähler auf (2**Addrbreite) springen möchte ... Gruß, SuperWilly
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.