Forum: FPGA, VHDL & Co. std_logic_vector to integer


von Daniel R. (dan066)


Lesenswert?

Ich würde gerne einen 32-Bit Vektor in einen Integer umwandeln (range 0 
to 10). Und zwar so, dass überschüssige Vektor-Bits abgeschnitten werden 
und ich nicht die folgende Fehlermeldung bekomme:
1
vec <= (others => '1');
2
int_s <= to_integer(unsigned(vec));
3
4
Value -1 for int_s is out of range 0 to 10
Ich hätte gerne, dass in int_s die 10 steht.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Daniel R. schrieb:
> und ich nicht die folgende Fehlermeldung bekomme:
Wer bringt diese Fehlermeldung? Und welche Bibliotheken verwendest du?

> Und zwar so, dass überschüssige Vektor-Bits abgeschnitten werden
Naja, wenn du in einem 32-Bit-Vektor alle Bits setzt, dann ist der Wert 
eben ausserhalb dem Bereich von 0 bis 10. Da hilft es nicht mal 28 Bits 
abzuschneiden, denn selbst die verbleibenden 4 Bits ergeben den Wert 
15.

Zeig mal einen kompletten "Dreizeiler", der dein Problem auch bei mir 
aufweist. Die oberen Zeilen reichen da nicht aus, damit lässt sich dein 
"Fehler" nicht nachvollziehen...

: Bearbeitet durch Moderator
von Daniel R. (dan066)


Lesenswert?

Also ich benutze die Bibliotheken
1
library work;
2
      use work.all;
3
    
4
library ieee;
5
      use ieee.std_logic_1164.all;
6
  use ieee.numeric_std.all;
Das Problem ist, dass ich ein 32-Bit Speicherwort auslesen will (liegt 
am Eingang cnt meiner Komponente):
1
entity XYZ is
2
  generic ( CNTBITSMAX : integer := 32 );
3
  port(
4
    cnt  : in std_logic_vector(CNTBITSMAX - 1 downto 0);
5
    res  : in std_logic;
6
    clk  : in std_logic);
7
end XYZ;
Dann hab ich einen integer zum zählen (wird dann wohl zum Vektor 
werden):
1
signal cnt_val_s : integer range 0 to 10;
2
...
3
cnt_val_s <= to_integer(unsigned(cnt));
Im Modelsim-Simulator klappt das, aber nur bis der Wert cnt zu groß 
wird.
Dann kommt der Fehler:
Value -1 for int_s is out of range 0 to 10
In meinem Fall möchte ich wirklich, dass alles überschüssige 
abgeschnitten wird.

von berndl (Gast)


Lesenswert?

Daniel R. schrieb:
> Dann hab ich einen integer zum zählen (wird dann wohl zum Vektor
> werden):signal cnt_val_s : integer range 0 to 10;
> ...
> cnt_val_s <= to_integer(unsigned(cnt));
> Im Modelsim-Simulator klappt das, aber nur bis der Wert cnt zu groß
> wird.
> Dann kommt der Fehler:

Tja, auch hier ist wohl der Teil des Codes, der das Problem verursacht, 
nicht dabei...

HINT: Viele Leute machen irgendwo sowas wie 'cnt <= cnt + 1;' Und dann 
fragen sie ab, ob der Wert schon groesser als irgendwas ist... Deshalb 
vermeide ich 'integer' wo ich bloss kann und nehme 'unsigned' mit 
genuegend Bits. Ich weiss, da denken viele hier anderst, aber die 
'integer' sind schon mit Vorsicht zu geniessen wenn sie mit einem 
'range' versehen sind...

: Bearbeitet durch Moderator
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

berndl schrieb:
> aber die 'integer' sind schon mit Vorsicht zu geniessen
Du hast Recht. Man muss einfach nur genau aufpassen und dich das 
Verhalten von Signalen immer vor Augen halten.

Daniel R. schrieb:
> Im Modelsim-Simulator klappt das, aber nur bis der Wert cnt zu groß
> wird.
Konsequenz: zuerst Abfragen und danach zählen oder zurücksetzen...

von VHDL hotline (Gast)


Lesenswert?

Erzähl uns doch einfach mal, was das für Speicherwerte sind und was du 
mit dem counter vorhast. Evtl. kann man die Speicherwerte BCD-kodiert 
ablegen, dann hast du die Einer-/Zehnerdezimalstelle (oder man macht die 
BCD-Konvertierung beim lesen). Oder falls die Eingangswerte irgendeine 
Logik haben, das irgendwie geschickt auf den Speicher abbilden.

Falls das oben gezeigte deine vollständige entity-Deklaration ist, wird 
die ohne ein "out" wahrscheinlich von der Synthese wegoptimiert.

von Daniel R. (dan066)


Lesenswert?

Aber ich dachte es ist empfehlenswert Integers zu benutzen, da das 
Synthesetool dann die besten Optimierungen vornehmen kann.

Ich bin mir ziemlich sicher, dass der problemverursachende Code dabei 
ist.
Anderes Beispiel:
1
library work;
2
      use work.all;
3
    
4
library ieee;
5
        use ieee.std_logic_1164.all;
6
        use ieee.numeric_std.all;
7
8
entity E is
9
  port(
10
    input  : in std_logic_vector(31 downto 0);
11
    output : out integer range 0 to 10);
12
end E;
Darauf folgt:
1
output <= to_integer(unsigned(cnt)); -- Zeile 50
ModelSim beschwert sich nicht, solange input <= A ist. Ist input = B 
kommt die Fehlermeldung:
1
Fatal: (vsim-3421) Value 11 for output is out of range 0 to 10.
2
#    Time: 400 ns  Iteration: 0  Process: /test/line__50 File: C:/.../src/Test.vhd
3
# Fatal error in Architecture rtl at C:/.../src/Test.vhd line 50

von Duke Scarring (Gast)


Lesenswert?

Daniel R. schrieb:
> Ist input = B
> kommt die Fehlermeldung
Dann wird wohl B zu groß sein.
Entweder das ist gewünscht, dann ist aber der Bereich für output zu 
klein, oder es ist nicht gewünscht und der Simulator hat Dir eine 
Schwachstelle gezeigt.

Duke

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Daniel R. schrieb:
> output <= to_integer(unsigned(cnt));
Warum musst du eigentlich einen Zähler in einen Integer umwandeln? 
Üblich ist es, mit dem Integer zu zählen und dann als Port einen 
std_logic_vector zu nehmen...

von Fisch (Gast)


Lesenswert?

Naja, es sollte doch eigentlich klar sein, dass der Simulator meckert, 
wenn du einen größeren Wert zuweist als für das Signal festgelegt ist. 
Prinzipiell hast du also zwei Möglichkeiten:
1. Du musst sicherstellen, dass am Eingang nie ein größerer Wert als 10 
anliegt.(eher schlecht)
2. Du clippst den Wert bei 10.
z.B. so:
1
signal cnt_val_s : integer range 0 to 10;
2
...
3
if(cnt > 10) then
4
  cnt_val_s <= 10;
5
else
6
  cnt_val_s <= to_integer(unsigned(cnt));
7
end if;

von Daniel R. (dan066)


Lesenswert?

Das letzte Beispiel hatte nur den Sinn das Problem auf den Punkt zu 
bringen. Ich habe einen RAM und in dem steht ein Zähler-Startwert als 
32-Bit-Vektor. Mein Zähl-Integer ist unterschiedlich groß, je nach 
generic-Einstellung. Dem Zähler wird der 32-Bit-Wert aus dem RAM 
zugewiesen und dann zählt er runter bis 0. Wenn im RAM ein Wert > 
Zählerrange drinstand, ist das eben ein Fehler vom Benutzer (der wissen 
muss, dass alle Werte > Zählerrange abgeschnitten werden).

ISE baut mir das ja ohne Probleme so wie ich es haben will. Das XST 
erkennt die überschüssigen RAM-Bits und optimiert sie weg. Das heißt die 
Timingsimulation läuft super, nur die vor-Synthese-Simulation beschwert 
sich.

von Daniel R. (dan066)


Lesenswert?

Fisch schrieb:
> if(cnt > 10) then
> [/vhdl]
Das würde grundsätzlich funktionieren, passt aber gar nicht in mein 
Konzept. Erstmal ist mir ein < oder > Vergleich hardwaremäßig zu teuer. 
Viel schlimmer ist aber, dass die überschüssigen Bits in meinem RAM 
dadurch eine Daseinsberechtigung bekommen und nicht mehr wegoptimiert 
werden würden. Ich baue darauf, dass Bits in meinem Distrubuted-RAM 
wegoptimiert werden, wenn ich sie nicht benutze. Ich habe nämlich einen 
RAM aus 32-Bit-Vektoren und in den allermeisten Fällen benutze ich nicht 
alle 32-Bit (lege ich vor der Synthese fest). XST erkennt das und 
optimiert alles nicht benutzte weg. Wenn ich den gesamten 32-Bit-Vektor 
jedoch über den > Vergleich mit der 10 vergleiche, dann werden ja alle 
32-Bits des Vektors benutzt; nämlich für diesen Vergleich. Sie würde 
nicht mehr wegoptimiert werden.

von VHDL hotline (Gast)


Lesenswert?

Dein Problem ist also nur, dass dein integer für die Synthese begrenzt 
sein soll, während es für die Simulation unbegrenzt sein soll?
Dann deklariere den integer eben abhängig von Synthese oder Simulation 
unterschiedlich.

von Daniel R. (dan066)


Lesenswert?

Normalerweise möchte man doch genau das simulieren, was synthetisiert 
werden soll.

Ich muss wohl einfach aufpassen, dass ich bei der Simulation nur gültige 
Werte benutze. Nach der Synthese könnten dann auch gefahrlos ungültige 
(zu große) Werte benutzt werden. Da das einen Fehlerfall darstellt, ist 
das resultierende Fehlerverhalten der Hardware eben, dass Bits 
abgeschnitten werden.

von D. H. (fisch)


Lesenswert?

Oder du benutzt einfach für deinen Zähler eine Range von 0 bis 15, was 
auf den gleichen Ressourcenbedarf hinauslaufen sollte. Wenn du dann 28 
Bits abschneidest, sollte niemals ein Überlauf stattfinden.

von VHDL hotline (Gast)


Lesenswert?

Ich denke du kannst dir da eine böse Falle stellen. Das range 0 to 10 
eines Integers wird von der Synthese nicht unbedingt beachtet. Die 
Synthese geht meiner Meinung nach dann einfach davon aus, dass du dein 
Design so beschrieben hast, dass nur die Werte 0 bis 10 erzeugt werden 
können, allerdings wird vermutlich trotzdem etwas synthetisiert, was mit 
2^n bit (also range 0 to 15) umgehen kann oder zumindest nichts, was nur 
für range 0 to 10 funktioniert. Im besten Fall funktioniert es trotzdem, 
wie du es gewünscht hast. Im schlechtesten Fall ist das Verhalten deines 
Designs dann für manche Fälle unbestimmt.

von Schlumpf (Gast)


Lesenswert?

Die Synthese kann einen range 0 to 10 eben nur in 4 Bit Register 
abbilden.
Und mit 4 Bit ist dann ein theoretischer Range von 0 to 15 möglich.

Es bietet sich also an, den Range nicht auf "krumme" Werte zu begrenzen.

So wie ich dich verstehe, geht es dir darum, dass du über ein generic 
o.ä. die Breite deines Zählers vorgeben willst und darauf baust, dass 
die Synthese dann den Speicher auch entsprechend anpasst.

Ich würde nicht die Breite des Zählers vorgeben, sondern die Breite des 
Speichers in Bit also im Prinzip so:


DATA_WIDTH = 4
RAM_DATA: std_logic_vector (DATA_WIDTH - 1 downto 0)
COUNTER: integer range 0 to 2**DATA_WIDTH - 1

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

VHDL hotline schrieb im Beitrag #3965811:
> Das range 0 to 10 eines Integers wird von der Synthese nicht unbedingt
> beachtet.
Das wird insofern beachtet, als dass "nur" bis zum nächsten Bit 
"aufgerundet" wird, und nicht immmer die 32 Bit eines "vollen" Integers 
verwendet werden. Und natürlich enthält der dadurch entstehende Zähler 
jeweils ungültige Zustände.

Und wenn man sich vergegenwärtigt, dass ein Zähler von 0..8 eben schon 4 
Bits braucht und 7 ungültige zustände hat, wird schnell klar, dass es 
bei diesem Zähler einen "automatischen Überlauf" von 8 nach 0 oder von 0 
nach 8 nicht gibt. Denn binär kommt bei einem 4-Bit-Zähler aufwärts 
nach 8 die 9 und abwärts nach 0 die 15...

von Schlumpf (Gast)


Lesenswert?

Daniel R. schrieb:
> Value -1 for int_s is out of range 0 to 10
> In meinem Fall möchte ich wirklich, dass alles überschüssige
> abgeschnitten wird.

Du kannst nicht alles überschüssige einfach abschneiden. Es können keine 
Bits geteilt werden.
Du kannst nur an den Grenzen 2^n abschneiden

Das würde dann so gehen:
1
int_s <= to_integer(unsigned(vec(3 downto 0)));

Aber auch dann hast du die Grenze nicht bei 10 sondern bei 15.

Und wenn du deinen Integer auf 0 to 10 begrenzt und dann aber im 
Simulator mit 11 beaufschlagst, ist es nur korrekt, dass der Simulator 
sich beschwert.


Integer1 range 0 to 10 --> 4 Bit
Integer2 range 0 to 15 --> 4 Bit

Simulator schreibt 12 auf integer1 --> ERROR
Simulator schreibt 12 auf integer2 --> alles ok

Du hast ein 16 Liter Fass zur Verfügung. Sagst dem Simulator, dass es 
aber nur ein 10 Liter-Fass sei, versuchst dann, in der Simulation 12 
Liter reinzuschütten und wunderst dich, dass der Simulator sich wehrt.

Und was ist jetzt dein Lösungsansatz?
Aus dem 16 Liter Fass ein echtes 10 Liter-Fass zu machen? Dadurch wird 
dein Simulator auch nicht glücklicher, wenn er versucht, in dieses dann 
12 Liter zu schütten, oder?

Ganz ehrlich: So richtig verstehe ich nicht, wo das Problem ist oder was 
du erreichen willst.

von Daniel R. (dan066)


Lesenswert?

Dass ich undefinierte Zustände bekomme, stimmt natürlich. Ich denke, die 
beste Lösung ist wohl:
Schlumpf schrieb:
> DATA_WIDTH = 4
> RAM_DATA: std_logic_vector (DATA_WIDTH - 1 downto 0)
> COUNTER: integer range 0 to 2**DATA_WIDTH - 1

Was ich will ist, dass ich immer 32-Bit geliefert bekomme und damit 
einen Counter setzen will, der nur mit 4-Bits zählt. Die Synthese merkt, 
dass ich 28-Bits gar nicht verwende und optimiert sie weg.
Mein Problem war, dass der Simulator die nicht benutzten 28-Bits nicht 
wegoptimiert, sondern einen Error produziert, weil 28-Bits nicht in 
4-Bits reinpassen. Wobei das auch nur passiert wenn ich bei der 
Integerumwandlung versuche mehr als 4 Einsen in den 4-Bit-Counter zu 
stecken.
Nun werde ich mit einer generischen Bitzahl arbeiten. Die Integerrange 
ist eine 2er Potenz und bei der Integerumwandlung werden entsprechend 
viele Bits vom 32-Bit Eingangsvektor benutzt.

von Björn P. (bjrn_g)


Lesenswert?

Hm, wie wäre es damit?
1
int_s <= to_integer(unsigned(vec (3 downto 0)));

Oder ist das zu einfach?

: Bearbeitet durch User
von Daniel R. (dan066)


Lesenswert?

Björn G. schrieb:
> Oder ist das zu einfach?
Nein so mach ich das.

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
Noch kein Account? Hier anmelden.