Forum: FPGA, VHDL & Co. 90° Video-Rotation


von Joachim S. (electribe)


Lesenswert?

Hallo Zusammen!

Ich komme gerade gedanklich nicht weiter und wollte mal eure Meinung 
hören: in einem Projekt muss ich auf einem Zynq US+ ein AXI4-Stream 
Video-Signal um 90° drehen. Wünschenswert mit so "hoher Auflösung wie 
möglich (4k)", aber mit 1024x768 bin ich schon zufrieden. Das Video 
kommt mit 25FPS und 2PPC rein.
Auf der bisherigen Hardware habe ich externen DDR4 RAM zur Verfügung, 
der für nichts anderes benötigt wird. Ich habe im BRAM einen 
Double-Buffer angelegt, in dem jeweils eine Zeile abgelegt wird, während 
die andere als 256 Burst AXI4 an einen MIG-Core des RAMs geschickt wird, 
wo alternierend je ein komplettes Frame abgelegt wird. Dann kommt der 
eklige Teil: ich muss random access jedes Pixel einzeln spaltenweise 
auslesen, setze sie wieder als 2PPC zusammen und schicke sie dann direkt 
weiter an einen Framebuffer-Write (DMA) zur weiterverarbeitung vom 
Prozessor. Dabei verschwende ich Bandbreite, weil der Bus zum RAM 64 Bit 
breit ist, ich aber nur 48 Bit davon verwende (2xRGB888). Die 
Zugriffszeiten beim lesen sind erwartbar extrem langsam - bis ich das 
nächste 24Bit Wort auslesen kann, vergehen etwa 14 Takte. Ich glaube ich 
könnte das ganze noch etwas optimieren, in dem ich genau schaue, welcher 
RAM gerade addressiert wird um wenigstens immer ein Spalte offen zu 
halten - im Prinzip läuft das ganze aber wie gewünscht.
Der Haken an der Sache ist, dass ich jetzt neue Hardware bekomme, auf 
der kein externer RAM mehr zur Verfügung steht. Für BRAM sind die Frames 
zu groß und der Versuch, einfach statt des externen RAMs per DMA in den 
PS RAM des Prozessors zu schreiben ist kläglich gescheitert, weil der 
RAM durch die pausenlosen Lesezugriffe so blockiert wird, dass des ganze 
System (Linux) ohne Kernel-Panic zum erliegen kommt.

Habe ich irgendwo einen Denkfehler bei meiner Umsetzung? Geht die ganze 
Geschichte, ohne externen RAM, einfach nicht? Ich komme immer wieder zu 
dem Punkt, an dem ich glaube, nicht um die ganzen langsamen random 
access Lesezugriffe drum rum zu kommen. Habt ihr vielleicht noch eine 
Idee?

Viele Grüße

Achim

von Gustl B. (gustl_b)


Lesenswert?

Jap, zum drehen musst du sehr viel speichern. Denn du bekommst ja Zeilen 
und gibst Spalten aus. Und das erste Pixel der letzten Spalte die du 
ausgeben wirst, das bekommst du schon mit der ersten Zeile rein. Du 
musst also fast ein Vollbild speichern.

von Joachim S. (electribe)


Lesenswert?

Hallo Gustl,

ja - damit, dass ich grundsätzlich eine Art von Framebuffer brauche, 
habe ich mich abgefunden. Die Frage die eher beschäftig ist, ob es 
möglich ist, die Rotation über DMA im PS-RAM durchzuführen, oder ob 
durch die permanenten Lesezugriffe an der Stelle chancenlos bin?

Viele Grüße
Achim

von Gustl B. (gustl_b)


Lesenswert?

Verstehe. Du hast also zwei Speicher(bereiche) einmal das Bild das 
reinkommt, das wird da zeilenweise hingelegt. Und dann das Bild das 
rausgeht. Und auch das soll wieder so drinnenliegen, dass es zeilenweise 
gelesen werden kann.

Jetzt kannst du von Einfangsbild nacheinander von jeder Zeile ein Pixel 
lesen und das zu einer Zeile im Ausgangsbild zusammensetzen.

Oder du liest eine Zeile im Eingangsbild und schreibst dann von jeder 
Zeile im Ausgangsbild ein Pixel.

Beides nicht toll. Vielleicht hilft es das Bild aufzuteilen. Z. B. in 
Quadrate mit 128*128 Pixeln. Dann liest du 128 mal 128 Pixel und 
schreibst auch 128 mal 128 Pixel. Jedes Mal ein Burst. Das Drehen machst 
du dann im BlockRAM weil da Zufallszugriffe nichts extra kosten.

von Joachim S. (electribe)


Lesenswert?

Scheiße. Ich war gerade dabei dir zu schreibenn, warum das nicht geht, 
um beim schreiben zu bemerken, dass mir diese vollkommen offensichtliche 
Möglichkeit nicht aufgefallen ist.
Fassungslos sage ich vielen Dank!

von T.U.Darmstadt (Gast)


Lesenswert?

Gustl B. schrieb:
> Vielleicht hilft es das Bild aufzuteilen. Z. B. in
Das kann kaum was bringen, weil er links oben anfang muss, was im 
Orginal sowohl links unten (lesen nach oben), als auch rechts oben 
(lesen nach unten) sein kann. Blockweises Drehen hilft dem nicht ab, nur 
richtiges Reinschreiben an die Speicherstellen und zwar parallel mit 
mehreren Pfaden und FIFOs. Für solche Sachen gibt es aber auch fertige 
Chips.

von Gustl B. (-gb-)


Lesenswert?

Thomas U. schrieb:
> Das kann kaum was bringen, weil er links oben anfang muss, was im
> Orginal sowohl links unten (lesen nach oben), als auch rechts oben
> (lesen nach unten) sein kann.

Verstehe ich nicht. Er hat ein Vollbild im RAM. DRAM. Und das soll um 
90° gedreht an eine andere Stelle im DRAM geschrieben werden.

Thomas U. schrieb:
> Blockweises Drehen hilft dem nicht ab, nur
> richtiges Reinschreiben an die Speicherstellen und zwar parallel mit
> mehreren Pfaden und FIFOs.

Im FPGA kann man das Drehen parallel mit BlockRAM bauen. Aber zum DRAM 
hin hat man nur das eine Interface. Und da geht es drum möglichst Bursts 
zu lesen und Bursts zu schreiben.
Wieso kann da blockweises Drehen nichts bringen? Gerade dadurch kann man 
doch sowohl lesend als auch schreibend mit Bursts vom und zum DRAM 
arbeiten.

Wenn man jeweils 128x128 Blöcke im FPGA dreht, dann braucht man dort 
128*128*8*3 Bits = 48 kByte BRAM. Man kann zum und vom DRAM Bursts mit 
der Länge 128x3 Bytes lesen und schreiben. Mit mehr BRAM gehen dann auch 
längere Bursts.

Thomas U. schrieb:
> Für solche Sachen gibt es aber auch fertige Chips.

Die man sich aber auch gut sparen kann wenn man sowieso so ein FPGA auf 
der Platine hat.

: Bearbeitet durch User
von Christoph Z. (christophz)


Lesenswert?

Joachim S. schrieb:
> Habt ihr vielleicht noch eine Idee?

Gustl hatte ja schon einen guten Ansatz, wie man die DRAM Limitierungen 
besser in den Griff bekommt.

Anderer Ansatz, wenn es dann um selber definierte Hardware geht, ein 
externes SRAM nehmen als Framebuffer.

von T.U.Darmstadt (Gast)


Lesenswert?

Gustl B. schrieb:
> Im FPGA kann man das Drehen parallel mit BlockRAM bauen.

Weil Dir das nichts bringt. Du musst wie du selber erkannt hast, die 
bursts auslasten, dazu musst du aber die richtigen Pixel schreiben. 
Diese kannst du aber, wenn du eine Spalte hast, direkt in das DDR 
schreiben und den dortigen Puffer des user Interface nutzen. Du brauchst 
aber mehrere Kanäle für mehrere Speicherstellen. Theoretisch brauchst du 
soviele, wie du auszulesende Spalten hast, um aus allen ehemaligen 
Zeilenpixeln die Spalten zusammen zu bauen. Wenn Du das nicht mavhst, 
bekommst du keine lineare Adressierung und damit nur sehr kurze Pakete, 
d.h. du musst viele Seiten im DRAM wechseln, um die Zeilen deines 
MINI-Blocks wegzuschreiben.

Das aber dauert so lange, dass du massenhaft von denen bräuchtests, um 
z.B. Nichtzugriff wegen Seitenwechsel oder Refresh zu verkraften. Es 
bleibt daher nur, eine intelligente Zuteilung zu den RAM-Bereichen so, 
dass die gleiche Seite lange offenbleibt.

Es ist daher besser, mit einem teilweise beschriebenen Wechselram zu 
arbeiten und bei ausreichender Anzahl von Zeilen, wenn genügend gefüllt 
ist, nochmal auzulesen und final zu sortieren. Z.B. könnte man jeweils 
256 Pixel einer Zeile nutzen und parallel wegschreiben.

Volle Bandbreite geht nur mit mehreren parallelen DDR-Controllern.

von Gustl B. (-gb-)


Lesenswert?

T. U. schrieb:
> eine intelligente Zuteilung zu den RAM-Bereichen

Ja wie denn genau?

T. U. schrieb:
> mit einem teilweise beschriebenen Wechselram zu arbeiten

Um genau das geht es doch schon die ganze Zeit. Der TO hat ein Vollbild 
im DRAM und will das - gedreht - an eine andere Stelle im DRAM 
geschrieben haben.
Dazu kann man aus dem ersten Bild im DRAM Quadrate lesen, also z. B. 128 
Zeilen mit je 128 Pixeln. Diese Quadrate kann man im FPGA im BRAM 
drehen, denn da kosten Zufallszugriffe nichts. Und dann schreibt man das 
gedrehte Quadrat an die richtige Stelle im Ausgabebildspeicher. Auch das 
ist dann ein zeilenweiser Zugriff der Bursts nutzen kann.

von T.U.Darmstadt (Gast)


Lesenswert?

Gustl B. schrieb:
> Der TO hat ein Vollbild im DRAM
Nö, laut seiner Aussage muss er ...

Joachim S. schrieb:
> ein AXI4-Stream Video-Signal um 90° drehen.
Er bekommt es also erst rein. Schon da muss man intelligent arbeiten, 
will man das RAM nutzen. Da braucht es Annahmen über Refresh, 
User-FIFO-Tiefe und Anzahl. Ich würde mit bis zu 4 user Interfaces 
arbeiten und Viertelzeilen nehmen.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Hat schon jemand den Vorschlag gemacht, den Bildschirm zu drehen? 
:duck-und-renn:

von T.U.Darmstadt (Gast)


Lesenswert?

Mampf F. schrieb:
> Hat schon jemand den Vorschlag gemacht, den Bildschirm zu drehen?
> :duck-und-renn:

solche Aufgaben enden nicht nur beim Drehen. Das Bild muss auch 
gestaucht oder beschnitten werden, auf 2 Monitore verteilt werden und 
eventuell gezommed werden. Das erfordert etwas, was wir in der 10. 
Klasse "Koordinatentransformation" genannt und angewendet haben. Damit 
lässt sich leicht so ziemlich alles verwursten ...

Die moderne Programmierergilde ist aber offenbar nicht mal mehr in der 
Lage, einen einfachen Zoom in einem browser richtig zu konfigurieren.

Beitrag "Zeilenumbruch komisch"

Unsere Jugend ist überfordert!

von Gustl B. (gustl_b)


Lesenswert?

T.U.Darmstadt schrieb:
> solche Aufgaben enden nicht nur beim Drehen.

Ja, ist das immer so?

T.U.Darmstadt schrieb:
> Die moderne Programmierergilde ist aber offenbar nicht mal mehr in der
> Lage, einen einfachen Zoom in einem browser richtig zu konfigurieren.

Dir ist klar, dass das mit dem Zoom eines Bildchens fast gar nichts mehr 
zu tun hat?
Da geht es um Änderung der Schriftgröße, Worttrennung, ...

T.U.Darmstadt schrieb:
> Unsere Jugend ist überfordert!

Wenn du hier zwei großteils verschiedene Dinge vergleichst sagt das viel 
über das Niveau der TU Darmstadt.

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.