Forum: FPGA, VHDL & Co. Ringpuffer mit Offset im read und write pointer


von Thomas (Gast)


Lesenswert?

Hallo,

ich würde in VHDL gerne eine Art Ringpuffer realisieren, bei dem es 
möglich ist, dass die write und read pointer nicht immer direkt auf die 
nächste Adresse zeigen sondern jeweils ein offset zur letzten Adresse 
haben können.
Die Abfolge der Adressen ist fix und hängt nur von der gesamt Anzahl der 
Adressen ab.

Etwas blöd zu erklären, also versuch ich es mal an einem kleinen 
Beispiel:
Angenommen wir haben insgesamt 6 Adressen. Dann sollen die Adressen wie 
folgt abgelaufen werden.

                1.Umlauf     2.Umlauf  3.Umlauf  4. Umlauf  5. Umlauf

write Adressen: 1 2 3 4 5 6   1 3 5     2 4 6      1 3 5      2 4 6 usw.

read Adressen :   1   3   5   2 4 6     1 3 5      2 4 6      1 3 5 usw.

Wie könnte ich so etwas am besten realisieren so dass es auch bei hohen 
Taktraten (> 200 MHz) noch funktioniert. Die gesamt Anzahl der Adressen 
kanns sich ändern wird aber immer 2ˆn sein (2 4 8 16 32 64...)

Kann mir jeamnd ein kurzes Code Beispiel schreiben?

Vielen Dank!

von Freddy (Gast)


Lesenswert?

sehe ich es richtig, dass Du ein einem etwas schreiben willst und im 
anderen etwas auslesen willst?
z.B. mit einem anderen Prozess? Was hälst Du davon ein DualPort Ram zu 
nehmen?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Thomas schrieb:
> read Adressen :   1 3 5     2 4 6     1 3 5      2 4 6      1 3 5 usw.
Wann findet denn da die Umschaltung von gerade nach ungerade statt? 
Immer am "Ende" des "Rings"? Ist dir klar, das ein Ring per Definition 
eigentlich kein Ende hat?

> Kann mir jeamnd ein kurzes Code Beispiel schreiben?
Ist das jetzt dein Ernst?
Wofür brauchst du das?
Was ist dein Speicher?

von Josef G. (bome) Benutzerseite


Lesenswert?

So wie ich das sehe, sind das doch einfach zwei Ringpuffer,
die abwechselnd verwendet werden ? ?

von Gustl B. (-gb-)


Lesenswert?

Du könntest immer das Ende eines Durchlaufs erkennen, also wann die 
höchste Addresse erreicht wurde und dann das um 1 verschieben.

Also du nutzt ja jede 2. Addresse, also 1. Durchlauf:
1 3 5 7 9 ... 1023, Ende erkennen, also ein einziges Mal eine Addresse 
um 1 oder 3 erhöhen, dann zweiter Durchlauf
2 4 6 8 ... 1024, wieder Ende erkennen.

Tja und das musst du halt für Lese- und Schreiboperation so bauen, dass 
die jeweils das gewünschte bekommen.

Ich sehe darin nur keinen Sinn?!

Willst du den Speicher für zwei Operationen aufteilen? Vielleicht kannst 
du dann der einen generell alle geraden und der anderen alle ungeraden 
Addressen geben, einfacher wäre es aber jeder seinen Addressbereich zu 
geben.

Also erkläre mal wozu du das brauchst, man kann es vermutlich anders 
lösen.

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Wenn du (2^n)-1 nimmst, kannst du doch immer +2 machen, oder?

lg

von Gustl B. (-gb-)


Lesenswert?

Gute Idee! Hatte ich gar nicht dran gedacht ...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Christopher B. schrieb:
> Wenn du (2^n)-1 nimmst, kannst du doch immer +2 machen, oder?
Und wer macht dann den Überlauf?

von Gustl B. (-gb-)


Lesenswert?

Ach so, ja, man würde dann lesen und schreiben bei entweder geraden oder 
ungeraden Addressen machen und eben nicht versetzt. Also muss man doch 
verschieben wie ich oben schrieb.
Und damit lesen und schreiben jeweils die anderen Adressen nutzen müsste 
man die Zahl der Durchläufe zählen oder irgendwie etwas bauen das sagt 
was gerade die garaden und was die ungeraden Addressen nutzen soll.

Das Problem weshalb das aber nicht Sinnvoll ist:
Wenn der Puffer eben eben nicht voll ist, also nur langsam geschrieben 
wird, dann müsste man mit dem Lesen immer warten. Also man schreibt 
zuerst alle ungeraden Addressen und erst danach beginnt man diese zu 
lesen und schreibt die geraden Addressen. Also eher sehr komisch.

Mir ist aber immer noch nicht klar wozu das nützlich sein soll.

von Kai S. (kai1986)


Lesenswert?

Hallo,

Thomas schrieb:
> 1.Umlauf     2.Umlauf  3.Umlauf  4. Umlauf  5. Umlauf
>
> write Adressen: 1 2 3 4 5 6   1 3 5     2 4 6      1 3 5      2 4 6 usw.
>
> read Adressen :   1   3   5   2 4 6     1 3 5      2 4 6      1 3 5 usw.


bekommt man nicht die gleiche Funktionalität, wenn man die 
Speicheradressen einfach umbenennt? Zum Beispiel so

                1.Umlauf     2.Umlauf  3.Umlauf  4. Umlauf  5. Umlauf

write Adressen:   4   5   6   1 2 3     4 5 6      1 2 3      4 5 6 usw.

read Adressen :   1   2   3   4 5 6     1 2 3      4 5 6      1 2 3 usw.

dann müsste man lediglich beim Initialisieren 1-3 einmal beschreiben.

Gruß Kai

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Lothar Miller schrieb:
> Und wer macht dann den Überlauf?

Ich hab leider keine Ahnung von VHDL, ich hab nur etwas nachgedacht und 
bin darauf gekommen. Vielleicht hat es ihm ja etwas genutzt.

lg

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Christopher B. schrieb:
> Ich hab leider keine Ahnung von VHDL, ich hab nur etwas nachgedacht und
> bin darauf gekommen.
Mit VHDL wird Hardware beschrieben. Und aus VHDL wird dann letztliche 
Hardware gemacht. Nur gibt es in richtiger Hardware eben keinen Zähler, 
der so einfach und von sich aus an einer 2^n-1 Grenze überlaufen würde.

Thomas schrieb:
>                   1.Umlauf    2.        3.         4.        5. Umlauf
> write Adressen: 1 2 3 4 5 6   1 3 5     2 4 6      1 3 5      2 4 6 usw.
> read Adressen :   1   3   5   2 4 6     1 3 5      2 4 6      1 3 5 usw.
Wenn man den ersten Durchlauf/Initialisierung weglassen könnte, dann 
wäre das unglaublich einfach: ein stinknormaler Ringpuffer ohne Offest 
und sonstwas. Denn dann ist die Schreibreihenfolge gleich der 
Lesereihenfolge:
> write Adressen:               1 3 5     2 4 6      1 3 5      2 4 6 usw.
> read Adressen :   1   3   5   2 4 6     1 3 5      2 4 6      1 3 5 usw.
Schreibreihenfolge: 135246135246
Lesereihenfolge:    135246135246

von Uwe (Gast)


Lesenswert?

Vom Adresszähler (Counter) wird das 3. Bit (q3)mit dem 0. Adressbit (A0 
write) des write-Adressbusses des Dual Port RAMs verbunden, das 
invertierte 3. Bit (/q3) mit dem 0. Adressbit (A0 read) des 
read-Adressbusses.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ich würde da einfach mal behaupten, dass dieser "Ringpuffer in 
Wirklichkeit ein Fifo ist. Und bei einem Fifo sollten aber m.E. die 
Schreib und Leseadressen unabhängig sein. Deshalb sollte es da 2 
Adresszähler geben...

Oder ist da tatsächlich eine starre Kopplung benötigt?

Es stellt sich also die Frage:
Thomas schrieb:
> ich würde in VHDL gerne eine Art Ringpuffer realisieren
WOFÜR?

von Thomas (Gast)


Lesenswert?

Hallo,

also erst mal danke für die vielen Antworten.

Entschuldigung für die Verwirrung, das Beispiel sollte nur das Prinzip 
zeigen. Später werden die write und read adressen nicht mehr durch 
einfaches +2 erzeugt werden können.

Dann mal was ich machen möchte.
Ich bekomme in einzelnen Streams Rohdaten in falscher Reihenfolge. Ich 
möchte die Rohdaten "on the fly" in die richitge Reihenfolge bringen 
bevor ich sie weiter verabeiten kann. Das heisst mit minimalem BRAM 
verbrauch.

Beispiel: Rohdaten bestehen insgesamt aus 20 Bit

Stream 1: Eingang 1 3 5 7 9 2 4 6 8 10
Stream 2: Eingang 11 13 15 17 19 12 14 16 18 20

Sortieren: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

(dies ist nur ein Beispiel, die Reihenfolge der Daten am Eingang kann 
auch ander aussehen)

Ich würde gerne wissen wie ich die Sortierung am besten mache.

Da ich eben so wenig BRAM wie möglich verwenden möchte, dachte ich mir 
ich nehme eine Art Ringpuffer (ich weiss der hat eigentlich kein Ende 
deshalb so eine Art wie ... ) der genau so groß ist dass ich nur die 
mindest Anzahl an Bits reinschreibe um sortieren zu können und dann die 
freien Speicherplätze wieder verwende.

Also für das Beispiel oben wäre das ein Speicher für 7 Bits (evt. 
klappts auch schon mit 6) dann schreibe ich

1 3 5 7 9 und 2 rein (ein Platz ist noch frei)

dann lese ich die 1 aus und schreibe die gerade kommende 4 an die noch 
frei Stelle.

dann lese ich die 2 aus und schreibe die gerade kommende 6 an die Stelle 
wo fühere die 1 stand

nun lese ich die 3 aus und schreibe die greade kommende 8 and die Stelle 
wo fühere die 2 stand

usw. und so fort.

Ich bin mir nur nicht sicher wie ich das am besten mach, damit das auch 
bei hohen Taktraten klappt.

Viele Grüße

von Uwe (Gast)


Lesenswert?

Zwei Schieberegister aus Flipflops die Parallelen Ausgäge der FFs in der 
richtigen Reihenfolge an ein anderes SR aus FFs an den parallelen 
Eingängen.

von Uwe (Gast)


Lesenswert?

Natürlich noch ein bischen Logik drumherum z.B. ein Counter der die 
Richtige anzahl der bits Abzählt bzw. mit Komperator für den Alarmwert 
bzw. die FFs nicht fest verdrahten sondern über programmierbare 
Multiplexer usw.

von Thomas (Gast)


Lesenswert?

Hey Uwe,

der Vorschlag gefällt mir sehr gut, das werd ich mal ausprobieren.

Danke!

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
Noch kein Account? Hier anmelden.