Forum: FPGA, VHDL & Co. Mehrere Frame Buffer nutzen


von Marc85 (Gast)


Lesenswert?

Board: Altera Cyclone III Development Board

Hallo zusammen,

ich versuche gerade im Altera SOPC Builder, mehrere Clipper- Scaler- 
Kombinationen umzusetzen. Also ungefähr so:

... Clipper1 -> FrameBuffer1 -> Scaler1 ...
... Clipper2 -> FrameBuffer2 -> Scaler2 ...
... Clipper3 -> FrameBuffer3 -> Scaler3 ...

Dabei tritt das Problem auf, dass ich mehr als zwei FrameBuffer benötige 
und somit auch auf mehr als zwei SDRAM Controller zurückgreifen müsste. 
Das Board hat jedoch nur zwei RAM.
Kennt hier jemand eine andere Möglichkeit, trotzdem mehrere FrameBuffer 
zu benutzen?

Vielen Dank

Marc

von Klaus (Gast)


Lesenswert?

Dann musst du dir wohl einen Wrapper um den RAM-Controller schreiben, 
der die verfügbare Bandbreite auf mehrere Ausgangsports verteilt, und 
jedem Port einen separaten Adressbereich zur Verfügung stellt.

von Kest (Gast)


Lesenswert?

Die Framebuffer kannst Du alle an einen SDRAM Controller hängen. 
Verstehe gerade nicht das Problem. Da musst Du keinen Wrapper schreiben, 
sondern einfach unterschiedliche Adressen angeben, an die im Speicher 
geschrieben werden soll

Kest

von P. K. (pek)


Lesenswert?

Kest schrieb:
> Die Framebuffer kannst Du alle an einen SDRAM Controller hängen.
> Verstehe gerade nicht das Problem. Da musst Du keinen Wrapper schreiben,
> sondern einfach unterschiedliche Adressen angeben, an die im Speicher
> geschrieben werden soll

Natürlich verringert sich die Bandbreite pro Zugreifer (d.h. Du musst 
nicht nur den Adressraum aufteilen, sondern auch das Zeitmultiplex für 
die Zugriffe meistern).

von Klaus (Gast)


Lesenswert?

Kest schrieb:
> Die Framebuffer kannst Du alle an einen SDRAM Controller hängen.
> Verstehe gerade nicht das Problem. Da musst Du keinen Wrapper schreiben,
> sondern einfach unterschiedliche Adressen angeben, an die im Speicher
> geschrieben werden soll

Ok, wenn das doch geht, ziehe ich meinen Vorschlag zurück ;-) Das war 
als Lösung gedacht, wenn man tatsächlich nur einen RAM Controller mit 
einem lokalen Port hat, und mehrere Module anschließen möchte.

von Marc85 (Gast)


Lesenswert?

Danke für die schnellen Antworten.

Ich habe bei den beiden Controllern jeweils eine "Base" von 0x00000000 
und ein "End" von 0x07ffffff. Das wären 134.217.727bit, also 16,7MB.
Wenn ich euch richtig verstanden habe, kann ich bei den Frame Buffern, 
also einfach die 0x07ffffff durch meine Anzahl an Frame Buffern teilen 
und die entsprechenden Startbereiche bei "Base address of frame buffers" 
eintragen.

Das werde ich gleich mal ausprobieren. Vielen Dank

von Marc85 (Gast)


Lesenswert?

Kest schrieb:
> Die Framebuffer kannst Du alle an einen SDRAM Controller hängen.
> Verstehe gerade nicht das Problem. Da musst Du keinen Wrapper schreiben,
> sondern einfach unterschiedliche Adressen angeben, an die im Speicher
> geschrieben werden soll

Das ist leider fehlgeschlagen. Ich habe erstmal nur zwei Frame Buffer an 
einen Controller gehangen. Dazu habe ich bei dem ersten den Startbereich 
ab 0x00000000 angegeben und beim zweiten den Bereich ab 0x03ffffff. Dann 
sollten beide Buffer einen Speicher von gut 8MB zur Verfügung haben, 
obwohl sie nur gut 2MB brauchen. Leider funktioniert das wie gesagt 
nicht.

Gruß

von Kest (Gast)


Lesenswert?

Was heißt "funktioniert nicht"?
Im Framebuffer kannst Du Unmengen an Parametern einstellen -- 
single/tripple buffer, Burst-Länge, Bit-Breite und so weiter... Es 
funktioniert erst wenn alles "richtig" ist.

Fang mal "klein" an mit einem Testpatterngenerator und einem Ausgang... 
Funktioniert? Dann klinkst Du Framebuffer dazwischen? Funktioniert? Dann 
nimmst Du Scaler dazu... funktioniert? Dann nimmst Du einen Input dazu 
statt Testpattern-Generator...
Gleichzeitig spielst Du halt mit Einstellungen, Buffer-Längen, 
FIFO-Größen und so weiter.

Kest

von Marc85 (Gast)


Lesenswert?

Kest schrieb:
> Fang mal "klein" an mit einem Testpatterngenerator und einem Ausgang...
> Funktioniert? Dann klinkst Du Framebuffer dazwischen? Funktioniert? Dann
> nimmst Du Scaler dazu... funktioniert? Dann nimmst Du einen Input dazu
> statt Testpattern-Generator...
> Gleichzeitig spielst Du halt mit Einstellungen, Buffer-Längen,
> FIFO-Größen und so weiter.

Die schrittweisen Aufbauten funktionieren soweit alle. Auch mit Frame 
Buffer. Das Problem liegt wie gesagt nur in der Nutzung mehrerer Frame 
Buffer mit einem Controller. Was mir noch aufgefallen ist, ist eine 
Warnung beim Framebuffer: "Warning: Base address is not aligned to burst 
boundary.".
Das hört sich garnicht so gut an. Die Warnung tritt auf, sobald ich die 
"Base address of frame buffers:" ändere. Welchen Wert ich eintrage ist 
egal. Alle ausser 0x00000000 erzeugen diese Warnung.

Gruß

von Kest (Gast)


Lesenswert?

Marc85 schrieb:
> Das hört sich garnicht so gut an. Die Warnung tritt auf, sobald ich die
> "Base address of frame buffers:" ändere. Welchen Wert ich eintrage ist
> egal. Alle ausser 0x00000000 erzeugen diese Warnung.

Schaue mal im Framebuffer, wie lang Deine Bursts sind. Ein Vielfaches 
von diesem Wert sollst Du im Framebuffer auch eintragen -- das 
funktioniert bestimmt ;-)


Kest

von Marc85 (Gast)


Lesenswert?

Kest schrieb:
> Schaue mal im Framebuffer, wie lang Deine Bursts sind. Ein Vielfaches
> von diesem Wert sollst Du im Framebuffer auch eintragen -- das
> funktioniert bestimmt ;-)

Hi,
ich habe eine Lösung gefunden.
Man benötigt das Multi-port Front-end von Altera. Dieses muss jedoch 
extra heruntergeladen werden. Falls es noch irgendjemanden interessiert:
http://www.altera.com/literature/an/an637.pdf
Wenn man das benutzt und dazu noch deine Anweisung befolgt (also die 
Adressbereiche für die Framebuffer aufteilt), funktioniert alles.

Danke nochmal an alle

von Kest (Gast)


Lesenswert?

Ich denke, Du brauchst eigentlich keinen extra Multiport-Frontend. Es 
gibt die sogenannten "Arbitration Shares" (rechte Maustaste im QSYS). da 
kannst Du für jede Verbindung die Priorität einstellen. Damit habe ich 
immer meine Master/Framebuffer realisiert.

Kest

von Marc85 (Gast)


Lesenswert?

Kest schrieb:
> Ich denke, Du brauchst eigentlich keinen extra Multiport-Frontend. Es
> gibt die sogenannten "Arbitration Shares" (rechte Maustaste im QSYS). da
> kannst Du für jede Verbindung die Priorität einstellen. Damit habe ich
> immer meine Master/Framebuffer realisiert.

Hi,
nächstes Problem...
Mit dem Multiport Frontend (MPFE) funktioniert es flüssig für bis zu 
sechs Frame Buffer. Ohne Multiport Frontend leider nach wie vor 
garnicht.
Die Adressen habe ich eingetragen wie du vorgeschlagen hast
64*64= 4096
2298kbyte/4096byte=561
Also nehme ich als Multiplikator 600.
4096byte*600=4096000byte
Dez      Hex
0        0
4096000  3E8000
8192000  7D0000
12288000 BB8000
16384000 FA0000
20480000 1388000
24576000 1770000
28672000 1B58000
Das Problem bei meinem MPFE ist, das Slave 0-5 mit 64bit für Master und 
Slave Port konfigurierbar sind, Port 6 und 7 aber fest auf 32bit 
eingestellt sind. Somit kann ich diese Ports nicht nutzen. Wenn ich sie 
einfach frei lassen will, gibt es errors.
Dann habe ich noch probiert 2 MPFE's zu nutzen und diese auf den zweiten 
Teil des dual-channel DDR2's zu legen. Diese scheinen sich aber 
ebenfalls negativ zu beeinflussen, egal ob ich die Adressen fortlaufend 
vergebe, oder für den zweiten DDR2 wieder bei 0x0 anfange.
Ich würds natürlich gerne ganz ohne MPFE machen. Aber dann bekomme ich 
wie gesagt nur einen Frame Buffer ans laufen, bzw. zwei FB auf zwei 
verschiedenen DDR2's.

Vielen Dank für eure Hilfe

Marc

von Kest (Gast)


Lesenswert?

ich habe jetzt nicht ganz verstanden, was Du meinst bzw. habe ich die 
Frage nicht gesehen ;-)
Unklar, was die Zahlen bedeuten: 64x64 Bit?Byte? Burstlänge? 
Burstbitbreite? ...Sorry, ohne Kontext kann ich nicht viel helfen, auch 
nicht, weil ich mit dem MPFE noch nichts gemacht habe. Aber es soll Dir 
klar werden, dass es theoretisch auch ohne gehen muss! Denn die 
Bandbreite des DDR2 scheint ja auszureichen.
Wenn Du 2 DDR2 Controller hast, kannst Du nicht einfach je 3 FB 
dranhängen? Die dürfen sich aber nicht überschneiden und jeweils eigenen 
AVALON-Bus haben...
Dein Multiplikator von 600 verstehe ich auch nicht ganz. Wenn man schon 
mit den Bursts arbeitet, dann sollte man auch Zweierpotenz nehmen, also 
eher 1024. Darauf hin muss Du dann alles optimieren.

Ist schwer zu sagen, was da passiert

kest

von Marc85 (Gast)


Lesenswert?

Kest schrieb:
> ich habe jetzt nicht ganz verstanden, was Du meinst bzw. habe ich die
> Frage nicht gesehen ;-)
> Unklar, was die Zahlen bedeuten: 64x64 Bit?Byte? Burstlänge?
> Burstbitbreite? ...Sorry, ohne Kontext kann ich nicht viel helfen, auch
> nicht, weil ich mit dem MPFE noch nichts gemacht habe.

Hi,
ja das soll tatsächlich die Burstlänge sein. Dazu habe ich das burst 
target von 64 words genommen und mit der Portweite von 64byte 
Multipliziert.

Kest schrieb:
> Aber es soll Dir
> klar werden, dass es theoretisch auch ohne gehen muss! Denn die
> Bandbreite des DDR2 scheint ja auszureichen.
> Wenn Du 2 DDR2 Controller hast, kannst Du nicht einfach je 3 FB
> dranhängen? Die dürfen sich aber nicht überschneiden und jeweils eigenen
> AVALON-Bus haben...

Am liebsten möchte ich es ja auch ohne MPFE machen ;)
Bisher hat es nur leider noch nicht einmal mit zwei FB an einem 
Controller funktioniert. Bzw. wenn ich Glück hatte, habe ich ein 
instabiles Bild bekommen, welches am zittern war und "zufallsmäßig" 
Pixel von dem anderen Bild enthielt.

Kest schrieb:
> Dein Multiplikator von 600 verstehe ich auch nicht ganz. Wenn man schon
> mit den Bursts arbeitet, dann sollte man auch Zweierpotenz nehmen, also
> eher 1024. Darauf hin muss Du dann alles optimieren.

Ok, das werde ich machen

Danke dir!

von Duke Scarring (Gast)


Lesenswert?

Marc85 schrieb:
> Bisher hat es nur leider noch nicht einmal mit zwei FB an einem
> Controller funktioniert. Bzw. wenn ich Glück hatte, habe ich ein
> instabiles Bild bekommen, welches am zittern war und "zufallsmäßig"
> Pixel von dem anderen Bild enthielt.
Hast Du denn den ganzen Kram mal simuliert? Auch wenn das in Deinem Fall 
etwas komplexer ist, sieht man so die Probleme i.a. wesentlich besser 
als auf der Hardware.

Duke

von Kest (Gast)


Lesenswert?

"Long shot": mach mal ein Screenshot von Deinem QSYS Aufbau. Ich wette, 
es funktioniert ohne MPFE nicht, weil die Clocks nicht stimmen (habe 
schon öfters gesehen). Ein Screenshot vom DDR2 Controller wäre auch 
nicht schlecht und auch ein Scressnshot vom FrameBuffer
Kest

von Marc85 (Gast)


Angehängte Dateien:

Lesenswert?

Duke Scarring schrieb:
> Hast Du denn den ganzen Kram mal simuliert? Auch wenn das in Deinem Fall
> etwas komplexer ist, sieht man so die Probleme i.a. wesentlich besser
> als auf der Hardware.
>
> Duke

Hi,
ich versuch mal die Simulation ans laufen zu bekommen, war nur 
eigentlich für einen späteren Zeitpunkt geplant.


> "Long shot": mach mal ein Screenshot von Deinem QSYS Aufbau. Ich wette,
> es funktioniert ohne MPFE nicht, weil die Clocks nicht stimmen (habe
> schon öfters gesehen). Ein Screenshot vom DDR2 Controller wäre auch
> nicht schlecht und auch ein Scressnshot vom FrameBuffer
> Kest

Hab ich gemacht.
In dem Ohne_MPFE.png sind alle Settings wie in MPFE.png. Lediglich das 
MPFE wird wie gezeigt übersprungen und die FB gehen direkt auf den DDR2 
Controller.
Die Settings vom DDR2 Controller wurden vom "DVI 1080P Loop-through" 
Tutorial von Bitec übernommen (http://www.bitec.ltd.uk/hsmc_dvi.html)

Danke!

von Kest (Gast)


Lesenswert?

Mehrere Sachen fallen mir auf:

- zunächst mal würde ich DDR2 Controller auf Half-Rate stellen, damit 
hast Du statt 64 Bit Bursts 128 Bit. Die Timings sind dann entspannter. 
Außerdem habe ich die Erfahrung gemacht, dass DDR2 Controller (sowohl 
legacy, als auch der Neue) nicht richtig mit dem Framebuffer arbeitet 
(Die Zugriffe sind dann jeden 2. Takt). Ob das ein Bug im Framebuffer 
ist oder im Controller, weiß ich nicht. Altera support meinte nur, ich 
möge doch half-rate verwenden, später wird es gefixt werden.
Lustigerweise, hat es mit Quartus 9.0 wunderbar funktioniert.

- Die Bursts von 1024 (im Framebuffer) sind viel zu lang! In der Zeit 
"verhungern" andere Framebuffer, weil im SOPC ein sequenzeeller Zugriff 
nicht länger als 100 sein kann (Arbitrieringsshares). Stell sie mal auf 
32-64 (je nach dem wieviel Speicher Du hast)

- Ganz wichtig ist die Reihenfolge Scaler<->Framebuffer! Ob Up-Scaler 
oder Down-Scaler -- es macht einen Riesenunterschied. Die 
Clock-Input/Output-Buffer müssen entsprechend ausgelegt sein. Es hilft 
mit einem Blatt Papier und Bleistift die Bandbreite auszurechnen, bevor 
man da was anfängt. Da siehst Du sofort wo Bottlenecks sind.

- Allgemein: Die FB-Fifos (Input und Output) sollten in etwa gleich der 
Arbitrierungsshares sein (direkt am DDR2). Die Summe aller 
Arbitrierungsshares sollte etwa die FIFO-Größe der Input/Outputs sein.

Noch mal zusammengefasst: Inputbandbreite ausrechnen (maximale Auflösung 
x fps) + Outputbandbreite (scaler berücksichtigen) sollte kleiner sein, 
als 64 Bit * 166 MHz

Kest

von Kest (Gast)


Lesenswert?

Habe mir gerade Bittec-Design angeschaut -- schrecklich! Ich glaube, sie 
haben so lange irgendwelche Zahlen geändert, bis es zufälligerweise 
funktioniert hat, anders kann ich es mir nicht erklären. Alleine 13 
Zeilen Zwischenbuffer im Ausgangs-Pfand spricht Bände! 1920x13x24Bit = 
73 kByte an m9k Blöcken! Wahnsinn! Soetwas sollte verboten werden.

Und wieso man die Daten über 2 Framebuffer durchschiebt ist mir auch ein 
Rätsel (um einfach zu zeigen, dass das funktioniert?)... Vergiss 
schnell, was Du da gesehen hast! :-)

Kest

von Kest (Gast)


Lesenswert?

sorry für diverse orthografische und Syntaxfehler... war wohl zu 
aufgeregt ;-)

von Marc85 (Gast)


Lesenswert?

Puh, das ist mal ausführlich!

Kest schrieb:
> Noch mal zusammengefasst: Inputbandbreite ausrechnen (maximale Auflösung
> x fps) + Outputbandbreite (scaler berücksichtigen) sollte kleiner sein,
> als 64 Bit * 166 MHz

Ok, das habe ich ausgerechnet:
Der Scaler ist ein Up- Scaler

560*24*350*60/s=    282240000bit
1680*24*1050*60/s= 2540160000bit

2.822.400.000 = 2,822Gbit/s

64bit*166.000.000Hz= 10,624Gbit/s

Die 24 ist noch dabei da ich die Farben parallel übertrage.
Passt aber offensichtlich trotzdem dicke.

Was ich noch nicht ganz verstehe ist, was die Bursts von 1024 bzw 64 
oder 32, mit der größe des Speichers zu tun haben. Ich habe die 
Einstellungen jetzt wie folgt geändert:
Portweite: 64
Write FIFO tiefe: 64
Write burst target: 32
Read FIFO tiefe: 64
Read burst target: 32

Die Arbitrierungsshares habe ich auf jeweils 10 gestellt, so dass 
6*10=60 ergibt, also fast 64.
Der Controller steht jetzt auf Half- Rate.

Leider habe ich immer noch ein schwarzes Bild.
Was mir aber aufgefallen ist, ist das ich durch die Einstellung "Half- 
Rate", ja nur noch eine DDR2.sysclock von 83MHz habe. Damit laufen bei 
mir ja alle Clipper, Scaler usw. Das Videosignal kommt aber mit 119MHz 
rein.
Werde nochmal versuchen alles ausser die DDR2 Controller auf CLK 
(125MHz) zu setzen.


Vielen Dank nochmal für die ausführliche Hilfe!

von Kest (Gast)


Lesenswert?

Marc85 schrieb:
> Was ich noch nicht ganz verstehe ist, was die Bursts von 1024 bzw 64
> oder 32, mit der größe des Speichers zu tun haben. Ich habe die

Ein Burst von 1024 erzeugt im FPGA ein Fifo mit 1024 * 64 Bit (aus M9K 
Blöcken)... Das hat mit der Größe des Speichers (DDR2) überhaupt nichts 
zu tun, aber mit den M9K Blöcken -- die hat man nicht unendlich ;-))

Marc85 schrieb:
> Die Arbitrierungsshares habe ich auf jeweils 10 gestellt, so dass
> 6*10=60 ergibt, also fast 64.

genau

Marc85 schrieb:
> Leider habe ich immer noch ein schwarzes Bild.

das kann mehrere Gründe haben. Da ist es wichtig festzustellen, was 
blockiert. Wenn Du Control-Ports hast, dann kannst Du mit NIOS 
Statusregister auslesen und (viel wichtiger) die Reihenfolge des 
"Anstartens" festlegen. Die ganze Video-Pipeline kann nämlich 
blockieren, sodaß es nur ein Reset hilft (danke Altera).
Über so einen Control-Port kannst Du dann Komponenten gezielt anhalten 
und wieder starten, wenn es z.B. zum Überlauf gekommen ist.

Marc85 schrieb:
> Was mir aber aufgefallen ist, ist das ich durch die Einstellung "Half-
> Rate", ja nur noch eine DDR2.sysclock von 83MHz habe. Damit laufen bei

ja, das ist immer so, dass die Taktrate halbiert wird. Du könntest alle 
Komponenten mit full-rate betreiben (ddr2_32bit_bot_auxfull), 
Framebuffer aber mit ddr2_32bit_bot_auxhalf, sodaß nur Dein Speicher und 
AVALON-Master (Frambuffer) mit der Hälfte rennen.

Du siehst, das Ganze ist nicht ohne.

Ich kann Dir nur empfehlen mit SignalTap zu arbeiten

von Marc85 (Gast)


Lesenswert?

Hi,
also nach langem hin und her, und der beachtung deiner Einstellungen, 
laufen immer noch nur maximal 5 FrameBuffer pro Speicher. Eine Änderung 
habe ich jedoch noch vorgenommen, die FIFO Tiefe sollte laut Alteraforum 
bei M9K auf 512 gesetzt werden 
(http://www.alteraforum.com/forum/showthread.php?t=5794). Andere Tiefen 
habe ich auch probiert. Es scheint wirklich dran zu liegen das bei noch 
mehr FrameBuffern, der Stream "verhungert".
Jetzt bleibt mir wohl nichts anderes übrig, als die restlichen Buffer 
auf den zweiten Ram Controller zu legen.
Wenn ich das mache, bleibt das Bild des zweiten Controllers jedoch 
schwarz, das des ersten Controllers funktioniert nach wie vor gut.
Bildlich:

RAM1(bottom):   x/2 Framebuffer läuft einwandfrei
RAM2 (top):     x/2 Framebuffer ergeben schwarzes Bild

Ich habe beide in zwei unterschiedlichen SOPC Files verarbeitet und 
beide nutzen den TestPattern- Generator. Sie sind auch beide gleich 
eingestellt. Muss ich da noch irgendwas mit den clocks beachten?

Danke und Gruß

von Marc85 (Gast)


Lesenswert?

So,
in lauter Verzweiflung bin ich alle 730 Zeilen im Assignment Editor 
durchgegangen und siehe da, memtop_cke war nicht eingetragen, danke 
BITEC =)

Alles läuft und das Thema hat sich erledigt.

von Kest (Gast)


Lesenswert?

Ha-Ha

Nach Jahren im FPGA-"Geschäft" weiß ich nun zu genau, dass man sich nie 
und nimmer auf die andere verlassen sollte. Den Speicher (Memorytest) 
hätte ich als erstes gemacht. Dabei ist interessant zu erfahren, wie die 
Kalibrierung erfolgreich funktioniert hat :-o
Schön, dass Du jetzt weiterkommst! :-)

Kest

von Marc85 (Gast)


Lesenswert?

Kest schrieb:
> Dabei ist interessant zu erfahren, wie die
> Kalibrierung erfolgreich funktioniert hat :-o

Hi,
also:
CVI => Clipper => FB => Scaler => CVO

Und vom FB aus:
FB => Pipeline Bridge => Memory
(Die Pipe wurde von Altera in einem Schulungsvideo eingesetzt, jeweils 
ein Read und Write Master auf eine Pipe, geht jedoch auch ohne)

Separate Clock im FB aktiviert.
FIFO Tiefe 256 (von Altera empfohlen da wohl kein kleinerer M9K 
existiert, 128 tuts auch).
Burst Target 32.
In den Memorys habe ich Half Rate aktiviert.

Achja, wegen den M9K Blöcken, ich hab es mal versucht zu übertreiben, 
der Compiler haut dann jedoch einen Error raus. Also ist man in der 
Hinsicht ein wenig "abgesichert".

Gruß

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.