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