Hallo, Ich bin gerade dabei ein Coding- und Encoding Modul zu schreiben. Die Entity sieht folgendermassen aus: entity Huffman is Port ( CLKxC : in STD_LOGIC; RSTxRB : in STD_LOGIC; -- Initialization Signals ENAWRxC : in STD_LOGIC; ENARDxC : in STD_LOGIC; ADDRxC : in STD_LOGIC_VECTOR (31 downto 0); DATAxC : in STD_LOGIC_VECTOR (31 downto 0); -- Encoding/Decoding Signals NEXTxC : in STD_LOGIC;-- Indicates new DATA (DATAxC may be identical) ENCODExC : in STD_LOGIC; DECODExC : in STD_LOGIC; LENGTHxC : in integer range 0 to 5000; -- Output DATAOUTxC : out STD_LOGIC_VECTOR(31 downto 0)); end Huffman; Nun kriege ich in einem kombinatorischen Prozess folgenden Fehler: ERROR:HDLCompiler:463 - "/home/xxx/VHDL/Huffman/Huffman/Huffman.vhd" Line 170: if-condition is an event, not an edge Wieso stellt dies ein Problem dar? Es handel sich dabei um folgenden Abschnitt: elsif DECODExC = '1' and VALIDxC = '1' then ---->if DECODExC'event then v.dec_len := LENGTHxC; end if; -- Shift only when new data available if NEXTxC'event then v.dec_shift := v.dec_shift(31 downto 0) & DATAxC; v.dec_ptr := v.dec_ptr + 32; end if; Weiter oben hatte ich für den Encode Part if ENCODExC'event then was kein Problem darstellte? Ich bin etwas verwirrt. Ein kurze Design Frage: Wie würdet ihr das Problem lösen, dass evtl. nachfolgende Datenframes identisch sind und deswegen den Process nicht neu starten würden? Ich dachte ich nehme ein zusätzlich Signal NEXTxC, welches für neuen Daten triggert. Geht das nicht auch eleganter? Gruss, Florian
F. D. schrieb: > Hallo, > Mal ne blöde Frage vorweg, ist das nen reines Simulationsding oder willst du das später synthetisieren? ;-)
F. D. schrieb: > Hallo, > > Ich will es später synthetisieren und auf einem FPGA laufe lassen, > > Grüsse Puuh ich glaube dann hast du noch einen langen Weg vor dir. Auch wenn ich dir vermutlich nicht besonders helfe: 1) Ein 'event mit Signalen, die nicht der Clock entsprechen habe ich zumindest noch nie in einem synthetisierbaren Design gesehen. 2) Dazu scheinst du Variablen zu benutzen, was ansich auch vermieden werden sollte. 3) Und drittens sehe ich das ein Integer als Port, willst du später einen Integer-Wert auf einen FPGA-Pin legen? :-) Eine qualitativ höherwertigere Antwort gibts bestimmt noch von Lothar!
F. D. schrieb: > -- Shift only when new data available > if NEXTxC'event then > v.dec_shift := v.dec_shift(31 downto 0) & DATAxC; > v.dec_ptr := v.dec_ptr + 32; > end if; Da liegt der Hund begraben. Wie würdest du denn das aus TTL-Bausteinen aufbauen...? Siehste. Was du vermutlich meinst, ist sowas wie "NEXTxC = '1' and NEXTxC'event", also die Langform für "rising_edge(NEXTxC)". Falls du auf eine Änderung des Pegels wartest, musst du wohl mit einem Flipflop arbeiten; bedenke aber auch, dass der die Variante mit "'event" auch Wechsel von 'Z' oder sonstwas nach '1' erkennt. Das ist nicht immer gewünscht.
Hallo, danke erstmal für die Antworten. >1) Ein 'event mit Signalen, die nicht der Clock entsprechen habe ich >zumindest noch nie in einem synthetisierbaren Design gesehen. Dann müsste ich wohl das alte Signal zwischenspeichern, und damit vergleichen, als workaround? >2) Dazu scheinst du Variablen zu benutzen, was ansich auch vermieden >werden sollte. Wieso denn das? >3) Und drittens sehe ich das ein Integer als Port, willst du später >einen Integer-Wert auf einen FPGA-Pin legen? :-) Also schlussendlich krieg ich die Daten vom Ethernet Interface. Ein anderes Modul legt dann die Daten an. Ich kann ja auch einen Integer anlegen, nachdem ich den STD_LOGIC_VECTOR entsprechend konvertiert habe, oder nicht? >Da liegt der Hund begraben. Wie würdest du denn das aus TTL-Bausteinen >aufbauen...? >Siehste. >Was du vermutlich meinst, ist sowas wie "NEXTxC = '1' and NEXTxC'event", >also die Langform für "rising_edge(NEXTxC)". >Falls du auf eine Änderung des Pegels wartest, musst du wohl mit einem >Flipflop arbeiten; bedenke aber auch, dass der die Variante mit "'event" >auch Wechsel von 'Z' oder sonstwas nach '1' erkennt. Das ist nicht immer >gewünscht. Ich frage mich halt wie ich am besten dem Modul mitteile, dass jetzt neue Daten anliegen und diese entsprechend verarbeitet werden sollen? Hat da jemand eine elegante Idee? Grüsse, Flo
F. D. schrieb: > Ich frage mich halt wie ich am besten dem Modul mitteile, dass jetzt > neue Daten anliegen und diese entsprechend verarbeitet werden sollen? > Hat da jemand eine elegante Idee? Naja, mit einem Takt wäre sinnvoll. Aber dann brauchst du auch das ganze "'event" und " = '1'", oder alternativ "rising_edge()". Oder, was ich ja angedeutet habe, den letzten Pegel in ein Flipflop laden und den aktuellen Pegel damit vergleichen.
Synthesizer können heutzutage schon einiges: http://www.lothar-miller.de/s9y/archives/47-wait-im-Prozess.html Auch mit kuriosen Clock-Enable-Beschreibungen kommen sie klar: http://www.lothar-miller.de/s9y/archives/1-Clock-Enable-in-einer-ISE-VHDL-Beschreibung.html Aber das ist doch zuviel verlangt: F. D. schrieb: > elsif DECODExC = '1' and VALIDxC = '1' then > if DECODExC'event then > : > end if; > if NEXTxC'event then > : > end if; Erst Kombinatorik, dann noch 2 undefinierte Takte ('event ohne Pegelabfrage). Das ist brutal. Ich rate dir DRINGENDST, ein Buch anzusehen, das VHDL in Bezug zur Synthese stellt. Mein Tipp: VHDL-Synthese Reichardt&Schwarz > v.dec_shift := v.dec_shift(31 downto 0) & DATAxC; Anfänger und Variablen. Eine tolle Kombination... :-o Für dich mal der Hinweis auf den Klassiker: Beitrag "Variable vs Signal" O_o schrieb: > Eine qualitativ höherwertigere Antwort gibts bestimmt noch von Lothar! Passt schon... ;-)
F. D. schrieb: > Ich frage mich halt wie ich am besten dem Modul mitteile, dass jetzt > neue Daten anliegen und diese entsprechend verarbeitet werden sollen? > Hat da jemand eine elegante Idee? Du hast eine Datenquelle, die weiß wann sie neue Daten ausgibt. Üblicherweise hat man ein Signal, dass anzeigt, das die Daten zu einem bestimmten Moment gültig sind. Wenn diese Signal aktiv ist, verarbeitest du die Daten. Tom
>Erst Kombinatorik, dann noch 2 undefinierte Takte ('event ohne >Pegelabfrage). Das ist brutal. Ich rate dir DRINGENDST, ein Buch >anzusehen, das VHDL in Bezug zur Synthese stellt. >Mein Tipp: VHDL-Synthese Reichardt&Schwarz Der Pegel muss ja '1' sein, damit er überhaupt da reinkommt. Danke für den Tipp. >> v.dec_shift := v.dec_shift(31 downto 0) & DATAxC; >Anfänger und Variablen. Eine tolle Kombination... :-o >Für dich mal der Hinweis auf den Klassiker: >Beitrag "Variable vs Signal" Ich habe einen rein kombinatorischen Prozess mit Schleifen. Grob gesagt habe ich CE D Flip Flops, die Länge und Code für einen ASCII Char beinhalten. Zum Encoden greife ich über den index auf die jeweiligen Reigster zu. Beim Decoden vergleiche ich jeden Code mit dem Input. Hast du diesen Code Abschnitt wegen einem bestimmen Grund gequoted? Ich habe nun den Code angepasst, doch jetzt geht im während der Synthese der Arbeitsspeicher aus. Kann man Schleifen resourcenschonender schreiben? >Du hast eine Datenquelle, die weiß wann sie neue Daten ausgibt. >Üblicherweise hat man ein Signal, dass anzeigt, das die Daten zu einem >bestimmten Moment gültig sind. Wenn diese Signal aktiv ist, verarbeitest >du die Daten. Danke für den Tipp. Aktiv allein triggert ja den Prozess noch nicht. z.B. dieses aktiv Signal mit der Clock verunden? Besten Dank für die Input bis jetzt. Grüsse
F. D. schrieb: > Kann man Schleifen resourcenschonender schreiben? Schleifen erzeugen parallele Hardware. Eine 32er Schleife macht also 32 mal die selbe Hardware. Und ganz schlimm wird es, wenn auf Speicher mit einer Schleife zugegriffen wird, denn dann kannkein RAM verwendet werden, sondern der ganze Speicher muß mit Flipflops und evtl. LUTS aufgebaut werden. Für einen halbwegs anständigen Verriss: zeig doch mal deinen Code. ;-) > Danke für den Tipp. Aktiv allein triggert ja den Prozess noch nicht. > z.B. dieses aktiv Signal mit der Clock verunden? Takt verUNDen? Auweia... Mit der Denkweise, die du jetzt noch hast, wird dein Design sicher nicht sicher laufen. Hast du meinen Literaturhinweis gesehen? Nur zur Verdeutlichung: vom VHDL-Sprachumfang lasen sich bestenfalls 5% synthetisieren. Eher weniger...
Ich glaube du solltest dir einfach mal nen FPGA Eval Board mit LEDs und nen paar Tastern schnappen und dann: - einzelne LEDs über Taster zum leuchten bringen - Einen Zähler bauen und über LEDs ausgeben - Eine einfache State Machine bauen, über Taster Zustände wechseln und damit auch LEDs ansteuern - Eventuell mal nen kleinen UART bauen Das bringt dir wahrscheinlich tausend mal mehr Erkenntnis als das was du jetzt machst. Mir scheint es so als wenn du gleich von 0 auf 100 starten willst, obwohl du noch nie auf einem FPGA gearbeitet hast.
>Schleifen erzeugen parallele Hardware. Eine 32er Schleife macht also 32 >mal die selbe Hardware. >Und ganz schlimm wird es, wenn auf Speicher mit einer Schleife >zugegriffen wird, denn dann kannkein RAM verwendet werden, sondern der >ganze Speicher muß mit Flipflops und evtl. LUTS aufgebaut werden. Ich habe eine Bank von 256 32bit FF. Anbei habe ich meinen Code eingefügt. Die Idee ist zuerst die Flip Flops zu füllen mit den entsprechenden Codes, wobei index = 0 dem Codewort für ASCII Wert 0 entspricht. >Takt verUNDen? Auweia... >Mit der Denkweise, die du jetzt noch hast, wird dein Design sicher nicht >sicher laufen. Hast du meinen Literaturhinweis gesehen? >Nur zur Verdeutlichung: vom VHDL-Sprachumfang lasen sich bestenfalls 5% >synthetisieren. Eher weniger... Deswegen frage ich, wie das am besten gelöst werden könnte. >Für einen halbwegs anständigen Verriss: zeig doch mal deinen Code. ;-) Voila. Ich denke das Encoden passt soweit, doch das Decoden ist ziemlich schwierig, da ich nicht weiss, wieviele Codeworte ich pro 32bit vorfinde. Kann zwischen 1 und 11 varieren. Grüsse
F. D. schrieb: > Ich denke das Encoden passt soweit Denken kann fehlen! Ich glaube nicht, dass du das Design so in funktionierende Hardware gegossen bekommst. Denn da soll ja alles irgendwie GLEICHZEITIG passieren... :-o Und wenn das je klappt, dann ist das schnarchlangsam durch die vielen Logikebenen. Was mir SOFORT ins Auge sticht (und weshalb das Design so nie funktionieren wird), ist so was wie diese kombinatorische Schleife:
1 | HUFFMAN_PROC: process ( ENCODExC, DECODExC, VALIDxC, LENGTHxC, DATAxC, NEXTxC, BITISSETxC, STATExDP, huff) |
2 | :
|
3 | begin
|
4 | if ENCODExC = '1' and VALIDxC = '1' then |
5 | :
|
6 | elsif DECODExC = '1' and VALIDxC = '1' then |
7 | if NEXTxC /= v.next_old then |
8 | :
|
9 | v.dec_ptr := v.dec_ptr + 32; -- hier haben wir sie... |
http://www.lothar-miller.de/s9y/categories/36-Kombinatorische-Schleife Dieses Design wird ohne GRUNDLEGENDE konzeptionelle Änderungen nicht laufen. Hast du mal so "billige" Sachen wie ein Lauflicht und einfachere FSM realisiert UND analysiert? Und: wie wird da gespeichert? Richtig: mit einem Takt in einem D-Flipflop (meinetwegen mit Enable). Mit einem Takt wird ein neuer Zählerwert oder Zustand gespeichert. Bei dir fehlt jedesmal der Takt:
1 | v.enc_len := v.enc_len - 1; |
2 | :
|
3 | v.dec_ptr := v.dec_ptr + 32; |
4 | :
|
5 | v.dec_ptr := v.dec_ptr - MAX_CODE_LEN;--max_code_len; |
Und was gibt das dann? Unbrauchbare und undeterministische Latches.
Hallo Florian, du solltest Lothars Literaturvorschlag wirklich beherzigen. Mit ein paar Forumsbeiträgen wird man dir die fehlenden Grundlagen nicht beibringen können. Viele starten mit falschen Erwartungen (aus der Softwarewelt) in die Hardwareentwicklung mit HDL. Da wird einfach solange simuliert bis die Simulation das macht was man sich erhofft. Will man den Code aber irgendwann mal synthetisieren empfiehlt sich eine andere Sichtweise. Man stellt sich die Hardware am Anfang am besten wirklich auf Gatterebene vor und versucht erst dann diese Gatter mit einer HDL zu beschreiben. Später wenn man etwas routinierter ist, kann man dann auch so "Softwarekonstrukte" wie Variablen mit Bedacht einsetzen.
F. D. schrieb: >>Du hast eine Datenquelle, die weiß wann sie neue Daten ausgibt. >>Üblicherweise hat man ein Signal, dass anzeigt, das die Daten zu einem >>bestimmten Moment gültig sind. Wenn diese Signal aktiv ist, verarbeitest >>du die Daten. > > Danke für den Tipp. Aktiv allein triggert ja den Prozess noch nicht. > z.B. dieses aktiv Signal mit der Clock verunden? Ein Prozess beschreibt im entfernten das Verhalten eines D-Flip-Flops. Das ist auch nur auf den Takt sensitiv. Bei einer Flanke übernimmt es die Daten am D-Eingang. Jedes Signal, dem du in einem auf den Takt empfindlichen Prozess einen Wert zuweist, ist im FPGA ein D-FF (Register). Alle anderen Bedingungen landen als kombinatorische Logik in einer LUT deren Ausgang mit dem D-Eingang des FF verbunden wird. An diese Randbedingungen musst du dich halten, sonst wirst du nie ein stabiles Design bekommen. Tom
@ Florian > ist im FPGA ein D-FF (Register). Im FPGA gibt es (überschlägig gesagt) für deine eigenen Ideen nur Flipflops und LUTs (Kombinatorik). Und wenn du dir selber nicht vorstellen kannst, wie deine Beschreibung damit realisiert werden könnte, dann hast du noch die falsche Denkweise (üblicherweise so eine sequentielle C Denkweise). VHDL ist keine Programmiersprache, die man einfach Schritt für Schritt ohne Seitenwirkungen debuggen kann. Da sollte/muss schon vor der ersten Zeile das Konzept passen, und es darf eigentlich nur noch die Frage nach der erreichbaren Geschwindigkeit im Raum stehen...
Hallo, vielen Dank für die Vorschläge/Inputs bis jetzt. >Dieses Design wird ohne GRUNDLEGENDE konzeptionelle Änderungen nicht >laufen. Hast du mal so "billige" Sachen wie ein Lauflicht und einfachere >FSM realisiert UND analysiert? Und: wie wird da gespeichert? Richtig: >mit einem Takt in einem D-Flipflop (meinetwegen mit Enable). Mit einem >Takt wird ein neuer Zählerwert oder Zustand gespeichert. Bei dir fehlt >jedesmal der Takt: > v.enc_len := v.enc_len - 1; > : > v.dec_ptr := v.dec_ptr + 32; > : > v.dec_ptr := v.dec_ptr - MAX_CODE_LEN;--max_code_len; >Und was gibt das dann? Unbrauchbare und undeterministische Latches. Hier wird auch mit einem D FF gespeichert. Latches gibt es keine in diesem Code. Es sieht ja folgendermassen aus: huff_in -> | D FF | -> huff Im kombinatorischen Prozess wird dann v := huff. Wie daraus ein Latch entstehen soll sehe ich nicht, der Synthesizer übrigens auch nicht. >du solltest Lothars Literaturvorschlag wirklich beherzigen. Mit ein paar >Forumsbeiträgen wird man dir die fehlenden Grundlagen nicht beibringen >können. Ich werd mir das Buch bestellen. >VHDL ist keine Programmiersprache, die man einfach Schritt für Schritt >ohne Seitenwirkungen debuggen kann. Da sollte/muss schon vor der ersten >Zeile das Konzept passen, und es darf eigentlich nur noch die Frage nach >der erreichbaren Geschwindigkeit im Raum stehen.. Ich habe wohl ein falsches Design im Kopf für mein Problem. Mein Modul sollte folgendes machen: Ich habe einen variablen Huffman Code, mit einer (momentanen) Codelänge von 3 - 17 bit. Jedem ASCII Char (0 - 255) kann ein Code zugeordnet, falls er im Code Alphabet vorkommt. Nun habe ich zwei Untermodule: Encoden und Decoden. Encode: Macht einen Lookup auf ein BRAM, wo der Code gespeichert ist. Bspw: a -> 97 -> ram(97) => 1011 Decode: Hier wirds haarig, weil ich theoretisch über alle möglichen Codes vergleichen muss. Mit variabler Codelänge Am einfachsten und am schnellsten wäre es, wenn ich dies parallel machen könnte, was aber in einer riesen Logik resultiert. Wie würdet ihr so etwas lösen? Eine Frage zum for loop: Die Logik innerhalb eines for loops wird parallel ausgeführt, richtig? Wie kann ich etwas sequentiel ausführen lassen in einem for loop? Begreift der Compiler was ich will, oder macht er es sowieso parallel? ein Beispiel:
1 | for i in 0 to 3 loop |
2 | b(i) := a(i) + 1; |
3 | end loop; |
wird parallel ausgeführt, doch wie siehts bei
1 | for i in 0 to 3 loop |
2 | b := a + 1; |
3 | end loop; |
aus? Ist b am schluss a + 4, oder wird der loop weg synthetisiert und ich habe a + 1? Grüsse
Loops mit Variablen? Sorry, das hat nichts mehr mit Hardwareentwurf zu tun.
F. D. schrieb: > Decode: > Hier wirds haarig, weil ich theoretisch über alle möglichen Codes > vergleichen muss. Mit variabler Codelänge Am einfachsten und am > schnellsten wäre es, wenn ich dies parallel machen könnte, was aber in > einer riesen Logik resultiert. Wie würdet ihr so etwas lösen? Ich kann mich grob erinnern, dass es da eine gewissen Bildungsregel gibt. Sowas in der Art wie: 1. Nullen zählen bis zur ersten 1 (prefix) 2. Zwei oder drei Bits nach der nach der ersten 1 per LUT auswerten (Suffix) Dann hast du für verschiedene Prefixe jeweils ein ROM welcher Code bei welchem Suffix rauskommt. Und Zack hast du es in sagen wir zwei Takten, evt. nur einen, wenn deine Frequenzanforderungen nicht allzu hoch ist. Dazu gibts es doch sicher unmengen an Papern! Bist ja nicht der erste...
F. D. schrieb: > doch wie siehts bei > for i in 0 to 3 loop > b := a + 1; > end loop; > aus? Ist b am schluss a + 4, oder wird der loop weg synthetisiert und > ich habe a + 1? > > Grüsse a + 1. Aber du solltest Variablen wirklich sein lassen. Das hilft dir jetzt zum Einstieg sicher nicht weiter. > Loops mit Variablen? Sorry, das hat nichts mehr mit Hardwareentwurf zu > tun. Das kann man so allgemein nun auch nicht sagen. Hier zb eine kompakte Schreibweise um mehrere Busleitungen zu verUNDen (anstatt MUX zu verwenden)
1 | BusControl: process(IO_DataOutArrayxD) |
2 | variable io_data_out : dBusDataType; |
3 | begin
|
4 | io_data_out := (others => '1'); |
5 | for i in 0 to CFG_IO_SLAVES-1 loop |
6 | io_data_out := io_data_out and IO_DataOutArrayxD(i); |
7 | end loop; |
8 | |
9 | IO_DataOutxD <= io_data_out; |
10 | end process; |
Ich glaub du verwechselst da was... In Software habe ich einen Baum, den ich durchlaufe bis ich ein Blatt finde. Wie würde man eine Baumstruktur in VHDL machen? >Loops mit Variablen? Sorry, das hat nichts mehr mit Hardwareentwurf zu >tun. ?
F. D. schrieb: >>Loops mit Variablen? Sorry, das hat nichts mehr mit Hardwareentwurf zu >>tun. > > ? Variablen haben prinzipiell nichts mit Hardware zutun (sind eben ein Softwarekonstrukt), da hat er schon recht. Deshalb soll man sie nur einsetzen wenn man weiß was man tut... > In Software habe ich einen Baum, den ich durchlaufe bis ich ein Blatt > finde. Wie würde man eine Baumstruktur in VHDL machen Kannst du zur Not auch so in Hardware machen. Sequenziell als Statemachine.
Also ich denke man würde den Baum dann irgendwie abspeichern z.B. die Nodes nacheinander. 1 / \ 2 3 / \ / \ 4 5 6 7 ... Die Abfolge 00 würde dann den Node 4 ergeben, also vor der Sequence noch ne 1 hin, was dann eben 100/4 ergibt. Dann an den entsprechenden Addressen im Speicher den dazugehörigen ASCII Werte abspeichern und sonst auf 0 belassen. So könnte man dann Bit für Bit den Input durchgehen, bis man ein Blatt erreicht. Wie könnte man so etwas noch schneller hinkriegen?
F. D. schrieb: > Dann an den entsprechenden > Addressen im Speicher den dazugehörigen ASCII Werte Sowas nennt sich lookup-table kurz LUT. Duke
F. D. schrieb: > Im kombinatorischen Prozess wird dann v := huff. Wie daraus ein Latch > entstehen soll sehe ich nicht, der Synthesizer übrigens auch nicht. Richtig, das ist dieses VHDL-für-Softies-Programmiermodell von Jiri Gaisler. Wie es hier in der Gegend so trefflich heißt: D'Katz mag Mäus, i mags it... ;-)
huffman decoder gibt es auch bei opencores.org
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.