Hallo, ich habe hier ein Problem und weiß nicht so recht, wie ich es umsetzen kann. Ich habe ein asynchrones FIFO, also unterschiedlicher Schreib- und Lesetakt. Es werden kontinuierlich Daten in den Fifo geschrieben. Da der Lesetakt aber schneller ist als der Schreibtakt, muss ich eine "Leseverzögerung" einbauen. Gelesen wird von einem externen Device. Ich habe nun vereinbart, dass das externe Device immer 1024 DoubleByte aus dem FIFO lesen soll (FIFO ist 16bit breit x 2048 Zeilen) und dann auf einen Interrupt wartet. Es kann natürlich nur 1024 DByte lesen, wenn diese auch da sind. Das bedeutet, dass der Interrupt erst auslösen darf, wenn die ersten 1024 DByte im Fifo sind. Dazu habe ich mir eine Zählschleife ausgedacht, die immer, wenn 1024 Schreibzyklen vorbei sind, ein Interrupt ausgelöst wird. Nach diesem Interrupt sollen die Daten aus dem FIFO ausgelesen werden, uns zwar synchron zum externen Lesetakt. Wie kann ich die steigende Flanke des IRQ Signals nutzen um dem Read-Device zu sagen, jetzt kannste deine 1024 Datenpakete abholen? Wäre eine Lösung über das Read-enable denkbar? Ich hatte mir gedacht, wieder einen Zähler zu bauen, der bis 1024 zählt und danach den rd_en auf Low letzt und dann erst wieder aktiviert, wenn der Trigger kommt, dass weitere 1024 Datensätze geschrieben wurden. Nur leider muss ich dann den process von dem Triggersignal und dem Readclock abhängig machen, Trigger setzt den counter auf Null und der Readclock zählt ihn nach oben... da bekomme ich aber sicher Probleme bei der Synthese. Hat jemand eine Idee, wie ich diese Sache elegant lösen kann? VIELEN DANK!
Ich gehe mal davon aus, du generierst dir den Fifo mit dem entsprechenden Tool des Herstellers deines FPGAs? Diese bieten meist auch die Option eines "almost empty" oder "almost full" Signals mit einstellbaren Schwellen. Du setzt also die Schwelle fuer das "almost empty" auf 1024. Dann wartest du bis almost empty 0 ist, liest deine 1024 Daten aus und wartest wieder.
Kannst du denn das Lesen nicht stoppen? Normal macht man das so, dass man das Empty Flag des FIFOs natürlich beachtet und nur ausliest, wenn auch was drin ist. Ob du dann 1024 Byte oder sonstwas ausliest ist egal, wichtig ist, den Zähler und die gesamte weitere Verarbeitung anzuhalten, bis wieder was im FIFO ist.
Danke für die Antworten! Ja das Fifo erstelle ich mit dem CoreGen, auch das AlmostEmty Flag ist dabei. Wußte bisher nicht, dass ich dabei eine Schwelle einstellen kann. Das wäre natürlich recht komfortabel. Sobald 1024 DByte drin sind, können sie ausgelesen werden. Das schaue ich mir mal an! Wobei ich hier aber sicher das AlmostFull Bit nehmen muss, denn der FIFO wird ja unterhalb von 1024 aufgefüllt. @ Christian: Ich hatte mir durch diese Methode eigentlich etwas geschaffen, dass es in keinem Fall zu einem empty kommen kann. Dadurch, dass immer 1024 DB ausgelesen werden, aber parallel dazu wieder neue Daten reinkommen, kann es nie leer werden. Denn sobald wieder 1024 da sind, wird wieder ausgelesen. Die Übertragung zum externen Device soll burstartig verlaufen. Also Übertragen (1024x16bit) und dann wieder warten, bis weitere 1024 Pakete anliegen und wieder auslesen... DANKE!!! EDIT: Dabei fällt mir eigentlich auf, dass das Almost_full Flag ja auch nur ein Trigger wäre, den ich mir ja schon künstlich durch die Schleife geschaffen habe. Die kann ich damit abschaffen, aber mein eigentliches Problem, dass der Read-process dann vom externen Readtakt und (!) vom almost_full Flag abhängt, hab ich damit immer noch nicht erschlagen. Ich schau mal, vielleicht fällt mir dazu noch etwas ein... vielleicht funktioniert es ja schon mit einer einfachen if Abfrage und ich komme nur noch nicht drauf :)
Du brauchst eigentlich auch keine getrennten Zähler, das Fifo kann Dir einen Zähler ausgeben, der sagt, wieviel Daten im Fifo sind. Ich würde eine State-Machine bauen, die diesen Zähler beobachtet. Sobald 1024 Daten drinnen sind, fängt dies an, 1024 x auszulesen. Nach dem Auslesen springt man wieder in den Beobachtung-State, wenn wieder 1024 drinnen sind, geht's weiter, sonst wird eben in diesem State gewartet, bis es soweit ist.
Ich bin leider noch nicht so lange im Geschäft :) Wie implementiere ich eine State-machine und wie weise ich ihr eine Funktion zu? Ist das auch nur eine Art automatisch generierter Core, oder muss ich die Funktion selber erzeugen bzw. generieren? Deine Variante klingt recht logisch bzw. sehr anschaulich. Leider habe ich gerade noch das problem, dass mein Fifo auch bei Grenzwert 8 (so viel schreibe ich erstmal testeweise in den Fifo, statt der 1024, damit ich es besser simulieren kann und nicht 1024 Flanken abzählen muss) kein almoist_full Flag setzt, das bleibt leider behaarlich auf 0. DANKE!
Hast du es auch richtig konfiguriert ? Die almost/programmable full/empty Signale funktionieren eigentlich gut. Dann musst du nurnoch dieses Signal auswerten und fertig. - warten bis almost full=1 - 1024 mal auslesen (alternativ : auslesen bis empty = 1 wenn es nicht zwingend maximal 1024er Blöcke sein müssen) - warten bis almost full=1 ... das sind genau 2 Zustände im Automaten(read_enable=0 und read_enable=1) Sowas kannst du noch ganz simpel in 2-3 If-Then erledigen.
Achso, für Burst-Übertragung ist das natürlich dann sehr günstig mit den Flags. Ich glaub, die Almost-Full sind fest, aber Prog-Full kannst du einstellen auf eine beliebige Anzahl. Übrigens werden die Flags synchron zum Takt der jeweiligen Seite ausgegeben. Also Empty synchron zur Lese-Seite und Full synchron zur Schreibseite. Somit kannst du am besten mit dem Prog-Empty Flag arbeiten, das ist dann schon synchron zum Lesetakt.
DANKE für die Antworten und die Hilfe. Kann mir jemand sagen wieso die markierte if-Anweisung in der SImulation ignoriert wird und die Daten sofort an den Ausgang geschaltet werden?
1 | DATA_READ: process (PClk, FIFO_prog_emty, PADD(10), PCS1, POEn, PRnW, PER_RSTn) |
2 | begin
|
3 | if rising_edge(PClk) then |
4 | if (FIFO_prog_emty = '0') then --=> wird in der Simulation ignoriert!!! |
5 | if (PCS1 = '0' and POEn = '0' and PRnW = '1' and PER_RSTn = '1') then |
6 | if (PADD(10) = '1') then |
7 | DATA_OUT <= DATA_OUT_FIFO; |
8 | else
|
9 | DATA_OUT <= (others => 'Z'); |
10 | end if; |
11 | else
|
12 | DATA_OUT <= (others => 'Z'); |
13 | end if; |
14 | else
|
15 | DATA_OUT <= (others => 'Z'); |
16 | end if; |
17 | end if; |
18 | end process; |
Das Z verwende ich nur, um in der Simulation einen besseren Überblick zu haben. Eine blaue Linie ist besser zu unterscheiden als eine weitere Grüne Linie. Mir ist bewußt, dass es diesen Zustand in der Hardware nicht gibt. Entweder er wird noch durch weitere Anweisungen ersetzt, oder es wird dann 0 gesetzt :) VIELEN DANK!
Warum dann nicht mit einer Defaultzuweisung? Dann wird das Ganze wesentlich übersichlicher, weil alle else herausfallen:
1 | DATA_READ: process (PClk, FIFO_prog_emty, PADD(10), PCS1, POEn, PRnW, PER_RSTn) |
2 | begin
|
3 | if rising_edge(PClk) then |
4 | DATA_OUT <= (others => 'Z'); |
5 | if (FIFO_prog_emty = '0') then --=> wird in der Simulation ignoriert!!! |
6 | if (PCS1 = '0' and POEn = '0' and PRnW = '1' and PER_RSTn = '1') then |
7 | if (PADD(10) = '1') then |
8 | DATA_OUT <= DATA_OUT_FIFO; |
9 | end if; |
10 | end if; |
11 | end if; |
12 | end if; |
13 | end process; |
Und das ist letzlich:
1 | DATA_READ: process (PClk) |
2 | begin
|
3 | if rising_edge(PClk) then |
4 | DATA_OUT <= (others => 'Z'); |
5 | if (FIFO_prog_emty = '0' and PCS1 = '0' and POEn = '0' and PRnW = '1' and PER_RSTn = '1' and PADD(10) = '1') then |
6 | DATA_OUT <= DATA_OUT_FIFO; |
7 | end if; |
8 | end if; |
9 | end process; |
BTW: der Prozess ist nur auf PClk sensitiv.
Für solche Vereinfachungen, denke ich, fehlt mir einfach noch der Blick. Ich denke das wird sich dann mit der Zeit ergeben. Freilich kann ich deinen Ausdruck genauso verstehen und nachvollziehen, aber selber darauf gekommen wäre ich nicht :) DANKE... Ich werde mal schauen, ob diese Umformulierung das Problem behebt!
1 | FIFO_prog_emty = '0' |
Diese Abfrage in der if-Anweisung wird einfach ignoriert und der Data_Out Zweig wird rein über das rd_en gesteuert, was aber nun noch testweise per constant auf '1' liegt. Dann wird direkt nach dem Schreiben des FIFOs der Wert wieder ausgelesen und dadurch kann natürlich der prog_emty Wert auch nie 0 werden. Würde die oben genannte Abfrage aber gehen, würden erst eine definierte Anzahl von DByte in das Fifo geschrieben, bevor ausgelesen werden kann. Eine direkte Verknüpfung von rd_en und dem prog_emty ist mir auch noch nicht geglückt, da das Signal dann häufiger toggelt, als die Daten zu Ende ausgelesen werden. Ich denke es ist noch irgendein logischer Fehler, ich muss ihn nur noch finden. Ich versteh die Welt nicht mehr...
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.