Forum: FPGA, VHDL & Co. Große Bit Vectoren im Spartan 3A


von Mr.EMail (Gast)


Lesenswert?

Hallo an Alle,

nach langem Mitlesen im Forum kommt nun mein erster Beitrag bzw. Frage.
Ich arbeite Freizeitmäßig an einem größeren FPGA Projekt und habe dazu 
folgende allgemeine Frage:

Ich benötige einen Speicher, der 2x 6144 Bit lang ist (in ein Vector 
wird geschrieben, der andere gelesen). Die Schwierigkeit dabei ist, dass 
ich die Daten an mehreren Stellen (8) des langen Vectors gleichzeitig 
immer 8 Bit breite Worte auslesen muss bzw. will. Gefüllt wird der 
Vector von vorn nach hinten immer mit 24 Bit breiten Worten.

Das Schreiben und Lesen erfolgt mit unterschiedlichen Takten (Schreiben 
mit 65MHz, auslesen mit etwa 30MHz).

Aus meinem bisherigen Verständniss klappt das so einfach mit BlockRam 
oder ähnlichem nicht weil ich an mehreren Stellen gleichzeitig auslesen 
muss und dazwischen keinen Adresssprung machen kann.

Gibt es eine elegante Lösung für das Problem oder wird das zwangsläufig 
ein 2x6144 großes FlipFlop-Grab?

von Roger S. (edge)


Lesenswert?

Eine elegante Loesung wird es sicher geben, laesst sich aber aus dem 
Informationsgehalt der Fragestellung nicht ermitteln.

Erste Naeherung: nutz die achtfache Anzahl BRAM.

Cheers, Roger

von Duke Scarring (Gast)


Lesenswert?

Datenbreiten kann man mit einem FIFO anpassen, bei dem die Bitbreite auf 
Schreib- und Leseseite sich um ein ganzzahliges Vielfache unterscheiden.

Falls das Schreiben und Lesen in verschiedenen Taktdomänen stattfindet, 
hilft ein asynchrones FIFO weiter.

Aber wie der Name FIFO schon sagt: first in - first out
Ein gleichzeitiges Lesen an unterschiedlichen Stellen ist damit nicht 
möglich.

Wenn es die Anwendung erfordert, ist ein distributed RAM mit 12288 Bit 
nicht unbedingt verschwenderisch bzgl. der Ressourcen. IMO.

Duke

von Schlumpf (Gast)


Lesenswert?

Mr.EMail schrieb:
> Aus meinem bisherigen Verständniss klappt das so einfach mit BlockRam
> oder ähnlichem nicht weil ich an mehreren Stellen gleichzeitig auslesen
> muss und dazwischen keinen Adresssprung machen kann.

Kann man schon mit BRAM machen, wenn man den BRAM mit der minimal 
möglichen Adressbreite und der daraus resultierenden maximalen 
Datenbreite konfiguriert und dann so viele parallel schaltet, bis deine 
gewünschte Datenbreite erreicht ist.
Und dann benutzt man nur die Adresse 0.

Ist zwar ne üble Verschwendung von RAM, aber falls du den eh übrig hast, 
wäre das ne Möglichkeit.

von Ottmar (Gast)


Lesenswert?

Einfach ein multiport RAM bilden.

Im Grunde sind das parallele RAM's die eingangsseitig parallel hängen. 
Es wird also in jedes RAM die gleiche Information geschrieben.
Für deinen Fall bräuchtest du dann 8 BRAM's.

von Mr.EMail (Gast)


Lesenswert?

Welche Informationen fehlen Dir denn? Der konkrete Anwendungsfall?

Roger Steiner schrieb:
> Erste Naeherung: nutz die achtfache Anzahl BRAM.

Du meinst also es wäre eleganter viele (=(6144*2)/8=1536) einzelne 8 Bit 
große BRAMs zu nutzen? (Hab ich das soweit richtig verstanden?).

Duke Scarring schrieb:
> Aber wie der Name FIFO schon sagt: first in - first out
> Ein gleichzeitiges Lesen an unterschiedlichen Stellen ist damit nicht
> möglich.

Dies erfordert leider der Anwendungsfall, sonst wäre ein FIFO die wohl 
beste Lösung.

Schlumpf schrieb:
> Kann man schon mit BRAM machen, wenn man den BRAM mit der minimal
> möglichen Adressbreite und der daraus resultierenden maximalen
> Datenbreite konfiguriert und dann so viele parallel schaltet, bis deine
> gewünschte Datenbreite erreicht ist.
> Und dann benutzt man nur die Adresse 0.
>
> Ist zwar ne üble Verschwendung von RAM, aber falls du den eh übrig hast,
> wäre das ne Möglichkeit.

Testweise könnte ich das mal versuchen. Im FPGA selbst brauche ich für 
den Rest nur sehr wenig Speicher da ich die Nutzdaten ohnehin in ein 
DDR2 Speicher schreibe (die passen gar nicht in das FPGA interne RAM).

von VHDL hotline (Gast)


Lesenswert?

Informationen, die nützlich sein könnten:

- Werden immer die gleichen Bytes im 6144-Bit-Vektor gelesen oder an 
beliebigen Stellen? Wie ist das Schema genau?

- Schreiben mit 65 MHz, Lesen mit 30MHz: Werden die 8 Byte also immer 
nach ca. 48 geschriebenen Bits gelesen? Wie wird das synchronisiert?

von Roger S. (edge)


Lesenswert?

Mr.EMail schrieb:
> Welche Informationen fehlen Dir denn? Der konkrete Anwendungsfall?

Die Systembeschreibung.
Deine Frage stuetzt sich auf eine moegliche Implementierung.
Waeren die umliegenden Komponenten und der Zweck bekannt,
dann koennte ein besserer Loesungsansatz gefunden werden.

> Du meinst also es wäre eleganter viele (=(6144*2)/8=1536) einzelne 8 Bit
> große BRAMs zu nutzen? (Hab ich das soweit richtig verstanden?).

Ein BRAM im S3 ist IMHO 18KBit gross, also wird es weitaus weniger 
werden.

Je nachdem wie variabel sind die Acht Leseaddressen sind,
ist mit einer BRAM Loesung der Datenpfad weitaus eleganter
als der Multiplexer den man sich um die Flipflop Variante baut.
Letzteres ist eine Spezialitaet Xilinx benutzender FPGA Greenhorns.

Kommt halt auch draufan ob du mehr Logik oder BRAMs zum verheizen zur 
verfuegung hast.

Cheers, Roger

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


Lesenswert?

Mr.EMail schrieb:
> Du meinst also es wäre eleganter viele (=(6144*2)/8=1536) einzelne 8 Bit
> große BRAMs zu nutzen? (Hab ich das soweit richtig verstanden?).
Was ist eigentlich das grundlegende Problem? Welche Aufgabe willst du 
mit diesem Monstervektor lösen? Warum verwendest du nicht ein "normales" 
RAM, auf das dann in z.B. 32-Bit Breite zugegriffen wird? So, wie es der 
Rest der Welt eben auch macht...

: Bearbeitet durch Moderator
von Mr.EMail (Gast)


Lesenswert?

Hallo und erstmal vielen Dank für die vielen Antworten.

Jetzt muss ich zuersteinmal ein wenig aushohlen - ich benutze das 
Spartan 3AN Starterkit:

Der FPGA bekommt über eine LVDS Schnittstelle ein Videosignal mit 
1024x768 Pixel bei 60Hz Bildwiederholfrequenz und 24Bit Farbtiefe 
(3x8Bit). Daraus resultiert der Pixeltakt von 65MHz.

Die Deserialisation der Daten usw. funktioniert bereits. Das Bild wird 
fehlerfrei über die VGA Schnittstelle wieder ausgegeben.

Gesteuert werden soll mit dem FPGA ein 256x192 Pixel großer LED Screen 
(ca. 3 mal 4m groß, Pixelabstand 16mm). Diesen Bildschirm habe ich so 
gebraucht aufgekauft, Teile der ursprünglichen Steuerung sind dabei, 
aber eben unvollständig - fehlende Teile sollen vom FPGA ersetzt werden.

Der LED Screen ist also 1/4 so groß wie die Quellauflösung des Eingangs 
- es ist ausreichend wenn z.B. genau das obere rechte Viertel des 
Bildschirms auf die LEDs übertragen werden - also keine Skalierung oder 
ähnliches.

Der von mir erfragte bzw. gesuchte Speicher soll folgende Funktion 
erfüllen:

Das Eingangssignal muss zwischengespeichert werden, die Daten kommen 
rein mit 24Bit breite (je 8 Bit RGB) Pixel für Pixel diese werden in 
Bit_Vektor 1 geschrieben. Ich muss das gesammte Bild für die LEDs einmal 
zwischenspeichern in den DDR Ram und einmal gleichzeitig schon an den 
Screen senden (aus Bit Vektor 2 wird gelesen). Dann wird Bit_Vektor 1 
und 2 getauscht und so weiter - also schon eine Art FiFo.

Der LED Screen braucht - um ein vollständiges Frame 2 mal zu empfangen 
und dazustellen - genau so lange wie ein Bild in 1024x768 von der Quelle 
braucht (Für die Experten: Scanmode 1/2 - es ist immer nur abwechselnd 
jede zweite Zeile aktiv, daher 2 mal).

Also muss das Bild in den Bit Vektor um von dort in den DDR Speicher 
geschrieben zu werden (Zugriff 1 auf den Bit Vektor, Wort 64 Bit breit).

Der LED Screen braucht die Daten aber in einer anderen Reihenfolge:

Das Display ist 4 Vertikale Teile geteilt, die alle gleichzeitig Daten 
wollen und zwar so: vollständige Zeile Rot, dann alle Blauen und dann 
alle grünen Pixel, daher der gleichzeitige Zugriff auf die gesammte 
Breite des Speichers. (Zugriff 2 auf den Vektor auf 4 verschiedene 
Stellen, jeweils 8 Bit breit).

Ich habe bei der Beschreibung bewusst z.B. den Scanmode weggelassen, da 
das dann zu kompliziert in der Beschreibung werden würde - nur grob: in 
der zweiten Bildhälfte sollen die Daten vom DDR wieder in den Bit Vektor 
geschrieben werden und von da wieder an den Screen.

Ich hoffe damit auch erstmal alle Fragen zum Thema synchronisierung 
beantwortet zu haben.

von eingast (Gast)


Lesenswert?

Dann mach für jede Farbe einen Speicher. Die Spartan 3 blockrams können 
dual port, einen zum reinschreiben den anderen zum rauslesen.

von Achim S. (Gast)


Lesenswert?

Mr.EMail schrieb:
> Roger Steiner schrieb:
>> Erste Naeherung: nutz die achtfache Anzahl BRAM.
>
> Du meinst also es wäre eleganter viele (=(6144*2)/8=1536) einzelne 8 Bit
> große BRAMs zu nutzen? (Hab ich das soweit richtig verstanden?).

Nein, Roger meinte wahrscheinlich genau das, was er geschrieben hat. 
Wenn du gleichzeitig von 8 verschiedenen Stellen deines Speichers lesen 
musst, dann nutze 8 verschiedene Speicher, die du alle gleich 
beschreibst. Auf der anderen Seite des dual ported RAMs kannst du dann 8 
unterschiedliche Adressen gleichzeitig lesen. Das "Umsortieren" der 
Daten nach RGB kannst du die FSM erledigen lassen, die die Adressen für 
den Lesezugriff generiert.

Wenn dein Speicher knapp werden sollte (was ich nicht glaube), dann 
kannst du auch noch den Takt für den Leseport verdoppeln (auf 60MHz) 
oder vervierfachen (auf 120MHz). in einem Pixeltakt die Daten von zwei 
oder vier verschiedenen Adressen eines BRAMs auslesen - spart wieder 
viele RAM-Blöcke.

von Mr.EMail (Gast)


Lesenswert?

Hallo,

vielen Dank nochmal für die konstruktiven Hinweise.

Nachdem ich noch einen Fehler in meinem Timingdiagrammen gefunden habe, 
hat sich die Sache mit dem DDR-Speicher vorerst erledigt. Das Problem 
ist das ich keinerlei technische Unterlagen zu dem Screen habe und die 
Ansteuerung praktisch durch Reverse-Engineering und Try and Error 
herausfinden muss(te).

Wenigstens was gelernt beim DDR Controller steuern ;)

Habe nochmal die Manuals zum BRAM etc. studiert und folgende Lösung ist 
jetzt angedacht:

Ich nutze 4 BRAMS (die sind im S3AN jeweils 18kBit groß, es passen also 
2 Zeilen rein). Der Port A wird, wie von Ottmar beschrieben, bei allen 4 
parallel geschaltet. Der Port A wird 36Bit breit sein, von denen aber 
nur 24Bit effektiv genutzt werden. Der Rest bleibt eben leer (passt 
trotzdem noch in das RAM).

Rein theoretich Teile ich jedes BRAM in 2 Hälften, indem ich eine 
Adressleitung nur Zeile für Zeile umschalte (am Leseport dann 
invertiert). Somit ist auch ausgeschlossen, dass gleichzeitig in eine 
Zelle geschrieben und gelesen wird.

Der Port B der 4 BRAMS wird getrennt angesteuert um die 4 Einheiten des 
Displays getrennt mit Daten zu versorgen. Der Port B der BRAMs ist dann 
9 Bit breit (1 Bit überflüssig).

Nicht gerade effizient was die RAM Nutzung angeht, aber "einfach".

Wenn wieder Zeit ist, werde ich mich an die praktische Umsetzung machen.

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.