Ich muss einem VHDL-Vektor einen Wert zuweisen , der 64 Bit auslastet
und würde gerne die aus MATHCAD generierten Werte nehmen. Das sind
positive Dezimalwerte.
Bei der Zuweisung bekomme ich aber schon beim INIT einen ÜBerlauffehler:
signal rtm_wert : std_logic_vector(63 downto 0) <= std_logic_vector
(to_unsigned( 5030521883283424760,64));
Was könnte da falsch sein?
Wenn ich es mit CALC umrechne auf Bit und zuweise geht es:
signal rtm_wert : std_logic_vector(63 downto 0) :=
"100010111010000000000001111111111111111111100000000010111111000";
benutzt wird:
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
Kleine Korrektur, auch im CALC geht es auch nicht. Der Calc läuft da
auch über. Die Werte scheinen zu groß zu sein. Der hier z.B.
18445829279364155008. Da muss ich mal Rücksprache mit den Kollegen
halten, ob die überhaupt stimmen.
Der automatische erzeugte Code in Verilog sieht so aus:
64'd 5030521883283424760
64'd18445829279364155008
-gb- schrieb:> := statt <=
Da habe ich was falsches rauskopiert, es war kein Syntaxproblem.
So war es:
signal rtm_wert : std_logic_vector(63 downto 0) := std_logic_vector
(to_unsigned( 5030521883283424760,64));
response:
** Error: D:\rtm_generator\src\rtm.vhd(37): near "5030521883283424760":
(vcom-119) Integer value exceeds INTEGER'high.
Numerische (dezimale) Literale sind leider erstmal integer, bevor man
sie in unsigned(mein int) stecken kann.
Mit den Vektorvarianten x"AFFEC0FFEEDEADBEEF" (x für Hex) geht es aber.
Wenn man große Zahlen unbedingt dezimal schreiben will, könnte man die
Ziffern in ein Hexliteral gießen und die Umrechnung zur richtigen Zahl
schnell mal als Funktion schreiben. Da du intialisierst kostet das ja
keine Hardware.
Ja, könnte man, leider fehlt mir momentan der Ansatz, wie ich aus den
gegebenen Dezimalwerten gültige Zahlen mache, die ich zuweisen kann.
Ich könnte ja HEX nehmen, aber die laufe auch irgendwie über.
Der größte Wert für z.B. 3FFF...F ist 9223372036854775807
D.h. der 18445829279364155008 kann gar nicht in 64 bit passen.
Ich frage mich was der soll. Kann jemand diese Veriloganweisung
interpretieren? muss ich die 1 weglassen?
Tomse schrieb:> der 18445829279364155008 kann gar nicht in 64 bit passen.
Warum nicht? Das ist (unsigned) FFFC_BFFF_DA22_FA00. Da ist also schon
noch "Luft" bis FFFF_FFFF_FFFF_FFFF.
> Der größte Wert für z.B. 3FFF...F ist 9223372036854775807
Der höchste signed 64-Bit Wert 7FFF_FFFF_FFFF_FFFF entspricht der obigen
Dezimalzahl. signed FFFF_FFFF_FFFF_FFFF wäre dann ja -1. Und signed
1000_0000_0000_0000 sind -9223372036854775808.
Simon L. schrieb:> Numerische (dezimale) Literale sind leider erstmal integer
Und leider ist integer'high noch immer nur 2^31-1.
Der TO sollte mal die konkrete Fehlermeldung des Tools hier wiedergeben,
als die Experten stumpf raten zu lassen.
Wie in den Antworten zu sehen ist, kann es kein Überlauffehler sein, da
der bspw der Syntax falsch geschrieben ist.
Und natürlich ist zu klären, welches tool hier den Fehler schmeisst.
Simon L. schrieb:> Wenn man große Zahlen unbedingt dezimal schreiben will, könnte man die> Ziffern in ein Hexliteral gießen und die Umrechnung zur richtigen Zahl> schnell mal als Funktion schreiben. Da du intialisierst kostet das ja> keine Hardware.
Interessanter Ansatz, gefällt mir aber nicht so, weil ich ein gültiges
Hexliteral habe, das aber ohne Umrechnung (die man vergessen könnte
hinzuschreiben) falsch ist.
Als Umweg aus dem Problem, das INT'high nur 2^31-1 ist, könnte man
trotzdem mit Funktionen arbeiten aber vielleicht besser in der Form von
unendlich genauen Decimals. Das wäre in VHDL am einfachsten ein Array
vom Typ int jeweils mit range 0 to 9.
Dann überlädt man noch die Funktion to_unsigned mit einer eigenen für
diesen neuen Arraytyp und es sollte klappen, ohne das es gross anders
aussieht. Die Zuweisung müsste wohl dann etwa so gehen:
signal rtm_wert : std_logic_vector(63 downto 0) := std_logic_vector
(to_unsigned("5030521883283424760",64));
Hab ich etwas übersehen, das meiner Idee im Weg steht?
Christoph Z. schrieb:> Hab ich etwas übersehen, das meiner Idee im Weg steht?
Ja, den test mit einem Synthesetool.
Die haben sich oft zickig, wenn man standard-Funktionen nach
Gutsherrenart verbiegt aehm, overloaded. VHDL ist nicht C++.
Lothar M. schrieb:>> der 18445829279364155008 kann gar nicht in 64 bit passen.> Warum nicht? Das ist (unsigned) FFFC_BFFF_DA22_FA00. Da ist also schon> noch "Luft" bis FFFF_FFFF_FFFF_FFFF.
Tja, da stehe ich wohl komplett auf dem Schlauch. Ich habe das in den
CALC eingegeben und mich daran aufgehängt. Der rechnet aber auch signed,
wie mir scheint und hat noch andere Probleme, weil er vorn abschneidet.
Wenn ich dort z.B. die o.g. Zahl eingebe, druckt er mir binär das aus
11001100.11001010.00110011.00110011.00010011.00110011.00111000.01100
da fehlen also Stellen.
In der kleinen Ansicht sieht man die führenden Nullen.
Wenn ich deinen HEX eingebe, geht es: er bringt halt nur einen negativen
Wert.
Kennt jemand einen Rechner, der das nicht falsch macht?
Das andere Problem mit dem limitierten Integer habe ich verstanden.
Hatte ich auch übersehen.
Das Dumme ist wie gesagt, dass die Zahlen aus MATHCAD eben in Real
rauskommen und ich nur die Zahlen habe. Hex wäre super, das kann ich
zuweisen.
Tomse schrieb:> Lothar M. schrieb:>>> der 18445829279364155008 kann gar nicht in 64 bit passen.>> Warum nicht? Das ist (unsigned) FFFC_BFFF_DA22_FA00. Da ist also schon>> noch "Luft" bis FFFF_FFFF_FFFF_FFFF.
ich glaub', Lothar (oder sein Taschenrechner) hat sich da verrechnet.
Das ist tatsächlich (jedenfalls nach meiner Rechnung)
FFFC_BFFF_D800_0680.
Recht hat er trotzdem.
Ja, ich denke, die Zahlen stimmen. Die Hinternisse sind offenbar INT im
VHDL und im PC, die das limitieren. Interessante Erkenntnis.
Bleibt die Frage nach einem Window-Taschenrechner, der 64 Bit breite
Dezimalwerte korrekt und direkt in HEX umrechnet. Den CALC kann ich
nicht auf unsigned umstellen oder dazu bewegen mit dieser großen Zahl zu
rechnen.
Müsste man erst splitten, nehme ich an. Z.B. 8 Bit wegnehmen und die per
Hand in HEX umbauen.
Markus F. schrieb:> Da schreibt man einfachsignal rtm_wert : std_logic_vector(63 downto 0)> := std_logic_vector(unsigned'(64d"5030521883283424760"));> und hat kein Problem mit "verkrüppelten" 32 Bit Integern.VHDL 2008 ist die Lösung! Danke!
Tomse schrieb:> Ja, könnte man, leider fehlt mir momentan der Ansatz, wie ich aus den> gegebenen Dezimalwerten gültige Zahlen mache, die ich zuweisen kann.
So zum Beispiel (die Routine ist signed und muss deswegen ein Bit mehr
haben als 64):
Tomse schrieb:> Bleibt die Frage nach einem Window-Taschenrechner, der 64 Bit breite> Dezimalwerte korrekt und direkt in HEX umrechnet.
Ich nehme gerne SpeedCrunch:
https://heldercorreia.bitbucket.io/speedcrunch/
Zum Rechnen kannst du binär und hex wie gewohnt eintippen. Potenz geht
wie in C oder in Python beides (^ oder **), constanten etc. gibt es
auch.
Die Resultate musst du auch nicht in HEX umrechnen, sondern zu schaltest
einfach die Basis um, in der die Resultate angezeigt werden (das geht
mit F4 bis F8).
Gibt es für übliche Betriebssysteme und läuft auch Portabel, wenn man
nix installieren darf.
>SpeedCrunch
Danke für den Tip, hab es unter Ubuntu installiert, ging problemlos.
Beitrag "Re: Hilbert Transformation im uC berechnen"
da hatte ich auch breitere Berechnungen benötigt als sie LibreOfficeCalc
erlaubt. Eine Zerlegung in Binärbrüche um ein IIR-Filter ohne
Multiplizierer in einem CPLD unterzubringen.
Sollwert: 0,161758498367701
LibreOfficeCalc aus Binärzahl: 0,161758423782885
mit Speedcrunch berechnet: 0,161758498288691
also fast 10 Stellen identisch, mit LibreOffice sind es nur 7. Der Rest
kann ein Rundungsfehler sein, da nur die ersten 32 binären
Nachkommastellen berücksichtigt sind.
Eingabe dazu in Speedcrunch (die Hilfefunktion ist gut verständlich):
dec(0b0,00101001011010010000000101000100)
Woraus definiert sich hier der "Sollwert"? Ist das die Realzahl und die
anderen die rückgerechneten Werte aus der zwischenzeitlichen
Transformation in Binär?
Ja genau, der Sollwert liegt dezimal vor, die anderen sind vom
Binärbruch auf dezimal zurückgerechnet.
Ich habe einen Text von 2001, darin sind 8 Koeffizienten für ein
IIR-Filter genannt. Die müssen noch quadriert werden, damit werden sie
doppelt so breit. Die Zahl 0,161758498367701 ist der kleinste quadrierte
Koeffizient.
Quadriert habe ich mit dem Gnome-Calculator, der rechnet mit bis zu 64
Bit, kennt aber keine Binärbrüche im Gegensatz zum SpeedCrunch.
Normalerweise wird dann in einem DSP oder Mikrocontroller damit
multipliziert. Ich habe aber einen anderen Text aus der Zeit, in dem ein
"multiplierless" IIR-Filter beschrieben ist, das so in ein CPLD passen
soll.
Dazu muss ich die 8 quadrierten Koeffizienten zu einer (hier auf 32 Bit
gerundeten) Summe von Binärbrüchen umformen. Dann braucht man nur noch
Addierer und Schieberegister, was (hoffentlich) weniger Platz im CPLD
braucht als 8 Multiplizierer mit mindestens 16 Bit Breite, oder
ersatzweise auch ein einziger Multiplizierer, der acht Berechnungen
nacheinander durchführt.
Ist denn überhaupt eine so hohe Auflösung nötig? Was passiert, wenn man
auf ein paar Bits verzichtet? Braucht die Anwendung diese Genauigkeit
oder ist es der Rechentechnik geschuldet, damit keine störenden
Artefakte entstehen? Man kennt solche Probleme z. B. bei
Potenzreihenentwicklungen, die bei unzureichender Näherung schnell ins
Oszillieren geraten.
Für Astronomie brauchte man sehr hohe Genauigkeiten, hieß es mal. Dafür
wurden Programmiersprachen entwickelt, die das unterstützten. Aber ich
vermute, dass man seinerzeit Auflösung und Dynamik nicht unterschieden
hatte. Ein Sonnensystem, dass Millionen Lichtjahre entfernt ist, da
kommt es doch wohl nicht mehr auf einen Zentimeter an.
Ich kann dazu nur den Artikel zitieren.
Beitrag "Re: Hilbert Transformation im uC berechnen"
das sind die beiden Texte, um 2001 als Zeitschriftenartikel und als
Kapitel in einem Buch erschienen. Damals waren programmierbare
Logikbauteile noch weniger komplex als heute, Multiplizierer in Hardware
noch selten enthalten.
In den Diagrammen sind jeweils (nur berechnet, nicht gemessen) die
exakte Kurve mit den auf vier dezimale Nachkommastellen gerundeten
Koeffizienten als durchgehende Linie gezeigt, und gestrichelt die mit
Binärbrüchen angenäherten, maximal auf die 6. binäre Nachkommastelle
gerundet. Wobei ich nicht weiß, wie die Binärzerlegung genau gemacht
ist.
Die Abweichungen kleiner als 1/10000 dB im Durchlass sind uninteressant,
aber eine Seitenbandunterdrückung von 55 oder nur 50 dB wären mit dem
Spektrumanalysator schon deutlich messbar.