Forum: FPGA, VHDL & Co. Bitstrom per Huffman-Tabelle erzeugen


von Cihan K. (lazoboy61)


Lesenswert?

Hallo,

habe mal wieder eine Frage. Stecke aktuell in einem Projekt drin, wo ich 
Bilddaten (Pixeldaten) komprimieren will. Warum und wieso lass ich jetzt 
mal weg, hat schon einen bestimmten Grund (Vllt. nur kurz zu erwähnen, 
um bestimmte Datenraten einhalten zu können).

So nun zu meinem aktuellen Stand. Habe mittels FFT die Bilddaten 
eingelesen und mir die Real und Imaginärwerte angesehen. Ist in 
Vergleich zu den Matlab-Referenzwerten in Ordnung. Nun habe ich eine 
Huffman-Tabelle, wo ich die FFT Output Daten skaliert einlese, um daraus 
ein Bitstrom zu generieren. Den Bitstrom habe ich unter Delphi schon 
einen Kollegen generieren lassen, sodass ich als Ergebnis einen 
Kompressionsfaktor von ca. 2 sah, was mich zum Ziel führt.

Meine Frage beruht sich nun darauf, wie ich diesen Bitstrom bilden soll. 
Aktuell habe ich folgendermaßen programmiert:

Die Skalierten FFT daten werden als Addresse für einen BRAM (Huffman 
Tabelle) benutzt, wo dann ebend die Bitstrom-Daten + die gült. Bitanzahl 
hinterlegt sind.
Z.B. habe ich eine Zahl 1 aus der FFT dann wird im BRAM die Addresse 1 
ausgelesen und gibt mir folgendes als Ergebnis: "0001010101010101" & 
"0000000000001110". Das Ergebnis sagt mir nun, dass auf den Bitstrom 14 
Bits gelegt werden müssen (von rechts aus gesehen, also 
"01010101010101").

Jetzt lege ich diese Bits in eine Zwischenvariable bis neue Daten 
kommen. Und hier liegt mein Problem, ich muss die Daten nun 
verschieben/shiften/platz machen, um neue Daten aufzunehmen bis eine 
bestimmte Menge gefüllt ist, sodass es wieder entleert werden kann. 
Vllt. ein bisschen durcheinander, aber die Frage halte ich ein bisschen 
Allgemein, wie sollte man nach der Huffman-Tabelle vorgehen, wie sollte 
der Bitstrom erzeugt werden?

Quellcode zu posten habe ich erstmal sein lassen, wollte das jetzt 
keinem antun, ist schon zuvieles drin, bis man sich reinfindet dauerts.

Würde mich über jede Hilfestellung sehr freuen.

mfg Cihan

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


Lesenswert?

Cihan Kalayci schrieb:
> bis eine bestimmte Menge gefüllt ist
Wie groß ist diese "bestimmte" Menge?
Denn so, wie due es da jetzt gerade beschrieben hast, ist das erst mal 
ein Monstermultiplexer...

Cihan Kalayci schrieb:
> "0001010101010101" & "0000000000001110".
> Das Ergebnis sagt mir nun, dass auf den Bitstrom 14 Bits gelegt werden
> müssen
D.h. die zweite Zahl wird nicht größer als 16?
Kannst du da mal ein längeres Beispiel geben?

von Cihan K. (lazoboy61)


Lesenswert?

Lothar Miller schrieb:
> Cihan Kalayci schrieb:
>> bis eine bestimmte Menge gefüllt ist
> Wie groß ist diese "bestimmte" Menge?
> Denn so, wie due es da jetzt gerade beschrieben hast, ist das erst mal
> ein Monstermultiplexer...

mit bestimmte Menge meine ich eigentlich nur 64 Bits, die dann in einen 
Fifo reingeschrieben werden. Die Zwischenvariable ist 128 Bits groß. 
D.H. sobald mehr als 63 Bits in der zwischenvariable drin ist, raus 
damit, in den Fifo damit, den Rest mit neu ankommenden Daten 
umsortieren.

> Cihan Kalayci schrieb:
>> "0001010101010101" & "0000000000001110".
>> Das Ergebnis sagt mir nun, dass auf den Bitstrom 14 Bits gelegt werden
>> müssen
> D.h. die zweite Zahl wird nicht größer als 16?
> Kannst du da mal ein längeres Beispiel geben?

Die Zahlen bzw. Bits können höchstens 15 werden, wobei es auch 
Sonderzeichen gibt. Im groben können in einem neuen Takt von mind. 4 - 
62 bits in die Zwischenvariable (in den Bitstrom kommen).

von Cihan K. (lazoboy61)


Lesenswert?

Ich versuch mal ein längeres Beispiel darzustellen.

Nehmen wir an wir haben folgende Huffman Tabelle:
Bram-Addresse              Bits      Anz.gült.Bits
 0                           11            2
 1                         1000            4
 2                        00001            5
 3                        10111            5
 ...
 252            011000111110101           15
 253            010100001110011           15
 254            010101001110001           15
 255            010101001110111           15

Nun kommt aus der FFT folgende Real und Imaginärzahlen raus (daten sind 
skaliert):
Real: 18000, 299, 0, 3, 255, ...
Imag: 0, 2, 252, 1500, 5000, ...

Als erstes wird die Huffman Tabelle in den Addressen 18000 und 0 
abgefragt. Hierbei muss ich erwähnen, dass es zwei Huffman Tabellen 
sind, jeweils real und imaginärteil. Dabei sind beide Huffman-Tabellen 
mit 1024x32 Bits implimentiert.

Nun wird geguckt: 18000 außerhalb des Bram Addressbereiches also 
sonderzeichen, d.h. eine bestimmte bitfolge("01010101001011") + die 
18000 landen im Bitstrom. Weiterhin wird für den imag. Teil die Addr. 0 
gelesen, also kommen die Bits "11" auf den Bitstrom.
                    (Sonderzeichen)     (18000)   (Imag-Teil)
Aktueller Bitstrom: 01010101001011 00100011001010000  11
Bitstrom-Größe: 33

Im nächsten Beispiel müssen nun die 299 und 2 genommen werden, auch hier 
hat der Real Teil ein Sonderzeichen, der Imag bekommt die Bits "00001" 
(siehe ob. Tabelle), also ergibt sich der nächste Bitstrom:
                            (vorherige Daten)
Aktueller Bitstrom: 010101010010110010001100101000011
                    01010101001011 00000000100101011 00001
                    (Sonderzeichen)      (299)    (Imag-Teil)
Bitstrom-Größe: 33 + 36 = 69

Jetzt müssen die ersten 64 Bits in ein Fifo. D.h. im nächsten Takt, raus 
aus dem akt. Bitstrom, rein in ein fifo. Der rest des Bitstroms muss nun 
mit den neu ankommenden Daten weiter verknüpft werden.

Und das geht so weiter bis die FFT ihre Arbeit fertig geleistet hat.

hoffe das Beispiel ist verständlich genug. Wäre echt dankbar wenn ihr 
mir dabei Tipps geben könntet.

von Cihan K. (lazoboy61)


Lesenswert?

Achso, vllt. noch erwähnenswert.

Ich versuche schon seit letzter Woche die Implimentierung für den 
Bitstrom hinzubekommen. Habe dabei immer das Problem, dass die Synthese 
ewigkeiten dauert und dabei im Arbeitsspeicher auch eine sehr große 
Auslagerungsdatei abgelegt wird ( > 3GB). Die Simulation mit ISIM unter 
Xilinx läuft, der Bitstrom wird erzeugt, aber wenn ich es synthesieren 
will, hat XST bzw. ISE echt probleme.

Wie sollte man bei sowas denn am besten vorgehen?

Cihan

von Cihan K. (lazoboy61)


Lesenswert?

keiner ne idee?

Cihan

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


Lesenswert?

Cihan Kalayci schrieb:
> Habe dabei immer das Problem, dass die Synthese ewigkeiten dauert
> und dabei im Arbeitsspeicher auch eine sehr große Auslagerungsdatei
> abgelegt wird ( > 3GB).
Hört sich nach "Kombinatorikmonster" an...

> Die Simulation mit ISIM unter Xilinx läuft, der Bitstrom wird erzeugt,
> aber wenn ich es synthesieren will, hat XST bzw. ISE echt probleme.
Das ist absolut kein Problem, sowas hinzubekommen. Ich behaupte, das 
schafft man mit einem kleinen Dreizeiler, wenn eine Schleife beteiligt 
ist.

Cihan Kalayci schrieb:
> Jetzt müssen die ersten 64 Bits in ein Fifo. D.h. im nächsten Takt, raus
> aus dem akt. Bitstrom, rein in ein fifo. Der rest des Bitstroms muss nun
> mit den neu ankommenden Daten weiter verknüpft werden.
>
> Und das geht so weiter bis die FFT ihre Arbeit fertig geleistet hat.
Das ist ein riesiger Multiplexer, kein Wunder, dass die Synthese da so 
lange braucht. Lass doch mal das Zusammensetzen des Bitstroms sehen.

von Cihan K. (lazoboy61)


Angehängte Dateien:

Lesenswert?

Ich poste mal einen Ausschnitt aus meinem aktuellen Code (siehe Anhang, 
code.vhd).

Aktuell habe ich versucht mit dem operator shift_left zu arbeiten. Was 
erstmal geklappt hat. die Synthese dauert aber immer noch sehr sehr 
lange, wobei er jetzt nur so ungefähr < 1GB Auslagerungsdatei erstellt 
hat.

@Lothar:
Würde mich interessieren, ob die Programmierung sinnvoll ist bzw. ob man 
sowas mit einem shift_left machen könnte.

Cihan

von Cihan K. (lazoboy61)


Lesenswert?

Wahrscheinlich ist der Code ein bisschen unübersichtlich.

Nochmal ein update:
Ich hab diesen Code im FPGA implimentiert, der funktioniert auch. Nur 
ich bekomme bei Place&Route Timing-Fehler, die vorher nicht da waren. 
Wahrscheinlich kommen sie durch die shift_left-Operationen zustande?
Da kommt mir die Frage dann, ob man die Vektorverschiebungen mit dem 
shift_left-Operator machen sollte oder gibt es eine bessere Lösung?

Cihan

von SuperWilly (Gast)


Lesenswert?

Kleiner Hinweis von mir: Ich würde die konstanten Operationen der 
konstanten Ausdrücke derart zusammenfassen, dass es lesbar wird. Diese 
kommen an mehreren Stellen vor.

z.B.

'Sonstwas_SIZE '
statt
'VALID_BIT_SIZE_im + SZ_BIT_SIZE'

von Cihan K. (lazoboy61)


Lesenswert?

Die Integer-Werte "VALID_BIT_SIZE_im" und "VALID_BIT_SIZE_re" ändern 
sich im jeden Takt. Meinst du dass ich die zu einer Variablen 
zusammenfassen soll und die so im code verwenden soll?

Cihan

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

i_USER_FIFO_DIN <= DATA_STREAM((BIT_SIZE - 1) DOWNTO (BIT_SIZE - 64));

ist fehler anfällig,

z.B. bit_size=8
DATA_STREAM((7 DOWNTO -56);

Bleibt 64 bit breit.  Ich weiss auch nicht ob downto bis in den 
Minusbereich geht.


schreibe besser: wird gleich übersichtlicher.

i_USER_FIFO_DIN <= DATA_STREAM((BIT_SIZE - 1) DOWNTO 0);


Die Frage: Wievile Zeit hast du muss in einem Takt alles passieren?

von Cihan K. (lazoboy61)


Lesenswert?

René D. schrieb:
> i_USER_FIFO_DIN <= DATA_STREAM((BIT_SIZE - 1) DOWNTO (BIT_SIZE - 64));
>
> ist fehler anfällig,
>
> z.B. bit_size=8
> DATA_STREAM((7 DOWNTO -56);
>
> Bleibt 64 bit breit.  Ich weiss auch nicht ob downto bis in den
> Minusbereich geht.
>
>
> schreibe besser: wird gleich übersichtlicher.
>
> i_USER_FIFO_DIN <= DATA_STREAM((BIT_SIZE - 1) DOWNTO 0);
>
>
> Die Frage: Wievile Zeit hast du muss in einem Takt alles passieren?

Zeitmäßig habe ich nur 10ns, ich takte ja mit 100 MHz.

Und die Zeile:
i_USER_FIFO_DIN <= DATA_STREAM((BIT_SIZE - 1) DOWNTO (BIT_SIZE - 64));

wird nur dann aufgerufen wenn BIT_SIZE > 64 ist, d.h. das Fifo wird 
immer mit 64 gült. Bits geladen. Der Minusbereich den du meinst tritt 
nicht auf.

Als Beispiel nehmen wir mal an dass BIT_SIZE 70 ist (>64), also sieht 
die Zeile dann so aus:
i_USER_FIFO_DIN <= DATA_STREAM((70 - 1) DOWNTO (70 - 64));
i_USER_FIFO_DIN <= DATA_STREAM(69 DOWNTO 6);-- 64 Bits

Cihan

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

>
> Zeitmäßig habe ich nur 10ns, ich takte ja mit 100 MHz.
>
kannst du das Schieben und in den Fifo legen in unterschiedlichen Takten 
durchführen?
Könnte dein Problen entspannen.


Muss Bit_size nicht eine Konstante sein?

Ist dein Fifo 64 bit breit?

Selbst wenn du eine 64bit breiten Fifo hast, bekommst du die Daten mit 
64bit Breite aus dem FPGA. Mach einen max. 32bit breiten Fifo. Da musst 
du nicht so viel schieben. Das würde sehr viel FPGA Resourcen sparen. Es 
kann aber passieren du muss zwei Werte in den Fifo legen. Und wenn der 
FiFo in der Annahme überlastet ist und keine neuen Werte gerade 
entgegennehmen kannm muss ein busy Signal an den eigentlichen 
Huffmandecoder gehen.
Für mach mal eine Pause.

von Cihan K. (lazoboy61)


Lesenswert?

René D. schrieb:
> Muss Bit_size nicht eine Konstante sein?

Bit_Size wird in jedem Takt aktualisiert, er gibt ja an wie viele Bits 
gerade in der Ziwschenvariable Data_Stream gültig sind.

René D. schrieb:
> Ist dein Fifo 64 bit breit?

Mein Fifo ist 64 Bit breit, ja und zwar aus folgendem Grund: Data_Stream 
kann in einem Takt 4 Bits - 62 Bits aufnehmen. D.h. z.B. wenn Bit_Size 
aktuell 33 ist und es werden nun weitere Bits in Data_Stream 
geschrieben, dann wird Bit_Size ebend zu 33+62= 95. Nun lese ich die 
oberen 64 Bits von Data_Stream in den Fifo ein und die restlichen Bits 
müssen nun wieder mit neu ankommenden Bits in Data_Stream. Und hier ist 
die Schwierigkeit. Wenn ich es so mache wie im obigen code (code.vhd, 
siehe weiter oben), dann dauert die Synthese sehr lange und er hat auch 
noch Timing-Fehler.

René D. schrieb:
> Selbst wenn du eine 64bit breiten Fifo hast, bekommst du die Daten mit
> 64bit Breite aus dem FPGA. Mach einen max. 32bit breiten Fifo. Da musst
> du nicht so viel schieben. Das würde sehr viel FPGA Resourcen sparen. Es
> kann aber passieren du muss zwei Werte in den Fifo legen. Und wenn der
> FiFo in der Annahme überlastet ist und keine neuen Werte gerade
> entgegennehmen kannm muss ein busy Signal an den eigentlichen
> Huffmandecoder gehen.
> Für mach mal eine Pause.

32Bit wird wahrscheinlich zu wenig sein, da ich in jedem Takt bis zu 62 
Bits neue Daten bekommen könnte. Um es so wie du beschrieben hast machen 
zu können müsste ich den FFT Output entweder nochmal zwischenspeichern 
(was ich vermeiden will) oder den Output stoppen können.

Cihan

von Strubi (Gast)


Lesenswert?

Moin,

weiss nicht, ob's hilft, aber ansich musst Du nur untenstehenden C-Code 
in VHDL giessen, allerdings mit einer grösseren Bitbreite für Deinen 
Fall (hier nur 32).
Das geht mit 2 oder 3 Zyklen Latenz, je nach Durchsatzanforderungen.

Der Code ist aus einer JPEG-Implementation. Die VHDL-Version kann ich 
leider nicht posten. Aber Huffman-Coder sollten sich diverse in 
verschiedenen JPEG-Encodern finden lassen. Würde den mal als separate 
Entity synthetisieren um das Problem zu isolieren.

Ahja: data und numbits sind daten resp. Anzahl bits, bitindex beginnt 
bei null. Fürs "flushen" der letzten feststeckenden Bits musst Du Dir 
noch 'n Signal reinbauen.
1
#define PUTBITS    \
2
{    \
3
    bits_in_next_word = (int16_t) (bitindex + numbits - 32);    \
4
    if (bits_in_next_word < 0)    \
5
    {    \
6
        lcode = (lcode << numbits) | data;    \
7
        bitindex += numbits;    \
8
    }    \
9
    else    \
10
    {    \
11
        lcode = (lcode << (32 - bitindex)) | (data >> bits_in_next_word);    \
12
        STUFF(lcode);   \
13
        lcode = data;    \
14
        bitindex = bits_in_next_word;    \
15
    }    \
16
}

Viel Erfolg,

- Strubi

von Cihan K. (lazoboy61)


Lesenswert?

Strubi schrieb:
> Moin,
>
> weiss nicht, ob's hilft, aber ansich musst Du nur untenstehenden C-Code
> in VHDL giessen, allerdings mit einer grösseren Bitbreite für Deinen
> Fall (hier nur 32).
> Das geht mit 2 oder 3 Zyklen Latenz, je nach Durchsatzanforderungen.
>
> Der Code ist aus einer JPEG-Implementation. Die VHDL-Version kann ich
> leider nicht posten. Aber Huffman-Coder sollten sich diverse in
> verschiedenen JPEG-Encodern finden lassen. Würde den mal als separate
> Entity synthetisieren um das Problem zu isolieren.
>
> Ahja: data und numbits sind daten resp. Anzahl bits, bitindex beginnt
> bei null. Fürs "flushen" der letzten feststeckenden Bits musst Du Dir
> noch 'n Signal reinbauen.
>
>
1
> #define PUTBITS    \
2
> {    \
3
>     bits_in_next_word = (int16_t) (bitindex + numbits - 32);    \
4
>     if (bits_in_next_word < 0)    \
5
>     {    \
6
>         lcode = (lcode << numbits) | data;    \
7
>         bitindex += numbits;    \
8
>     }    \
9
>     else    \
10
>     {    \
11
>         lcode = (lcode << (32 - bitindex)) | (data >>
12
> bits_in_next_word);    \
13
>         STUFF(lcode);   \
14
>         lcode = data;    \
15
>         bitindex = bits_in_next_word;    \
16
>     }    \
17
> }
18
>
>
> Viel Erfolg,
>
> - Strubi

Ich habs auch in Delphi umgesetzt. Da geht es ja dann nicht um Timing 
(grob gesehen), wo ich hier in VHDL probleme bekomme.

Eigentlich habe ich versucht genau nach diesen Schema zu programmieren, 
Bits auffüllen, dementsprechend Platz machen, wenn eine bestimmte Menge 
gefüllt wurde, abladen, wieder umfüllen + auffüllen, wieder Platz machen 
für die Bits, usw.

Eigentlich geht es mir in diesen Thread wirklich nur darum, wie man so 
etwas in VHDL am besten umsetzen sollte. Ich hab sachen wie shifter 
probiert (shift_left), doch leider mit Timing Fehlern. Oder auch ganz 
einfache Schieberegister, allerdings mit einer Breite von 128 Bits, 
welches wieder in der Synthese einfach zu lange Zeit braucht. Im groben 
noch nichts brauchbares.

Mit welcher Technik, mit welchen Verfahren sollte man denn am besten 
Bitstroms erzeugen. Ich bin langsam am verzweifeln.

Zu Not muss ich alle Daten zwischenspeichern, gemühsam alles durchführen 
und den Bitstrom erzeugen. Mein Problem dabei ist aber, dass ich 
zyklisch Daten bekomme (Bilddaten von einer Kamera alle 1,6 ms) und ich 
dabei nicht alle Zeit der Welt habe.

Cihan

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

Cihan Kalayci schrieb:
> René D. schrieb:
>> Muss Bit_size nicht eine Konstante sein?
>
> Bit_Size wird in jedem Takt aktualisiert, er gibt ja an wie viele Bits
> gerade in der Ziwschenvariable Data_Stream gültig sind.


i_USER_FIFO_DIN <= DATA_STREAM((BIT_SIZE - 1) DOWNTO (BIT_SIZE - 64));

ist dein Code überhaupft fitbar?

Ich bin mir sehr sicher, dass BIT_SIZE eine Konstante sein muss. Da 
dieser Ausdruck nicht durcn den Fitter geht.

DATA_STREAM((BIT_SIZE - 1)

Sowas hatte ich auch bereis aus probiert und das ging nicht.
Welchen Fitter benutzt du?

Das ist mal eine Frage an den Lothar, wie hier der Stand der VHDL ist?
Ist interessant, man kann auch was dazu lernen.





Ich habe mich mit decodieren mal beschäfftigt.

An der Stelle hatte ich es wie folgt gelöst.
Das Schiebe register war doppelt so breit wie der Fifo.



Fifo
------<--------
      deocoder

Ein Pointer hat auf das forderste gültige bit gezeigt.
Und wenn das gülte bit die Fifo Breite überschritten hat wurden die 
Daten aus dem Schieberegister entnommen. Die Position der Entnahme gibt 
der Pointer an.

von Cihan K. (lazoboy61)


Lesenswert?

René D. schrieb:
> Sowas hatte ich auch bereis aus probiert und das ging nicht.
> Welchen Fitter benutzt du?

Was meinst du denn mit Fitter?

René D. schrieb:
> Ich habe mich mit decodieren mal beschäfftigt.
>
> An der Stelle hatte ich es wie folgt gelöst.
> Das Schiebe register war doppelt so breit wie der Fifo.
>
>
>
> Fifo
> ------<--------
>       deocoder
>
> Ein Pointer hat auf das forderste gültige bit gezeigt.
> Und wenn das gülte bit die Fifo Breite überschritten hat wurden die
> Daten aus dem Schieberegister entnommen. Die Position der Entnahme gibt
> der Pointer an.

Eigentlich habe ich es genauso gemacht wie du es geschrieben hast. Was 
hast du den mit den übrigen Bits gemacht? und wie hast du die Bits 
nacheinander in den doppelt so breiten register geschrieben?

Ich versuch mal noch einmal ein Beispiel darzustellen, wie es bei mir 
aktuell aussieht.

Cihan

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

doch leider mit Timing Fehlern. Oder auch ganz
einfache Schieberegister, allerdings mit einer Breite von 128 Bits,
welches wieder in der Synthese einfach zu lange Zeit braucht.

Es ist ja in Grunde auch kein reines Schieberegister mehr es wirdnach 
links weggespeichert und das Schieberegister kann zwischen 0 und 64 bit 
weit hüpfen.
Da kommen eine Menge Leitungen zusammen. vor jedem Reigster muss ein 
64bit breiter Multiplexer realisiert werden.

Was für eine Kamera hast du, die 64bit erzeugt?
Typisch sind 12bit Farbtiefe pro Pixel.
12bit und 64bit das sind Entfernungen dazwischen


Huffman hat ein Problem man, kann icht vorhersagen wie weit die 
Schiebung sein wird, sonst könnte man parallelisieren.

von Cihan K. (lazoboy61)


Lesenswert?

So hier das Beispiel:

FiFo Input DIN ist 64 Bit groß.
Data Stream Schiebe Register (meine Zwischenvariable) ist 128 Bit groß

Nun kommen Daten an:
Bsp.: 33 Bits
Die 33 Bits werden in Data_Stream geschrieben

die nächsten Daten kommen: 44 Bits
Nun werden die ersten 33 Bits um 44 Stellen verschoben mit shift left, 
um für die nächsten 44 Bits Platz zu machen. Anschließend werden die 44 
Bits in Data Stream geschrieben. Nun habe ich 77 Bits in Data_Stream.

Richtig! jetzt muss ich die oberen 64 Bits in den Fifo schieben:
D.H. bit 76(77-1) bis 13(77-64) müssen in den Fifo rein, darum folgende 
Zeile:
i_USER_FIFO_DIN <= DATA_STREAM((BIT_SIZE - 1) DOWNTO (BIT_SIZE - 64));
Und mein Bit_Size ist ebend in diesem Fall Bit_Size, welches in jedem 
Takt verändert wird.
Bin aber noch noch fertig, nachdem die oberen 64 bits nun im Fifo sind 
müssen die letzen 13 Bits wieder geshiftet werden, da neue daten kommen 
und platz gemacht werden muss. z.B. kommen jetzt 24 neue Bits.
Also müssen die unteren 13 Bits um 24 Stellen nach links verschoben 
werden und die 24 neuen Bits kommen in Data_Stream rein.
Nun habe ich als Bit_size - WErt 37 Bits.

so geht es nun weiter bis ebend keine Daten mehr kommen.

Das was Rene D. mit pointer meinte ist bei mir Bit_Size.

Mein eigentliches Problem liegt aber darin, dass meine shift-Operationen 
Timing Fehler verursachen. Deswegen die Frage an dich Rene D., wie hast 
du den die Bits geshiftet  umsortiert  sortiert usw.?

Cihan

von Cihan K. (lazoboy61)


Lesenswert?

René D. schrieb:
> Was für eine Kamera hast du, die 64bit erzeugt?
> Typisch sind 12bit Farbtiefe pro Pixel.
> 12bit und 64bit das sind Entfernungen dazwischen

Ich habe eine Line Cam, die mir 12 Bit x 8192 Zeilen in 4 Sprekten 
liefert. Allerdings geht in die FFT nur 1 Sprektrum mit 12Bit x 8192 
Zeilen rein. Der Output der FFT wird nun skaliert und mit der 
Huffman-Tabelle verglichen. Die 64 Bit werden dann hier 
zusammengestückelt, es sind also keine Kameradaten, die 64 Bit meine 
ich.

René D. schrieb:
> Huffman hat ein Problem man, kann icht vorhersagen wie weit die
> Schiebung sein wird, sonst könnte man parallelisieren

genau das ist ja mein Problem :-(
muss doch aber irgendwie elegant zu lösen sein.?!?

Cihan

von Cihan K. (lazoboy61)


Lesenswert?

Cihan Kalayci schrieb:
> Und mein Bit_Size ist ebend in diesem Fall Bit_Size, welches in jedem
> Takt verändert wird.

Der Satz musste lauten:
Und mein Bit_Size ist ebend in diesem Fall 77, welches in jedem
Takt verändert wird.

sorry
Cihan

von Strubi (Gast)


Lesenswert?

Hi Cihan,

du musst u.U. einen 'Barrel shifter' von Hand implementieren, und zwar 
je einen mit "left shift" und einen "right shift", die gleichzeitig 
arbeiten.
Damit sollte zumindest der Syntheseschluckauf weggehen...
Die Probleme mit den Timings kamen bei mir auch, als ich als erstes mal 
ganz 'naiv' die Geschichte mit 1 clock-Delay implementiert hatte. Mit 
entsprechendem Pipelining solltest Du die 100 MHz hinkriegen (könnte 
allenfalls auf einem Spartan3 etwas knifflig werden).

Grüsse,

- Strubi

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

> Timing Fehler verursachen. Deswegen die Frage an dich Rene D., wie hast
> du den die Bits geshiftet  umsortiert  sortiert usw.?
>
> Cihan

Gute Frage
Ich habe gerade nachgeschaut.

Ich habe kein Schieberegister sonderen ein Ringspeicher. So werden die 
einzelnen Bits nicht verschoben sondern dem Schreiben ein Offset 
gegeben.
Der Code stamte von einem Decoder. Der Fifo schreibt in den 
Ringspeicher.
1
    case write_rot_pointer is
2
    when "00"=>  rot_buffer(7 downto 0)<= input_reg(15 downto 8);
3
    when "01"=>  rot_buffer(15 downto 8) <=input_reg (15 downto 8);
4
    when "10"=> rot_buffer(23 downto 16) <=input_reg(15 downto 8);  
5
    when "11"=>   rot_buffer(31 downto 24) <=input_reg(15 downto 8);
6
    when others=> null;
7
    end case;
8
    end if;
9
  end if;
10
end if;
11
end if;
12
end process;
13
 
14
process (barrel_pointer,rot_buffer)
15
   begin
16
      case to_integer(barrel_pointer) is
17
         when 0 => barrel<= rot_buffer (0 downto 0) &  rot_buffer (31 downto 17);
18
         when 1 => barrel<= rot_buffer (1 downto 0) &  rot_buffer (31 downto 18); 
19
         when 2 => barrel<= rot_buffer (2 downto 0) &  rot_buffer (31 downto 19);
20
         when 3 => barrel<= rot_buffer (3 downto 0) &  rot_buffer (31 downto 20);
21
         when 4 => barrel<= rot_buffer (4 downto 0) &  rot_buffer (31 downto 21);
22
         when 5 => barrel<= rot_buffer (5 downto 0) &  rot_buffer (31 downto 22);
23
         when 6 => barrel<= rot_buffer (6 downto 0)  &  rot_buffer (31 downto 23);
24
         when 7 => barrel<= rot_buffer (7 downto 0)  &  rot_buffer (31 downto 24);
25
         when 8 => barrel<= rot_buffer (8 downto 0)  &  rot_buffer (31 downto 25);
26
         when 9 => barrel<= rot_buffer (9 downto 0)  &  rot_buffer (31 downto 26);
27
         when 10 => barrel<= rot_buffer (10 downto 0) &  rot_buffer (31 downto 27);
28
         when 11 => barrel<= rot_buffer (11 downto 0) &  rot_buffer (31 downto 28);
29
         when 12 => barrel<= rot_buffer (12 downto 0) &  rot_buffer (31 downto 29);
30
         when 13 => barrel<= rot_buffer (13 downto 0) &  rot_buffer (31 downto 30);
31
         when 14 => barrel<= rot_buffer (14 downto 0) &  rot_buffer (31 downto 31);
32
         when 15 => barrel<= rot_buffer (15 downto 0);
33
         when 16 => barrel<= rot_buffer (16 downto 1);
34
         when 17 => barrel<= rot_buffer (17 downto 2);
35
         when 18 => barrel<= rot_buffer (18 downto 3);
36
         when 19 => barrel<= rot_buffer (19 downto 4);
37
         when 20 => barrel<= rot_buffer (20 downto 5);
38
         when 21 => barrel<= rot_buffer (21 downto 6);
39
         when 22 => barrel<= rot_buffer (22 downto 7);
40
         when 23 => barrel<= rot_buffer (23 downto 8);
41
         when 24 => barrel<= rot_buffer (24 downto 9);
42
         when 25 => barrel<= rot_buffer (25 downto 10);
43
         when 26 => barrel<= rot_buffer (26 downto 11);
44
         when 27 => barrel<= rot_buffer (27 downto 12);
45
         when 28 => barrel<= rot_buffer (28 downto 13);
46
         when 29 => barrel<= rot_buffer (29 downto 14);
47
         when 30 => barrel<= rot_buffer (30 downto 15);
48
         when 31 => barrel<= rot_buffer (31 downto 16);
49
         when others => null;    
50
      end case;
51
end process;

von Cihan K. (lazoboy61)


Lesenswert?

Mir ist grad etwas unklar.

Was ist der Unterschied zwischen den beiden Code-Ausschnitten:

Ausschnitt 1:
1
DATA_STREAM((VALID_BIT_SIZE_im - 1) DOWNTO 0) <= 
2
  VALID_DATA_im((VALID_BIT_SIZE_im - 1) DOWNTO 0);
3
DATA_STREAM((SZ_BIT_SIZE + VALID_BIT_SIZE_im - 1) DOWNTO VALID_BIT_SIZE_im) <= 
4
  SZ_re(16 DOWNTO 0);
5
DATA_STREAM((VALID_BIT_SIZE_re + SZ_BIT_SIZE + VALID_BIT_SIZE_im - 1) DOWNTO (SZ_BIT_SIZE + VALID_BIT_SIZE_im)) <= 
6
  VALID_DATA_re((VALID_BIT_SIZE_re - 1) DOWNTO 0);

Ausschnitt 2:
1
DATA_STREAM((VALID_BIT_SIZE_re + SZ_BIT_SIZE + VALID_BIT_SIZE_im - 1) DOWNTO 0) <= 
2
  VALID_DATA_re((VALID_BIT_SIZE_re - 1) DOWNTO 0) & 
3
  SZ_re(16 DOWNTO 0) & 
4
  VALID_DATA_im((VALID_BIT_SIZE_im - 1) DOWNTO 0);

Meiner Meinung nach sollte es keine Unterschiede geben. Bei dem ersten 
Ausschnitt stimmt das Ergebnis, aber bekomme Timing-Fehler und die 
Synthese dauert ziemlich lange.
Bei dem zweiten Ausschitt ist das Ergebnis zwar falsch, aber wenigstens 
keine Timing-Fehler und die Synthese läuft normal durch.

Die Bits von Data_Stream habe ich mir in Chipscope angeguckt, woraufhin 
ich die Unterschiede sah.

Cihan

von Cihan K. (lazoboy61)


Lesenswert?

René D. schrieb:
> case write_rot_pointer is
>     when "00"=>  rot_buffer(7 downto 0)<= input_reg(15 downto 8);
>     when "01"=>  rot_buffer(15 downto 8) <=input_reg (15 downto 8);
>     when "10"=> rot_buffer(23 downto 16) <=input_reg(15 downto 8);
>     when "11"=>   rot_buffer(31 downto 24) <=input_reg(15 downto 8);
>     when others=> null;
>     end case;

So weit ich sehe, hast du immer 8 Bit weise geschrieben?!?
Und anschließnd je nach pointer Position entsprechen die Bits 
weitergegeben.
Richtig?

Cihan Kalayci schrieb:
> Ausschnitt 1:DATA_STREAM((VALID_BIT_SIZE_im - 1) DOWNTO 0) <=
>   VALID_DATA_im((VALID_BIT_SIZE_im - 1) DOWNTO 0);
> DATA_STREAM((SZ_BIT_SIZE + VALID_BIT_SIZE_im - 1) DOWNTO VALID_BIT_SIZE_im) <=
>   SZ_re(16 DOWNTO 0);
> DATA_STREAM((VALID_BIT_SIZE_re + SZ_BIT_SIZE + VALID_BIT_SIZE_im - 1) DOWNTO 
(SZ_BIT_SIZE + VALID_BIT_SIZE_im)) <=
>   VALID_DATA_re((VALID_BIT_SIZE_re - 1) DOWNTO 0);
>
> Ausschnitt 2:DATA_STREAM((VALID_BIT_SIZE_re + SZ_BIT_SIZE + VALID_BIT_SIZE_im - 
1) DOWNTO 0) <=
>   VALID_DATA_re((VALID_BIT_SIZE_re - 1) DOWNTO 0) &
>   SZ_re(16 DOWNTO 0) &
>   VALID_DATA_im((VALID_BIT_SIZE_im - 1) DOWNTO 0);

Ich habe nochmal über Nacht überlegt, was der Unerschied sein kann.
Mit einem Beispiel lässt sich das wahrscheinlich besser erklären.
Nehmen wir an das "VALID_BIT_SIZE_re" und "VALID_BIT_SIZE_im" für beide 
Codeausschnitte die selben Werte haben, dann sollten die Ergebnisse auch 
gleich sein. Das Problem beim ersten Ausschnitt ist wahrscheinlich, dass 
ISE in der Synthese für die Variablen alle Möglichkeiten berücksichtigen 
muss. Im zweiten Ausschnitt gehen die Variablen ja gegen 0 ("...downto 
0"). Hier geht er ja von der rechten Seite aus gesehen bei Data_Stream 
von einem festen Wert aus (0). Im Ausschnitt 1 variieren die Index Nr. 
von Data_Stream.

Was ich aber nicht verstehe, warum ich unter dem Code von Ausschnitt 2 
falsche Ergebnisse habe. Als Bsp. mal kurz:
Nehmen wir an dass
VALID_DATA_re(15 DOWNTO 0) <= X"154B" und VALID_BIT_SIZE_re <= 14 bzw.
VALID_DATA_im(15 DOWNTO 0) <= X"0003" und VALID_BIT_SIZE_im <= 2 bzw.
SZ_re(16 DOWNTO 0) <= X"0480A" und SZ_BIT_SIZE <= 17 (einzige Konstante) 
ist.
Dann sollte das Ergebnis ja folgendes für Data Stream sein:
1
Data_Stream((14 + 17 + 2 - 1) DOWTNO 0)) <= "01010101001011" & "00100100000001010" & "11"; -- in Binär
2
Data_Stream <= X"0AA59202B"; -- in Hex
Doch ich bekomme folgendes zusammengestückelt:
1
Data_Stream((14 + 17 + 2 - 1) DOWTNO 0)) <= "000010101010010110000000000000011"; -- in Binär
2
Data_Stream <= X"0154b0003"; -- in Hex

das kann ich mir überhaupt garnicht erklären, wie er auf dieses Ergebnis 
kommt. Ich hab mir alle Signale in Chipscope angeguckt und auch diese, 
die ich ebend benannt habe, doch das Ergebnis ist ebend falsch.

habe ich einen Fehler drin, den ich nicht sehe?

Cihan

von SuperWilly (Gast)


Lesenswert?

Kannst du den in Echtzeit beobachteten Fehler simulieren?

von Cihan K. (lazoboy61)


Lesenswert?

SuperWilly schrieb:
> Kannst du den in Echtzeit beobachteten Fehler simulieren?

Der Fehler tritt in der Simulation nicht auf.

Simulation ist genauso wie ich es auch eigentlich erwarte.

Dort wird der Vektor auch richtig zusammengestückelt.

Der Fehler taucht nur in der Hardware auf (in Chipsope).

Cihan

von SuperWilly (Gast)


Lesenswert?

Hast Du in Echtzeit Fifo-Überläufe oder Unterläufe? Dock mal die 
entsprechenden Fifo-Flags an Chipscope ...

Hast du verschiedene Taktdomänen, deren Übergänge du nicht richtig 
behandelst?

von Cihan K. (lazoboy61)


Lesenswert?

Taktdomäne habe ich nicht, alles läuft unter 100MHz.

Der Teil mit dem Fehler den ich meine, hat mit dem Fifo noch nichts zu 
tun. Es wird einfach nur aus einem Bram Daten eingelesen (auch unter 
100MHz) und anschließend je nach Inhalt wird ein 128 Bit Register 
beschrieben. Und das beschreiben hier ist schon Fehlerhaft.

Die Fifo Flags sind auch in Chipscope drin, werden aber wie gesagt zu 
dem Zeitpunkt wo der Fehler auftritt noch nicht verwendet.

Cihan

von SuperWilly (Gast)


Lesenswert?

Du simulierst exakt die gleichen BRAM-Schreib- und Lesezugriffe?

von Cihan K. (lazoboy61)


Lesenswert?

SuperWilly schrieb:
> Du simulierst exakt die gleichen BRAM-Schreib- und Lesezugriffe?

Ja. Ich simiuliere in ISIM.

Alle Flags die in der Programmierung gesetzt werden, alle Register die 
beschrieben werden sind von Timing her genau gleich. Nur der Inhalt der 
Register (Data_Stream 128 Bit Zwischenspeicher) ist unterschiedlich.

Ich mache mal gleich Screenshots und versuche mal darzustellen was ich 
meine.

Cihan

von Cihan K. (lazoboy61)


Lesenswert?

Ich habe in meinem Projekt einen großen ROM für die FFT initialisiert, 
8192x12 Bit und zwei weitere RAMS (BRAM) für die Huffman-Tabelle, 
jeweils 1024x32Bit. Allein diese ROM und RAMS haben eine Zeilenanzahl 
von ca. 1000 Zeilen, da ich sie ja initialisiert habe. Kann sowas ISE / 
XST durcheinander bringen? Manchmal trifft er die Zeilennummer nicht, 
wenn er mich auf meine Fehler hinweist. Würde ihn so etwas stören?
Meiner Meinung nach sollte das ja kein Problem darstellen.

Cihan

von Duke Scarring (Gast)


Lesenswert?

Cihan Kalayci schrieb:
> Manchmal trifft er die Zeilennummer nicht,
> wenn er mich auf meine Fehler hinweist. Würde ihn so etwas stören?
Tritt der hier beschriebene Fehler dann auf, wenn die Zeilennummer 
geteilt wird und zum Teil auf der nächsten Zeile steht?
Wenn ja, dann ist das wahrscheinlich nicht die Ursache Deines 
eigentlichen Problems.

Duke

von Cihan K. (lazoboy61)


Lesenswert?

Der Fehler tretet dann auch in meinen Sourcecode auf.
Die Fehlerangabe ist schon richtig, manchmal trifft er die Zeilennummer 
nicht.

Cihan

von Cihan K. (lazoboy61)


Angehängte Dateien:

Lesenswert?

Hier die Screenshots die ich versprochen habe.

Habe einen weiten und nahen Screenshot von der Simulation in ISIM und 
der Hardwareimplimentierung mit Chipscope gemacht.

Habe auf allen Bilder einen roten Punkt gemacht. Der deutet auf den 
Fehler hin den ich meine. In dem Punkt wird der Inhalt anders. In den 
nahen Bildern kann man sehen, dass alle anderen Register vor dem 
beschreiben von Data_Stream sowohl unter ISIM als auch unter Chipscope 
die gleichen Inhalte in den Registern haben.

Cihan

von SuperWilly (Gast)


Lesenswert?

Erreichst Du denn mit Chipscope-Core die Timing-Closure?

von Cihan K. (lazoboy61)


Lesenswert?

Meinst du mit Timing-Clousure evtl. Timing-Fehler. Aktuell sind keine 
Timing Fehler drinne.

Cihan

von SuperWilly (Gast)


Lesenswert?

Nimm doch einfach mal eine einfache BRAM-Ansteuerung mit entsprechenden 
Schreib- und Lesezugriffen und mach dir deutlich, ob Chipscope das 
anzeigt, was du in der Simulation siehst. Nicht dass du falsche Annahmen 
bezüglich des BRAM-Timings hast ....

von Cihan K. (lazoboy61)


Lesenswert?

Ich speichere die Daten Stück für Stück in einem FIFO, der wiederum 
durch eine RS422 Routine ausgelesen wird und mir die gleichen Daten in 
Hterm ausgibt wie in CS. D.h. wenn ich in CS Fehlerhafte Daten habe, 
tauchen diese auch in Hterm auf.

Cihan

von Cihan K. (lazoboy61)


Lesenswert?

Nach längerer Zeit möchte ich mich mal mit meinem Ergebnis melden.

Am Anfang hatte ich ja versucht eine (sehr sehr große) Kombinatorik zu 
beschreiben, die auf einer 128 Bit Variable basiert. Leider hatte ich da 
viele Probleme in Hinsicht der Resourcenverwendung und des 
Timingverhaltens.

Habe im Anschluss das Design auf eine 64 Bit Variante umgebaut, was viel 
weniger Resourcen gebraucht hat und vor allem hatte ich keine 
Timingprobleme. Der Bitstrom wird nun über die Huffman-Tabelle korrekt 
erzeugt. Ich muss auch noch dazu sagen, dass ich viele IF ELSE Abfragen 
optimiert habe (anders beschrieben) sodass ich dadurch auch bisschen 
Resourcen sparen konnte. Letztendlich habe ich nun ein Design, dass 
30-40% des FPGA (VIRTEX 5) füllt.

Wollte den Thread nicht in der Luft hängen lassen.

Danke nochmals an alle Beteiligten für ihre hilfreichen Beiträge.

lg Cihan

von Joel (Gast)


Lesenswert?

Bekommst du denn jetzt die erhoffte Kompression?

von Joel (Gast)


Lesenswert?

Also welchen Kompressionsfaktor?

von Cihan K. (lazoboy61)


Lesenswert?

Ja die Kompression ist gelungen. Komme auf Kompressionsfaktoren bis ca. 
1,5 - 3. Die Kompressionsrate hängt natürlich von meinem Scale_Factor 
und der Huffman-Tabelle ab.

Cihan

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.