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;
Tomse schrieb: > signal rtm_wert : std_logic_vector(63 downto 0) <= std_logic_vector > (to_unsigned( 5030521883283424760,64)); := statt <=
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.
:
Bearbeitet durch Moderator
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: > Und leider ist integer'high noch immer nur 2^31-1 "Bald" nicht mehr. https://vhdlwhiz.com/vhdl-2019/#long-integers
Warum kein VHDL 2008? Da schreibt man einfach
1 | signal rtm_wert : std_logic_vector(63 downto 0) := std_logic_vector(unsigned'(64d"5030521883283424760")); |
und hat kein Problem mit "verkrüppelten" 32 Bit Integern.
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.
Beitrag #7272598 wurde von einem Moderator gelöscht.
Muss ja nicht zwingend ein Windows-kompatibler Rechner sein. https://www.wolframalpha.com/input?i=18445829279364155008+to+hexadecimal
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):
1 | library ieee; |
2 | use ieee.numeric_std.all; |
3 | use std.textio.all; |
4 | |
5 | entity large_decimals is |
6 | generic
|
7 | (
|
8 | BITS : natural := 65; |
9 | DEBUG : boolean := false |
10 | );
|
11 | end entity large_decimals; |
12 | |
13 | architecture sim of large_decimals is |
14 | |
15 | -- missing from numeric_std
|
16 | function "**"(num : signed; exp : signed) return signed is |
17 | variable result : signed(BITS - 1 downto 0); |
18 | variable e : signed(BITS - 1 downto 0); |
19 | begin
|
20 | result := num; |
21 | e := exp; |
22 | if e = 0 then return to_signed(1, BITS); end if; |
23 | l : loop |
24 | assert not DEBUG report "result=" & to_hstring(result) severity note; |
25 | e := e - 1; |
26 | if e = 0 then |
27 | exit; |
28 | end if; |
29 | result := resize(result * num, result'length); |
30 | end loop; |
31 | return result; |
32 | end function "**"; |
33 | |
34 | function to_dstring(s : signed) return string is |
35 | function to_dstring_recursive(s : signed) return string is |
36 | variable digit : character; |
37 | begin
|
38 | digit := integer'image(to_integer(s mod 10))(1); |
39 | if s / 10 > 0 then |
40 | return to_dstring(s / 10) & digit; |
41 | end if; |
42 | return to_string(digit); |
43 | end function to_dstring_recursive; |
44 | |
45 | variable digit : character; |
46 | begin -- to_dstring |
47 | digit := integer'image(to_integer(s mod 10))(1); |
48 | if s / 10 > 0 then |
49 | return to_dstring_recursive(s / to_signed(10, s'length)) & digit; |
50 | end if; |
51 | return to_string(digit); |
52 | end to_dstring; |
53 | |
54 | |
55 | procedure int64_read(variable ln : inout line; num : out signed; good : out boolean) is |
56 | constant dvals : string := "0123456789"; |
57 | variable c : character; |
58 | variable maxdepth : signed(BITS - 1 downto 0); |
59 | |
60 | --
|
61 | -- translate a single numeric ('0' - '9') into its integer equivalent.
|
62 | -- Return -1 if character isn't identified as valid numeric
|
63 | --
|
64 | function ival(c : character) return signed is |
65 | begin
|
66 | for i in dvals'range loop |
67 | if dvals(i) = c then |
68 | return to_signed(i - 1, BITS); |
69 | end if; |
70 | end loop; |
71 | -- if character isn't numeric
|
72 | return to_signed(-1, BITS); |
73 | end function ival; |
74 | |
75 | --
|
76 | -- check if character is a numeric.
|
77 | --
|
78 | function is_dec(c : character) return boolean is |
79 | begin
|
80 | return ival(c) /= to_signed(-1, BITS); |
81 | end function is_dec; |
82 | |
83 | --
|
84 | -- The recursive part of int64_read. Collects single digit's numerical values in
|
85 | -- string in a recursive descend until it hits a non-digit character.
|
86 | -- Then, on ascent of the recursive call, adds up all the collected digits
|
87 | -- multiplied by ther digit position's valence.
|
88 | --
|
89 | -- TODO: lacks any overflow checks.
|
90 | --
|
91 | impure function recursive_int64_read(depth : signed) return signed is |
92 | variable num : signed(BITS - 1 downto 0); |
93 | variable c : character; |
94 | begin
|
95 | -- peek into the line buffer to see if there is another numeric character
|
96 | if ln.all'length > 0 and is_dec(ln.all(ln.all'left)) then |
97 | read(ln, c); |
98 | num := ival(c); |
99 | assert not DEBUG report "digit = " & c severity note; |
100 | return recursive_int64_read(depth + 1) + num * |
101 | to_signed(10, BITS) ** |
102 | (maxdepth - depth); |
103 | else
|
104 | -- walk on, nothing to see here
|
105 | maxdepth := depth - 1; |
106 | return to_signed(0, BITS); |
107 | end if; |
108 | end function recursive_int64_read; |
109 | |
110 | begin -- int64_read |
111 | maxdepth := to_signed(0, maxdepth'length); |
112 | -- skip leading white space
|
113 | if ln.all'length > 0 then |
114 | skip_loop: for i in ln.all'range loop |
115 | if ln.all(ln.all'left) = ' ' or ln.all(ln.all'left) = HT then |
116 | read(ln, c); |
117 | else
|
118 | exit skip_loop; |
119 | end if; |
120 | end loop; |
121 | |
122 | -- call recursive part
|
123 | num := resize(recursive_int64_read(to_signed(1, BITS)), num'length); |
124 | -- error checking
|
125 | if maxdepth < 1 then |
126 | good := false; |
127 | else
|
128 | good := true; |
129 | end if; |
130 | end if; |
131 | end int64_read; |
132 | |
133 | begin -- architecture sim |
134 | p_initial : process |
135 | variable l : line; |
136 | variable s : signed(BITS downto 0); |
137 | variable good : boolean; |
138 | begin
|
139 | l := new string'("18445829279364155008"); |
140 | |
141 | int64_read(l, s, good); |
142 | |
143 | if good then |
144 | write(output, "result= " & to_dstring(s) & " (" & to_hstring(s) & ")"); |
145 | else
|
146 | write(l, "error reading from string " & l.all); |
147 | writeline(output, l); |
148 | end if; |
149 | wait; |
150 | end process p_initiaL; |
151 | end architecture sim; |
1 | result= 18445829279364155008 (0FFFCBFFFD8000680) |
:
Bearbeitet durch User
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)
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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.
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.