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?
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!
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!
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...