Forum: FPGA, VHDL & Co. Bildverarbeitung/Auslesen CMOS Sensor


von Manuel T. (tedd)


Lesenswert?

Hallo!

Ich bin relativ neu im FPGA und VHDL Bereich und bin mir in vielen 
Sachen noch recht unsicher: Mein Projekt ist es die Daten eines CMOS 
Sensors(MT9M001 ...1280x1024 a 10bit) auszuelesen und über USB (EZUSB 
FX2LP) an den Rechner zu senden.
Als FPGA nutze ich auf einem Board (Ztex USB-FPGA 1.15b) den Xilinx 
Spartan6 XC6SLX75. Auf dem board ist auch ein 128MB RAM drauf.

Da der Sensor ohne Unterbrechung seine Pixel schickt sobald er einen 
Takt bekommt und der USB Fifo zwischendurch mal voll sein könnte, müssen 
die Pixel zwischengespeichert werden um Datenverlust zu vermeiden.
Dafür nutze ich mit dem Xilinx MIG den RAM als RingBuffer.
Der BlockRAM hat ja "nur" 3096kBit und somit passen da keine ganzen 
Bilder rein und wenn ich nur Zeilen zwischenspeicher muss ich den Takt 
so langsam laufen lassen das ich die Bilder mit nur 3-4FPS auf den 
Rechner bekomme.

Ich habe also einen Prozess, der die Pixel mit dem CMOS Takt in den RAM 
schreibt.
Ein zweiter Prozess liest die Daten aus dem RAM mit dem USB Takt aus.
Ein weiterer Prozess synchronisiert den Füllstand des RAMS zwischen dem 
Lese- und dem Schreibprozess.

Jetzt mein Problem:
Ich würde gerne noch ein bisschen Bildverarbeitung auf dem FPGA 
reinbauen.
Zum Beispiel ein "ganz einfaches" Histogramm.
Ich habe mir gedacht, dass ich im Schreibprozess in den RAM die 
jeweiligen Grauwerte zählen könnnte.
Im Leseprozess aus dem RAM ins USB könnte ich dann Pixel im Bild mit 
meinem Histogramm überschreiben.
Allerdings brauche ich ja, wenn ich nur ein Histogramm einer Zeile 
machen will schon ein Array von 1280*10bit.
Bei einem ganzen Bild bräuchte ich das ganze 1024mal.
Jetzt stellt sich mir die Frage ob das ganze überhaupt realisierbar ist.

Die einzige Methode die mir erade einfällt wäre es, das Histogramm auch 
ins RAM zu schreiben. Aber wenn ich wirklich ein Histogramm eines ganzen 
Bildes haben will, dann müsste ich doch für jeden Grauwert, also 1024 
mal, über das Bild gehen und diesen zählen was mir auch nicht sinnvoll 
erscheint...

Ich hoffe der text war nicht zu lang und ich habe nichts wichtiges 
vergessen.
bin euch für jeden Tip sehr dankbar :)

Gruß
manuel

von Manuel (Gast)


Lesenswert?

OK bei der ganzen Aufregung,dass ich kein ganzes Bild im fpgazwischen 
speichern kann, habe ich vergessen,dass es einen unterschied macht ob 
man tatsächlich 1280*1024 10bit Werte speichern möchte oder 1024 Werte 
(10bit) mit denen man 1024*1280 darstellen kann

von Sigi (Gast)


Lesenswert?

Gleich zu Beginn ein solches Projekt auszuwählen ist vlt
nicht gerade die beste Idee.

Aber gut, zur Kamera: MT9-Module gibt's z.B. bei EBay
für ca. 20-30 Euro, allerdings mit 8Bit. Ein einfaches
I2C-master-Modul reicht, um die Controller-Parameter zu
setzen. (hab ich mit einem dieser Boards mal gemacht, ist
kein grosser Aufwand).

Zu USB: Ich kenne das TZEX-Board nicht, die USB-Ansteuerung
auf dem Board scheint aber auch nicht so kompliziert sein.
Aber statt USB ist vlt ein VGA als einfache Ausgabe
besser/einfacher. Anleitungen für VGA-Ansteuerungen
gibt's auch zu Hauf (und die Kameraparameter zu setzen
ist mit I2C-master ein Klacks).

Falls der FIFO überläuft: Einfach den Pixel-Takt runtersetzen
und mit weniger FPS zufrieden geben.

von Markus F. (Gast)


Lesenswert?

Sigi schrieb:
> Falls der FIFO überläuft: Einfach den Pixel-Takt runtersetzen
> und mit weniger FPS zufrieden geben.

Dann hast Du aber keine ordentlichen FPS mehr, einige Sensoren machen 
das Timingmässig auch nicht mit.

von Fitzebutze (Gast)


Lesenswert?

Hi,

mit einer ähnlichen Konfiguration arbeite ich schon ne Weile. Ist recht 
komplex, einen zuverlässigen Bildstrom hinzukriegen.
Wenn noch gar kein Framework existiert, wird das ein ganz schönes Paket.
Wenns nur zum Lernen ist, würde ich mal mit einem 3x3-Filterkernel oder 
einem Debayer-Algo anfangen. Da kommt man schon mal ohne RAM aus.

Ansonsten die Checkliste:
1) USB-FIFO-Interface
2) Sensor-Ansteuerung i2c (Soft CPU?)
3) PC-seitiges "Frame-grabbing" per USB. Wichtiges Detail: Ohne 
RAM-Pufferung der Bilder geht es fast nur im isochronen Transfermodus.

von Manuel T. (tedd)


Lesenswert?

Hallo!

Danke schonmal für die Antworten.
Bin noch einmal in mich gegangen und habe die letzten Tage etwas dran 
gearbeitet.
Wahrscheinlich ist es falsch rübergekommen aber einige Dinge 
funktionieren schon:

Ich habe auf dem FPGA einen Ringbuffer beschrieben mit einem 
Adressbereich der genau 2 Bilder umfasst. Es wird also immer ein Bild 
vom CMOS in den DDR RAM geschrieben während das vorherige aus dem DDR 
RAM gelesen wird und über USB an den Rechner geschickt wird.
Das ganze läuft in 2 verschiedenen Prozessen, einem Lese- und einem 
Schreibprozess ab.
Auf dem PC kriege ich auch schon ein Livebild über ein JAVA GUI.
I2C Befehle kann ich ebenfalls an ein I2C Slave Modul auf dem FPGA 
senden.
So kann ich zum Beispiel einen Benutzerdefinierten Threshold ans FPGA 
schicken und der binarisiert mir dann das Bild im Leseprozess(if-Abfrage 
ob das gerade gelesene Pixel über oder unter dem Threshold liegt...).

Jetzt ist mein Problem, dass ich gerne auf dem FPGA ein Histogramm 
erstellen würde.
Wenn ich allerdings ein Array mit 1024 Einträgen a 21 Bit (weil eine 
Graustufe maximal 1280*1024 mal vorkommen kann) erstelle dauert das 
synthetisieren so ewig lange das ich es vorzeitig abbreche weil ich gar 
nicht weis ob er irgendwann mal fertig wird.

Wie geht man mit so großen Datenmengen um?
Das Histogramm auch ins RAM zu schreiben erscheint mir sehr kompliziert 
zu sein, denn wenn ich auf den ersten Eintrag zugreifen bzw. den ersten 
Grauwert inkrementieren will müsste ich den ja erstmal einlesen, dann 
inkrementieren und dann wieder ins RAM schreiben was mind. 3 Taktzyklen 
dauern würde?!

Vielleicht hat bezüglich Histogramm und großen Datenmengen ja noch 
jemand einen Tip :)

Besten Gruß
Manuel

von P. K. (pek)


Lesenswert?

Manuel Ted schrieb:
> Das Histogramm auch ins RAM zu schreiben erscheint mir sehr kompliziert
> zu sein

Da bist ja schon von selbst auf die richtige Lösung gekommen, und das 
ist nicht derart kompliziert wie es auf den ersten Blick scheint. Und Du 
sparst Dir ein riesiges FF-Grab.

Richtig gepipelined solltest Du jeden zweiten Wert aus dem Bild in das 
Histogramm reinkriegen. Vermutlich reicht es aber auch, wenn Du noch 
weniger Werte berücksichtigst, und z.B. mit einem (separaten...) 
1024x16-Ram auskommst. Da solltest Du Dir sowieso Gedanken machen wie 
genau Du's denn wirklich brauchst. Für eine simple Darstellung im Bild 
selbst, ohne weitere Verarbeitung, genügt Dir sicher noch weniger.

von Manuel T. (tedd)


Lesenswert?

Peter K. schrieb:
> Da bist ja schon von selbst auf die richtige Lösung gekommen, und das
> ist nicht derart kompliziert wie es auf den ersten Blick scheint. Und Du
> sparst Dir ein riesiges FF-Grab.
Hallo!

Die Antwort kam ja schnell! Danke!
Dazu habe ich ein paar Fragen:
> Richtig gepipelined solltest Du jeden zweiten Wert aus dem Bild in das
> Histogramm reinkriegen. Vermutlich reicht es aber auch, wenn Du noch
> weniger Werte berücksichtigst, und z.B. mit einem (separaten...)
> 1024x16-Ram auskommst. Da solltest Du Dir sowieso Gedanken machen wie
> genau Du's denn wirklich brauchst. Für eine simple Darstellung im Bild
> selbst, ohne weitere Verarbeitung, genügt Dir sicher noch weniger.

Was ist mit richtig gepipelined gemeint?
Ich verstehe das jetzt so, da ich ja aus dem RAM erstmal lesen muss um 
einen Wert zu inkrementieren oder sonstiges den erst mal lesen muss und 
erst auf der zweiten Taktflanke wieder reinschreiben kann. Daher jeder 
2te Pixel?

Richtig! Für die simple Darstellung im Bild brauche ich eigentlich gar 
nicht so viele Werte weil ich die eh' nicht alle Darstellen kann. 256 
pro Graustufe würden für den Anfang sicher dicke reichen.

Wie ist das mit dem RAM gemeint. Extra dafür ins DDR RAM?
Oder muss/kann ich mir da etwas aus den Language Templates auf Basis des 
Block RAMs kopieren?
Habe hierzu einmal unter Device Macro Instatiation -> Spartan 6 -> 
RAM/ROM die BRAM_*_MACRO Sachen gefunden.
und unter Synthesis Constructs ->Coding Examples -> RAM -> BlockRAM 
gibt's auch was.
Bin nun etwas verunsichert welches ich nehmen soll aber ich habe mir 
jetzt auch schon den UG383 Spartan-6 Block RAM User Guide geschnappt und 
werde mir das mal durchlesen...

von P. K. (pek)


Lesenswert?

Manuel Ted schrieb:
> Extra dafür ins DDR RAM?

Nein, bloss nicht, bei dieser Art Operation bräuchtest Du im DDR immer 
mehrere (viele) Zyklen.  Deshalb schreibe ich ja separat. Nimm dafür 
ein Block-RAM, dafür sind sie da.

> Was ist mit richtig gepipelined gemeint?

Synchron lesen braucht 2 Zyklen, schreiben 1 Zyklus und inkrementieren 
je nach Clockspeed auch noch einen Zyklus. Trotzdem kannst Du mit ein 
paar Kniffen erreichen, dass Du alle 2 Zyklen einen Wert bearbeiten 
kannst.
Den Aufwand kannst Du Dir aber sparen, wenn es nicht so genau sein muss.

von J. S. (engineer) Benutzerseite


Lesenswert?

Wieso ausgerechnet (nur) jeden zweiten? Wenn fummeln, dann richtig.

Bei einem echten looped access aufs RAM braucht man in der Regel 
wenigstens 3 Takte, weil das BRAM einen Takt verzögert ist und die 
Addition nicht voll kombinatorisch zu machen ist.

1:setadr
2:fetch
3:add
4:store
5:read

Ein neues "setadr" kann frühestens beim Takt 4 kommen, weil schon im 
nächsten Takt dieser Wert geholt werden können muss, um aktuell zu 
bleiben. Man hätte also (4-1) = 3 Takte Verzögerung, erfasste also nur 
jeden dritten.  Bei einem DP-RAM braucht man u.U. sogar 4 steps, wegen 
des Transparenzproblems beim write while read, erspart sich aber dafür 
etwas Verwaltungslogik.

Ok, wenn man denn Adder irgendwie noch mit reinnimmt, wäre noch ein Takt 
zu sparen, aber Du brauchst so oder so immer Schattenrams und /oder 
parallele Architektur, es sei denn Dein FPGA-Takt ist n mal schneller, 
als die Daten.

Wenn man es aber richtig pipelined, bekommt man natürlich jeden Wert 
mitgezählt. Ist natürlich ein bissl Gefummel und baucht einen pre write 
cache und einen post read cache sowie einen intelligenten Adder, der die 
Doubletten in der cache pipe erfasst. Dann geht es mit einem internen 
B-BRAM und aufgrund der einfacheren Verwaltung ist dann die DP-RAM 
Lösung kürzer.

von P. K. (pek)


Lesenswert?

Juergen S. schrieb:
> Wieso ausgerechnet (nur) jeden zweiten?

Du hast natürlich recht, es geht auch mit komplett allen Werten. Die 
Lösung "nur jeden zweiten" bietet m.E. aber das beste 
Aufwand-Ertrags-Verhältnis, wenn man es einigermassen genau will.

Für diesen Fall hier aber ist die "billigste" Lösung, sprich nur jeden 
N-ten Wert überhaupt zu benutzen und gar nichts zu pipelinen, 
wahrscheinlich sowieso hinreichend.

von HTI (Gast)


Lesenswert?

Was spräche dagegen, jeden zweiten Wert in ein eigenes RAM zu schieben 
und nachher zu addieren?

von Markus F. (Gast)


Lesenswert?

Bei einem Histogramm reicht in der Regel ein repräsentativer 
Querschnitt, weil das, was aus einem Histogramm herauszuholen ist, 
nämlich z.B. der Median wenig Verwertbarkeit besitzt.

von Manuel T. (tedd)


Angehängte Dateien:

Lesenswert?

Ah

Habe gar nicht gesehen, dsas hier noch mehr Beiträge gekommen sind! 
Danke!

Ist es nicht sogar möglich jeden Wert ins Histogramm reinzunehmen indem 
der BRAM mit READ_FIRST Mode implementiert wird?
Da ich 1024 Grauwerte und höchstens 2 Bilder im RAM habe, habe ich einen 
2048 * 10 Bit BRAM mit asynchronen Ports (einer schreibt ins BRAM mit 
dem Takt mit dem die Pixel kommen, der andere liest vom BRAM mit dem USB 
Takt) inferiert(so richtig?)
1
  process(CLKA)
2
  begin
3
    if ( rising_edge(clka) ) then
4
      if ena = '1' then
5
        doa <= RAM(to_integer(unsigned(addra)));
6
        if ( wea = '1' ) then
7
          RAM(to_integer(unsigned(addra))) := dia;
8
        end if;
9
      end if;
10
    end if;
11
  end process;
12
13
  process(clkb)
14
  begin
15
    if ( rising_edge(clkb) ) then
16
      if enb = '1' then
17
        dob <= RAM(to_integer(unsigned(addrb)));
18
        if ( web = '1' ) then
19
          RAM(to_integer(unsigned(addrb))) := dib;
20
        end if;
21
      end if;
22
    end if;
23
  end process;

Man fängt beim ersten Pixel an und setzt die Adresse. Beim nächsten Takt 
wird der Wert erhöht und der WriteEnable Pin gesetzt sowie die Adresse 
des nächsten Grauwertes gesetzt. Allerdings kommt man an der Stelle 
wahrscheinlich in einen Konflikt da vemutlich beim schreiben schon die 
nächste Adresse verwendet wird und nicht wie gewünscht die vom ersten 
Pixel.
Allerdings müsste man so doch zumindest jeden zweiten Wert schreiben 
können.

Ich kann schon Werte in meinem Bild darstellen allerdings bekomme ich 
komischerweise immer 16 Pixel Breite Lücken in meinem Histogramm.

Ich vermute, dass das evtl. mit folgender InfoMeldung(Keine Warnung) im 
Design Summary zusammenhängt:

    Xst:1843 - HDL ADVISOR - FlipFlop HIST1_ADDRA_0 connected to a 
primary input has been replicated

Die Meldung bekomme ich für die Adressbits 0 - 3 des BlockRAM, womit 
sich ja 2^4 = 16 Werte darstellen lassen.
Im XST User Guide steht man soll den Max_Fanout Wert für das Projekt 
höher stellen, allerdings weis ich nicht was ich da einstellen soll.
Der steht momentan auf 100000.

Ansonsten bekomme ich nur noch eine Warnung, dass die Timings bei Async 
BRAM mit Read_first_mode einzuhalten sind und nicht auf beiden Ports von 
auf Adresse gleichzeitig gelesene/geschrieben werden darf.

von Manuel T. (tedd)


Lesenswert?

Ich habe jetzt den BlockRAM mal als ipcore reingemacht und dort habe ich 
das gleiche Problem, allerdings ohne Infos im Design Summary. Scheint 
also doch evtl. an meinem vhdl design zu liegen.

von Ralf (Gast)


Lesenswert?

Manuel Ted schrieb:
> Ist es nicht sogar möglich jeden Wert ins Histogramm reinzunehmen indem
> der BRAM mit READ_FIRST Mode implementiert wird?
Das read first regelt nur, dass bei gleichzeitigem Lesen zuerst der alte 
Wert gelesen wird und dann geschrieben.



> Ich kann schon Werte in meinem Bild darstellen allerdings bekomme ich
> komischerweise immer 16 Pixel Breite Lücken in meinem Histogramm.
Weil du immer alte Werte ausliest und sie addierst.

> Ich vermute, dass das evtl. mit folgender InfoMeldung(Keine Warnung) im
> Design Summary zusammenhängt:
>     Xst:1843 - HDL ADVISOR - FlipFlop HIST1_ADDRA_0 connected to a
> primary input has been replicated
Nö, das hat was mit Geschwindigkeit zu tun und dem Umstand, dass das 
primary FF in den IO Zellen sitzt. Im replizierten steht nichts anderes 
drin.

von Manuel T. (tedd)


Lesenswert?

Ralf schrieb:
>> Ich kann schon Werte in meinem Bild darstellen allerdings bekomme ich
>> komischerweise immer 16 Pixel Breite Lücken in meinem Histogramm.
> Weil du immer alte Werte ausliest und sie addierst.

Und wieso sind die Lücken immer 16 Pixel Breit?
Die Adresse für das BlockRAM setze ich immer über den gerade anliegenden 
Grauwert für das jeweilige Pixel. Müssten die Daten dann nicht 
"ungeordnet" im BlockRAM liegen und man würde willkürliche bzw von den 
Grauwerten abhängige Lücken bekommen?

von Manuel T. (tedd)


Angehängte Dateien:

Lesenswert?

Ok vielleicht mache ich auch irgendwas mit der Adressierung falsch?

Wenn ich das BlockRAM einfach mit Werten vollschreibe bekomme ich keine 
16 Pixel Breite Lücken.

Das mache ich folgendermaßen:
1
            -- WR_IMG = 0 Erstes Bild wird geschrieben
2
            if ( WR_IMG = '0' ) then
3
              -- Fülle die ersten 1024 Adressen mit dem Wert 128
4
              if ( HIST1_ADDRA(9 downto 0) <= 1023 ) then
5
                HIST1_DIA  <= "10000000";
6
                HIST1_WEA  <= ( others => '1' );
7
                HIST1_ADDRA(10) <= WR_IMG;
8
                HIST1_ADDRA  <= HIST1_ADDRA + 1;
9
              -- Sind die Adressen gefüllt mache nichts
10
              else
11
                HIST1_WEA  <= ( others => '0' );
12
              end if;
13
            -- WR_IMG = 1 Zweites Bild wird geschrieben
14
            else
15
              -- Fülle die Adressen von Bild 2 mit dem Wert 255
16
              if ( HIST1_ADDRA(9 downto 0) <= 1023 ) then
17
                HIST1_DIA  <= ( others => '1' );
18
                HIST1_WEA  <= ( others => '1' );
19
                HIST1_ADDRA(10) <= WR_IMG;
20
                HIST1_ADDRA  <= HIST1_ADDRA + 1;
21
              -- Sind die Adressen gefüllt mache nichts
22
              else
23
                HIST1_WEA  <= ( others => '0' );
24
              end if;
25
            end if;
Das BlockRAM hat eine Tiefe von 2048 und eine Breite von 8 Bit.
Da ich im externen RAM ja einen Speicherbereich "reserviert" habe in den 
2 Bilder passen will ich in den ersten 1024 Adressen des BlockRAMs das 
Histogramm vom ersten Bild speichern und in den Adressen 1025-2048 das 
Histogramm vom zweiten Bild.
WR_IMG = '0' heißt, dass gerade das erste Bild geschrieben wird. Ist das 
Bit gesetzt, wird das zweite Bild geschrieben.
Folglich müsste ich doch wenn ich das oberste Bit der BRam Adresse mit 
dem WR_IMG Signal setze auch das Histogramm für das erste oder zweite 
Bild schreiben können.
So bekomme ich im ersten Bild ein (den leseprozess lass ich jetzt mal 
außen vor) Histogramm was mir für jeden Wert eine 128 anzeigt.
Für das zweite Bild eine 255...

Wenn ich allerdings die Adresse über den pixelwert setze kriege ich 
wieder die 16 pixel breiten lücken.
1
            -- Setze die Adresse über den Grauwert
2
            if ( HIST1_READA = '0' ) then
3
              HIST1_ADDRA(10)  <= WR_IMG;
4
              HIST1_ADDRA(9 downto 0) <= CAM_DD;
5
              HIST1_READA <= not HIST1_READA;
6
            -- schreibe den an der Adresse anliegenden Wert + 1 in die Adresse
7
            else
8
              HIST1_DIA  <= HIST1_DOA + 1;
9
              HIST1_WEA  <= ( others => '1' );
10
              HIST1_READA <= not HIST1_READA;
11
            end if;

Juergen S. schrieb:
> 1:setadr
> 2:fetch
> 3:add
> 4:store
> 5:read

Hier habe ich ja nur:
1: setadr
2: fetch,add,store

Ist das viellecht der Grund? Wenn ja wieso?

: Bearbeitet durch User
von Manuel T. (tedd)


Lesenswert?

Ok sry... ich sehe gerade, dass wenn ich einfach ein Software Histogramm 
vom gespeicherten bild mache auch schon die Grauwerte welche die 16 
Pixel breiten Lücken verursachen zu fehlen scheinen.
Also schein es irgendwo an der Hardware zu liegen.
Tut mir leid das ich den Thread wieder hochgeholt habe. Ich mache mich 
jetzt erstmal auf die Suche nach dem Fehler ;)

von FPGA-Fuzzi (Gast)


Lesenswert?

Dein Input ist nicht normal verteilt. Was Dein VDHL tut, sollte man 
simulieren können.

von Manuel T. (tedd)


Lesenswert?

Die äquidistanten Lücken kamen daher, dass Bit 4 vom CMOS Sensor auf 
meinem Board nicht richtig angelötet war.

Nächstes Problem :
Ich möchte die Werte des Histogramms auf den Wert 255 normieren damit 
ich diese venünftig darstellen kann. Allerdings ist das mit dem teilen 
und multiplizieren auf einem FPGA ja nicht so einfach.
Selbst wenn ich nur die Daten verarbeiten will für eine Kantendetektion 
oder so muss ja vermutlich auch irgendwo mal geteilt werden.

Wenn ich einfach bei 255 aufhöre den jeweiligen Grauwert zu zählen, ist 
bei einem 1280*1024 großem Bild je nachdem was man aufnimmt fast jeder 
Grauwert bei 255.

Vielleicht ist eine "quick&dirty" Lösung einfach das rechtsschieben von 
Bits was ja einer Division von 2 entspricht... hmhmhm :-)

: Bearbeitet durch User
von Uwe (Gast)


Lesenswert?

> Vielleicht ist eine "quick&dirty" Lösung einfach das rechtsschieben von
> Bits was ja einer Division von 2 entspricht... hmhmhm :-)
bzw. nur die oberen 8 Bit verdrahten, dann mußt du nicht mal schieben

von Manuel T. (tedd)


Lesenswert?

Ja das wäre auch eine Idee!

Gibt es eine Möglichkeit über Attribute wie 'length oder so rauszufinden 
welches das höchste gesetzte Bit bei einem std_logic_vector ist?

Dann könnte ich die Darstellung immer ab diesem Bit + den nächsten 7 Bit 
für den jeweiligen Grauwert machen.

von high tec ing (Gast)


Lesenswert?

Während der Synthese kann man das prüfen und optimieren lassen, zur 
Laufzeit geht das nur durch einen priority decoder.

von Manuel T. (tedd)


Lesenswert?

Hallo!

Wie wird das Teilen denn bei den "Profis" gemacht?
Fast jeder Filter, etc braucht doch Divisionen.
Wird das dann wirklich mit so einem Radix-2 Teiler gemacht?

Wenn ich das richtig verstanden habe, dauert bei einer Division die 
Verzögerung des Ergebnisses so lange wie die Anzahl der Bits des 
Dividenden.
Das würde für eine Bearbeitung eines 1280*1024 Bildes und 8 Bit Pixeln 
bzw. Dividend bei 200 MHz doch "schon" 50ms Sekunden bedeuten.
Das wärde in meinem Fall eine Halbierung der Framerate :(

Will man jetzt die Nachbarn von einem Pixel betrachten stelle ich mir 
das auch ziemlich schwer vor, da man die Pixeldaten ja Stück für Stück 
aus dem Ram holt.

Ist das ganze wirklich so kompliziert?

Ich habe keine Ahnung von Pico-/Microblaze oder sogar DSPs aber geht das 
damit evtl. "einfacher" ?

von P. K. (pek)


Lesenswert?

Manuel Ted schrieb:
> Das würde für eine Bearbeitung eines 1280*1024 Bildes und 8 Bit Pixeln
> bzw. Dividend bei 200 MHz doch "schon" 50ms Sekunden bedeuten.
> Das wärde in meinem Fall eine Halbierung der Framerate :(

Du rechnest bei 8-bit Auflösung mal mit 8 Cycles. Wenn Du nun jeden 
Eintrag deines Histogramms durch den Maximalwert teilst, ergibt das dann 
1024 * 8 = 8192 Cycles, bei 200 MHz sind das ~41 us.

Wenn Du Double-Buffering betreibst, reduziert sich Deine Framerate 
überhaupt nicht.

von Manuel (Gast)


Lesenswert?

Schon... meine Rechnung bezog mich aber auf einen Algorithmus bei dem 
jeder Pixel geteilt werden muss.

Scheint aber alles schmarrn zu sein:
Anscheinend macht man es so, dass man die Divisionen so "pipelined", 
dass diese für die Pixel Parallel ablaufen.
Also man startet bei Pixel 1, macht mit einer weiteren Division bei 
Pixel 2 weiter und wenn man bei Pixel 8 ist, ist die Division für Pixel 
1 (fast) fertig.
Am Ende vom Bild hat man dann nur eine Verzögerung von 8 Taktzyklen.

von Edi M. (Gast)


Lesenswert?

Genau so macht man es. Die schrittweise Division wird nicht sequenziell 
nach und nach ausgeführt, sondern jede Rechenstufe exisitert real. Ist 
im Prinzip so wie bei Opel am Band. Jeder Arbeiter macht einen Schritt 
und zwar immer denselben, am Ende ist die Karre fertig und derletzte 
gibt das Ergebnis aus.

Und dann kommt General Motors und behauptet, die pipeline ist zu lang, 
braucht zuviel Strom und fordert Beihilfen, die die hessische 
Landesregierung bereitwillig rausgibt.

von P. K. (pek)


Lesenswert?

Manuel schrieb:
> Scheint aber alles schmarrn zu sein:
> Anscheinend macht man es so, dass man die Divisionen so "pipelined",
> dass diese für die Pixel Parallel ablaufen.

Das mit dem "Schmarrn" greift etwas zu kurz.

Wenn Dein Ausleseprozess schnell genug ist und Du daneben die Zeit zur 
Verfügung hast, machst Du es mit nur einer Instanz, wenn es möglichst 
schnell gehen muss nimmst Du N parallele Instanzen.

Ist immer ein Tradeoff: Eines kostet weniger FPGA-Resourcen (& 
allenfalls Strom), das andere weniger Zeit.

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


Lesenswert?

Manuel Ted schrieb:
> Gibt es eine Möglichkeit über Attribute wie 'length oder so rauszufinden
> welches das höchste gesetzte Bit bei einem std_logic_vector ist?
So einfach ist das zur Laufzeit nicht:
http://www.lothar-miller.de/s9y/archives/55-Finde-das-MSB.html

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.