Forum: FPGA, VHDL & Co. to_unsigned Wertebereich


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Armes FPGA im Wald (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Irgendwie stehe ich mit dem folgenden Ausschnitt VHDL code auf dem 
Schlauch:
type AntAr is array (3 downto 0) of unsigned(CTR_SIZE-1 downto 0);
  signal Bla_DP  : AntAr;

elsif( Bla_DP(I) < to_unsigned(2**CTR_SIZE-1, CTR_SIZE) )

CTR_SIZE ist ein Integer mit Wert 32.

Vivado quitiert dies mit der Fehlermeldung: [VRFC 10-1537] value 
4294967295 is out of target constraint range 0 to 2147483647

Eigentlich müsste ich mit 32 bit doch Werte von 0 bis 4294967295 
abbilden können (eben 2**32-1), das scheint aber nicht aufzugehen. Das 
erste Argument von to_unsigned wird ja offenbar korrekt ausgewertet, 
also ist entweder das zweite Argument (CTR_SIZE) oder die Bitbreite von 
Bla_DP zu klein. Kann mir jemand erklären welches und wieso?

von Gustl B. (-gb-)


Bewertung
-2 lesenswert
nicht lesenswert
Bei Vergleichen wie

elsif( Bla_DP(I) < to_unsigned(2**CTR_SIZE-1, CTR_SIZE) )

Kannst du das normal mit einer ganzen Zahl vergleichen. Und diese äußere 
Klammer muss da nicht hin.

elsif Bla_DP(I) < 2**CTR_SIZE-1 then

sollte also funktionieren. Zur Not eben der umgekehrte Vergleich, also

elsif Bla_DP(I) /= x"FFFFFFFF" then ...

Edit:
2**CTR_SIZE-1 ist größer als die maximal erlaubte Integer. Daher kann 
Vivado damit vielleicht nicht umgehen.

: Bearbeitet durch User
von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> 2**CTR_SIZE-1 ist größer als die maximal erlaubte Integer. Daher kann
> Vivado damit vielleicht nicht umgehen.

Exakt. Auszug aus numeric_std:
function TO_UNSIGNED (ARG, SIZE : NATURAL) return UNRESOLVED_UNSIGNED is
...

und natural'range ist 0 to integer'high. integer'high ist nun mal 
2**31-1, das wird so also nichts.

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Gehen denn diese Lösungen?

elsif Bla_DP(I) /= (Bla_DP(I)'range => '1') then
elsif Bla_DP(I) /= x"FFFFFFFF" then
elsif Bla_DP(I) < x"FFFFFFFF" then
elsif Bla_DP(I) /= (others => '1') then

Oder kann man das für einen Vergleich "<" auch nach unsigned wandeln?

elsif Bla_DP(I) < unsigned((Bla_DP(I)'range => '1')) then
elsif Bla_DP(I) < unsigned((others => '1')) then

von Markus F. (mfro)


Bewertung
-2 lesenswert
nicht lesenswert
Ein unsigned will man normalerweise zum Rechnen haben. Viele Funktionen 
in numeric_std rufen intern to_unsigned() auf (und werden deswegen 
genauso auf die Nase fallen).

Mit einem 33-Bit unsigned wird man auf Dauer deshalb wahrscheinlich 
nicht glücklich.

von Tim (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Markus F. schrieb:
> Gustl B. schrieb:
>> 2**CTR_SIZE-1 ist größer als die maximal erlaubte Integer. Daher kann
>> Vivado damit vielleicht nicht umgehen.
>
> Exakt. Auszug aus numeric_std:
> function TO_UNSIGNED (ARG, SIZE : NATURAL) return UNRESOLVED_UNSIGNED is
> ...
>
> und natural'range ist 0 to integer'high. integer'high ist nun mal
> 2**31-1, das wird so also nichts.

aber size ist doch die Vektorbreite und nicht der Wert.

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Ja, aber

Tim schrieb:
> TO_UNSIGNED (ARG, SIZE : NATURAL)

ARG ist ja mit

Armes FPGA im Wald schrieb im Beitrag #6234244:
> 2**CTR_SIZE-1

auch ein Integer und es ist zu groß.

von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
Armes FPGA im Wald schrieb im Beitrag #6234244:
> Eigentlich müsste ich mit 32 bit doch Werte von 0 bis 4294967295
> abbilden können (eben 2**32-1), das scheint aber nicht aufzugehen.

Das eigentliche Problem steckt in diesem Satz.

Der maximale Wertebereich eines 32-Bit Integers ist eben nicht 2**32-1, 
sondern nur 2**31-1 (also -2147483648 bis 2147483647). Entsprechend 
deckt ein natural eben nur den Bereich von 0 bis 2147483647 ab.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Armes FPGA im Wald schrieb im Beitrag #6234244:
> Eigentlich müsste ich mit 32 bit doch Werte von 0 bis 4294967295
> abbilden können (eben 2**32-1)
Das ist das unschöne am VHDL-Integer: es gibt keinen "unsigned long".

Und irgendwann im letzten Jahrtausend wurde mal festgelegt, dass der 
Wertebereich eines Integers beliebig sein kann, er aber mindestens 32 
Bits breit sein muss. Diese "Mindestforderung" ist daraufhin zur 
Normalität geworden, weil fast alle Rechner diese 32 Bit selbt 
verwendeten.

Kurioserweise ist in VHDL nicht mal -2**32 im garantierten 
Integer-Wertebereich enthalten, sondern es ist schon bei -2**32-1 
Schluss:
https://forums.xilinx.com/t5/Simulation-and-Verification/how-to-initialise-a-big-signed-or-unsigned-VHDL/td-p/676723

von Markus F. (mfro)


Bewertung
2 lesenswert
nicht lesenswert
Lothar M. schrieb:
> 
https://forums.xilinx.com/t5/Simulation-and-Verification/how-to-initialise-a-big-signed-or-unsigned-VHDL/td-p/676723

Das ist ein etwas anders gelagertes Problem (für das es eine Lösung 
gibt):
    signal lu           : unsigned(47 downto 0) := to_unsigned(2147483648, 48);
geht so nicht.

Aber so (VHDL 2008):
    signal lu           : unsigned(47 downto 0) := 48d"2147483648";

von Dussel (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Das ist das unschöne am VHDL-Integer: es gibt keinen "unsigned long".
In irgendeiner neuen VHDL-Version (VHDL-2020 oder 21?) soll aber der 
Integer endlich mal auf 64 Bit erweitert werden.

von Dussel (Gast)


Bewertung
0 lesenswert
nicht lesenswert

von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
Dussel schrieb:
> Lothar M. schrieb:
>> Das ist das unschöne am VHDL-Integer: es gibt keinen "unsigned long".
> In irgendeiner neuen VHDL-Version (VHDL-2020 oder 21?) soll aber der
> Integer endlich mal auf 64 Bit erweitert werden.

Selbst wenn das tatsächlich so ist, dauert's ab da dann wohl nur noch 20 
Jahre, bis die Software das vollständig unterstützt (VHDL 2008 z.B. ist 
längst noch nicht überall - um nicht zu sagen: nirgends - vollständig 
umgesetzt).

von Armes FPGA im Wald (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antworten. Ich habe es jetzt so gelöst:
elsif Bla_DP(I) /= x"FFFFFFFF" then

was ich eigentlich sehr unschön finde, da die Bitbreite jetzt nicht mehr 
über den Generic änderbar ist.
elsif Bla_DP(I) < unsigned((others => '1')) then

werde ich noch ausprobieren.

Ich bin im selben Code noch auf ein ähnlich gelagertes Problem 
gestossen:
if ((signed(ADC_D) > signed(Limit_D)) OR (-signed(ADC_D) > signed(Limit_D))) then

Mein Ziel ist es, zu überprüfen ob der ADC-Wert (signed integer) 
innerhalb eines gültigen Bereichs liegt (gegeben durch Limit_D, wird von 
einer CPU in ein 16 Bit Register geschrieben). Eigentlich wollte ich 
Limit_D als unsigned verwenden. Allerdings erlabut VHDL keine 
grösser/kleiner Vergleich zwischen signed und unsigned.
Beim obigen Code sieht man (Testbench sei Dank), dass der Vergleich 
schiefgeht wenn ADC_D den kleinsten negativen Wert annimmt: 0x8000 (16 
bit). Das ergibt für mich Sinn: die erste Bedingung ist ohnehin erfüllt 
(negativer Wert ist kleiner als positives Limit_D. Bei der zweiten 
Bedingung wird ADC_D negiert, was zum Overflow führt und somit -0x8000 
-> 0x8000. Somit sind beide Bedingungen falsch, obwohl der ADC am 
negativen Rand klebt.

Gelöst habe ich das dann so:
if ((signed(ADC_D) > signed(Limit_D)) OR (signed(ADC_D) < -signed(Limit_D))) then

Was in der Testbench mit den Extremwerten zu funktionieren scheint. Ist 
das akzeptabel oder habe ich das Problem jetzt einfach an eine andere 
Stelle verschoben? Das Limit_D nun positiv sein muss ist klar (die CPU 
darf keinen unsgined Wert in das Limit_D Register schreiben der zu gross 
ist, da das dann als negative Zahl interpretiert wird). Mir kommt die 
Lösung erneut unsauber vor.

Wir synthetisiert der Synthesizer in Vivado eigentlich einen 
grösser/kleiner Vergleich? Wird da ein Subtrahierer erzeugt und die 
Zahlen voneinander abgezogen um anhand des Vorzeichens des Resultats zu 
entscheiden?

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Markus F. schrieb:
> Das ist ein etwas anders gelagertes Problem
Mir gings da weniger um das Problem dort, sondern eher um die 
grundlegenden Ausführungen zum Integer... ;-)

> für das es eine Lösung gibt
Und auch diese Lösung ist eigentlich nur ein rostiger Notnagel.
Denn die simpleste "Lösung" wäre doch, wenn ein Integer eben nicht nur 
32 Bit breit sein würde. Sondern wenn dessen Breite z.B. per 
Anweisung/Schalter/Definition bis hin zu z.B. 256 Bits (das ist jetzt ja 
keine absurde Zahl und 64-Bit CPUs sind Alltag) gewählt werden könnte. 
Und dann ginge eben auch wie gewohnt "to_unsigned(2147483648, 48)". Wie 
gesagt: die Definition eines Integers gäbe das her.

Dussel schrieb:
> In irgendeiner neuen VHDL-Version (VHDL-2020 oder 21?)
Die dann 2023 vom Synthesizer unterstützt werden...  :-(
> soll aber der Integer endlich mal auf 64 Bit erweitert werden.
Der Integer muss nicht "erweitert werden". Der kann das schon seit 1987. 
Die Entwickler der Tools müssen das nur unterstützen. Da wird letztlich 
nur uralter Wein in neue Schläuche gefüllt und alle klopfen sich auf die 
Schulter.

> endlich mal auf 64 Bit erweitert werden.
Bitter. Ich hätte da für eine Norm, die wieder 10 Jahre gelten soll, 
mindestens das Vierfache erwartet. Damals im Jahre 1987 waren 32 Bits 
wie 256 Bits heute. Der GCC hat schon vor über 10 Jahren einen 128 Bit 
Integer-Datentyp definiert und kann damit auf 64 Bit CPUs sogar 
rechnen....

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Armes FPGA im Wald schrieb im Beitrag #6234898:
> Bla_DP(I) < unsigned((others => '1')) then
> werde ich noch ausprobieren.
Geht nicht, weil der der cast ja nicht 1. weiß, wie breit der Vektor 
sein soll und 2. nicht, welchen Typ er hat. Bestenfalls ginge das etwa 
so:
Bla_DP(I) < unsigned'(CTR_SIZE-1 downto 0 => '1') then

siehe http://www.lothar-miller.de/s9y/archives/82-Qualifier.html

: Bearbeitet durch Moderator
von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Bitter. Ich hätte da für eine Norm, die wieder 10 Jahre gelten soll,
> mindestens das Vierfache erwartet.

Ich hätt's ja hübsch gefunden, wenn wenigstens eins meiner Tools mit dem 
Xilinx-Vorschlag
    type int64 is range -2**63 to 2**63 - 1;
    signal i64              : int64 := 2147483648;

hätte umgehen können. Wird aber leider (weder von Quartus, Modelsim oder 
ghdl) verstanden und nur mit wirren Fehlermeldungen bedacht.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.