Hallo. Ich habe momentan eine Problemstellung mit deren eigenen Lösung ich nicht so ganz zufreiden bin. Evtl hat eibner von euch ja eine elegantere Lösung für mich. Ich habe einen Vektor der 256 Bit groß ist. Der Vektor ist Charakterischtisch immer so aufgebaut das zu beginn ein oder mehrere Nullen stelen. Gefolg werden sie von mehreren einsen und am ende stehen wieder nullen. Die Verhältnisse variieren aber immer. Es ist quasi ein Impuls mit variabler länge. Ich muss nun die Anzahl der einsen bestimmen. MEine Idee war nun, die Daten über ein Schiebegister in einen Seriellen Datenstrom umzuwandeln, und dann die anzahl der aufeinanderfolgenden einsen zu zählen. Das ist abllerdings eine sehr zeitaufwendige angelegenheit 256 bits zu schieben. Gibt es keine lösung, um die einsen im Vektor aufzuaddieren? Oder hat jemand eine ganz andere Idee?? Danke für eure Hilfe.
Du könntest alle Bits mit einem XOR zusammenschalten. Bei 256 bit kommt da aber eine Menge Logik zusammen. Die Laufzeiten dürften auch nicht unerheblich sein. ciao, Stefan.
Alle Bits XOR-verknüpft ergibt aber doch die Parität. Wie willst du damit auf die genaue Anzahl kommen? IMHO sollte das mit einem SR dessen Ausgang auf den EN-Eingang eines Zählers geht am einfachsten zu realisieren sein.
das ist doch endlich mal eine richtig schöne Frage mit unendlich vielen Realisierungsmöglichkeiten in VHDL, das ist ernst gemeint. Da kann man mal sehen, was in VHDL so geht, mit Schematics wäre das ziemlich umständlich. Die Funktion lässt sich komplett kombinatorisch realisieren, mit weniger als 40 Zeilen VHDL, ohne jedes Flip-Flop. Nachteil : extrem groß, also in diesem Punkt keine Konkurrenz zur SRG-Variante, dafür aber in knapp 200 ns fertig mit zählen ! Das Ding braucht 1285 (!) Logikelemente in einem Cyclone II, EP2C20F484, immerhin 6% von diesem Baustein, Details + Screenshot von der Simulation s. Anhang, m.E. ein gutes Bsp. für die Verwendung von Funktionen in VHDL PS: hier lässt sich sicher noch was optimieren, wenn man der Synthese etwas auf die Sprünge hilft, ich denke Reduktion auf 1/4 ist drin
Puh... super. Das ist eine gute Idee. Ich werde das gleich mal imlementieren. Ich hoffe ich oute mich jetzt nicht als absolutet noob, aber wie funktioniert die Übergabe von "din" in der entity zu "imp"? Verknüpft VHDL den ersten eintrag im funktionsaufrum mit dem ersten eintrag in dr entity? Oder schaut er welcher Vektor bei der größe in frage kommt?
din wird in Zeile 35 als Argument an die Funktion f1 übergeben (zugegeben ein blöder Name, man sollte da was sinnvolles nehmen), in f1 werden die 1sen gezählt und das Ergebnis als integer zurückgegeben. in Zeile 35 erfolgt dann gleichzeitig die Konvertierung zurück auf std_logic_vector. Bei der Wärme macht das aber schon 'ne Kiste Eis ;-)))
Das ist der Hammer. Ich denke ich muss noch ein bisschen üben, das ich das mal eben so aus dem ärmel schütteln kann. Respekt und Anerkennung. Na mal schauen wie ich das wieder gutmachen kann. Aber jetzt bin ich mir auch im klaren darüber, warum ich VHDL so interessant finde. Da kann man immer wiedr feststellen das 1001 wege nach Rom führen, und meine nie die beste ist :-)
@FPGA-user: wie würde sich der Resourcenverbrauch ändern wenn man deine Funktion splittet. Also man hat eine Funktion die nur 128 Bit zählen, dies ruft aber intern für zwei Teile a 64 Bit eine Funktion auf die nur 64Bit große Vektoren zählen, diese wiederum zweimal eine Funktion für 32Bit usw. usw. D.h. ein sogenanntes Binary Splitting. Ziel wäre es das der Fitter bei der Synthese nun die Möglichkeit bekommt gleiche Funktionsblöcke zu rationalisieren. Wäre sowas von Erfolg gekrönnt ? Gruß Hagen
@Hagen das wäre eine Variante der Optimierung. Gleiche Funktionsblöcke allein werden evt. nicht viel bringen. Meine Idee wäre, eine Funktion zu schreiben, die mit einer Look-Up Table 4 Input-Bits in eine 3 bit Binärzahl wandelt, das wären bei 256 bit = 64 Look-Up-Tables. Die 64 Ergebnisse müsste man dann mit einem Adder-Tree schrittweise auf das Endergebnis mit 9 bit aufaddieren. Das wären dann 32 + 16 + 8 + 4 + 2 + 1 = 63 Addierer mit jeweils 2 Eingängen, wobei sich die Bitbreite in jeder Addierer-Stufe um 1 erhöht. Nur so ne Idee, keine Ahnung wieviel LEs das am Ende bringt, die Synthese ist manchmal unergründlich.
Sorry, sind natürlich 3 * 64 = 192 Look-Up-Tables in der 1.Stufe - die Wärme ..........
Hm, ich habe nochmal drüber nachgedacht. Mein Vorschlag wird nichts bringen wenn man davon ausgeht das in parallel die kompletten 256 Bits mit einmal ausgerechnet werden müssen. Denn dann muß die Synthese immer ein Resultat bringen das die 256 Bits eben parallel berechnen. Wenn ich das richtig verstanden habe so arbeiten die Fitter immer mit den gleichen Regeln für die Optimierung von Boolschen Operationen. Ihre Matrix Optimierung findet immer die kompakteste Boolsche Verknüpfung für eine vorgegebene Formel. Ergo: sollte das Design komplett kombinatorisch gelösst werden müssen so meine ich das egal welcher VHDL Source benutzt wird immer fast identisch viele LE's drauf gehen werden. Erst eine synchron getaktete Lösung könnte den Resourcenverbrauch reduzieren, da dann immer Stückchenweise zb. 32Bits ausgewertet werden, dann aber eben in 8 Takte nacheinander. Gruß Hagen
Hi, ich bin zwar auch ein Anfänger, möchte aber meinen Senf auch noch dazugeben ;-) Wie wäre es 2 Zähler durchlaufen zu lassen? Einer von Vorne und einer von Hinten. Sobald beide eine '1' gefunden haben, kann man Hinten-Vorne berechnen und hat die Anzahl. Geht das? Wäre maximal 1/2 Laufzeit. 2. Optimierung (Laufzeit). Wenn ZHinten<ZVorne, dann Anzahl = 0 Grüße, André
Sobald du Zähler benutzt hast du ein synchrones Design und kein kombinatorisches. Die Laufzeit des kombinatorischen Design ist im Vergleich zu einem Synchronen -> sofort. Mal abgesehen von den Gatter Laufzeiten. Die obigen Vorschläge zielten immer auf ein kombinatorische Design ab, sprich man legt vorne 256 Bits an und hinten kommt über die verschiedenen Gatter sofort die Anzahl der gesetzten Bits raus. Meiner Meinung nach lässt sich das wirklich nur über ein synchrones Design, das somit mehrere takte benötigt, mit weniger Resourcen bewerkstelligen. Gruß Hagen
ja wenn es was umsonst gibt :-) also ich denke wenn man das in hardware realisieren will müsste man wirklich erstmal wissen wie viel zeit man für die auswertung verbrauchen darf. je nachdem wieviele takte zur verfügung stehen würde ich das signal entsprechend zerlegen und die einsen jeweils aufaddieren.
Hi, so. Nachdem ich wieder nüchtern bin und ausgeschlafen habe, möchte ich kurz anmerken daß meine Idee für die Tonne ist. Die verbraucht mehr Resourcen und ist im Worst-Case auch nicht schneller als ein Schieberegister. Vielleicht kann man was optimieren, wenn man weiß woher der Vektor kommt und mit welcher Länge der Impuls mindestens/höchstens vorliegt. Grüße, André
Hi ich bin es noch mal ... die anderen Zuweisungen habe ich wohl verstanden, aber was mir nicht klar ist, ist die Zuweisung von "din" zu "inp". Woher weiss die Funktion das "inp" die werte von "Din" repräsentiert? Ich sehe nirgendwo so etwas wie inp <= din oder so. Wenn mir das noch ein mal einer verklickern könnte... Danke
Ich frage auch so genau, da der Vektor mit den 256 Bit in meinem fall ein Signal ist und nicht in de entity enthalten ist. Daher habe ich bedenken ob das dann auch funktioniert. Deswegen wollt ich so genau wissen wie die Werteübergabe stattfindet.
das funktioniert schon, keine Angst, nimm einfach bitcount als Component in Deinen Code rein, leg das Signal an din an und das Ergebnis bekommst Du an sum_1 geliefert. wenn du schonmal z.B. in C programmiert hast, dann sollte das mit der Funktion nichts besonderes sein. Es wird eine Funktion deklariert, die einen Parameter übergeben bekommt. In der Funktion heisst dieser eben <inp>. Wie nun das Signal heisst, das Du beim Aufruf von f1 übergibst, ist völlig wurscht, Hauptsache es ist vom TYP den die Funktion erwartet ! Wo ich damals als Einsteiger viel länger fürs Verständnis gebraucht habe ist der Punkt, dass in der Funktion eine Loop mit einer Zählvariablen steht, in Hardware wird aber kein einziger Zähler, nichtmal ein Flip-Flop generiert ! Ich finde es extrem stark, dass man in VHDL Kombinatorik so abstrahieren kann !
Das geht ja leider nicht. Ich kann keinen 256 Bit großen Vektor in einem Stück an eine komponente übergeben. Dann meckert das webpack. In dem Design Summary steht bei boundet IOB maximum von 173. Deswegen habe ich diesen langen Vektor in einzelnen 32er blöcken die hinereinander getaktet werden übertragen. in diese Komponente werden die dann mit hilfe von addressen wieder aneinander . Somit steht mir der lange Vektor nicht in der entity zur verfügung, sondern nur als Signal, nachdem ich dn Vektor wieder zusammengebaut habe. Was kann ich denn da machen?
also steht der Vektor im FPGA komplett mit 256 bit zur Verfügung oder nicht ? JA) wo ist das Problem? NEIN) umso besser, dann schreib die Funktion einfach für 32 bit oder so um und addiere die Ergebnisse auf, dann brauchst halt 8 Takte bis das Ergebnis da ist aus Deinem letzten Satz hätte ich gefolgert, dass das Signal komplett vorhanden ist. Dann sind doch keine IOBs erforderlich oder was meinst Du mit IOB Maximum 173 ??? Dass der Vektor bei mir über IOBs rausgeht ist doch nur ein Besipiel, um mal schnell eine Synthese zu machen.
noch ne Idee, wenn da eine Beschränkung des WebPack vorliegt, dann kopier die Funktion doch in Deine Sourcen rein, an den Anfang der Architecture, und ruf sie dann einfach auf, warum geht das nicht ?(habe hier nur die ALTERA Software, kein WebPack)
Argh... jetzt hab ich es glaub ich verstanden... sorry das ich so generft hab. Ich schiebs einfach mal auf das Wetter :-) Danke ich denke es klappt nun :-)
Anbei mal mein Versuch eine teilsynchrone Lösung zu bauen. Du kannst im VHDL in den Generics alles konfigurieren. Über InputWidth die Größe des Input Vektors und über SliceWidth die Anzahl der Bits die aus dem Input Vektor pro Takt als kombinatorische Berechnung berechnet werden sollen. Interessant ist nun das du über SliceWidth die Synthese derart beeinflussen kannst das entweder wenige LE's verbraucht werden dafür aber mehr Takte benötigt werden, oder sehr viele LE's benötigt werden dafür aber die maximal möglich Taktgeschwindigkeit sich wieder reduziert. Man muß also tatsächlich eine Kompromiss finden zwischen LE Verbrauch und benötigter Zeit pro kombinatorische Berechnung. Je größer SliceWidth gewählt wird um so mehr LE's werden verbraucht und um so geringer muß die Taktfrequenz von Clock sein. Je kleiner SliceWidth gesetzt wird um so mehr Takte benötigt man, verbracht weniger LE's und die Taktfrequenz kann höher gewählt werden. Gruß Hagen
anbei mal ein Screenshot aus der Simulation von Quartus II mit SliceWidth := 16; Gruß Hagen
@Hagen nicht schlecht, da hast Du Dir einige Arbeit gemacht. Kleine Kritik sei erlaubt : Im Extremfall bei 1 bit SliceWidth dürfte bei Deiner Version ein 256 zu 1 Multiplexer rauskommen, für den Fall wäre ein Schieberegister vermutlich effektiver.
Ja, das dachte ich mir auch schon. Allerdings lässt sich so einigermaßen der Effekt von SliceWidth auf den Verbracuh von LE's und der nötigen Gatterlaufzeit der kombinatorischen Logik vergleichen. Ich werde sogar das Ding mal unter Xilinx WebPack und Quartus II für verschiedene FPGA's austesten, nur so zum Vergleich. Ansonsten noch Verbesserungen oder Kritiken ? ich bin auch nur Anfänger. Gruß Hagen
ansonsten top, ordentlicher Stil, alles schön eingerückt, einheitliche Notation, mit das beste VHDL, was ich so im Forum gesehen hab
Danke fürs Kompliment, die Sauberkeit entwickelt man nach 20 Jahren als Profiprogrammierer. Nur, leider hilft das bei der "Programmierung" von FPGA/CPLD nicht so viel weiter. Ich habe einige Programmiersprachen für normale PC's erlernt und dies ging eigentlich immer schneller. Der Einstieg auf FPGAs/CPLDs ist wohl in letzter Zeit das härteste Brot beim Erlernen einer neuen Programmiersprache für mich. Zb. mit obigem VHDL: alles fertig, alles schein logisch korrekt zu sein nur bei der Simlation zeigte sich das der Code die untersten 8 Bits des 256 Bit Inputs immer doppelt gezählt hat. Ich habe mindestens 4 Stunden benötigt um zu erkennen das meine Clockfrequenz schneller als die internen Gatterlaufzeiten waren ! Nach Reduktion der Taktfrequenz gings auf einmal. Ich hasse das wenn man in einer Programmmiersprache noch nicht routiniert ist und jedesmal bei Problemen wie der Ochse vorm Scheunentor rumgrübelt. Also nichts für ungut, guter Stil hin&her, aber das nützt nichts wenn man es immer noch nicht voll begriffen hat ;) Gruß Hagen
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.