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:
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...
Das Problem ist, dass ich ein 32-Bit Speicherwort auslesen will (liegt
am Eingang cnt meiner Komponente):
1
entityXYZis
2
generic(CNTBITSMAX:integer:=32);
3
port(
4
cnt:instd_logic_vector(CNTBITSMAX-1downto0);
5
res:instd_logic;
6
clk:instd_logic);
7
endXYZ;
Dann hab ich einen integer zum zählen (wird dann wohl zum Vektor
werden):
1
signalcnt_val_s:integerrange0to10;
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.
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...
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...
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.
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
librarywork;
2
usework.all;
3
4
libraryieee;
5
useieee.std_logic_1164.all;
6
useieee.numeric_std.all;
7
8
entityEis
9
port(
10
input:instd_logic_vector(31downto0);
11
output:outintegerrange0to10);
12
endE;
Darauf folgt:
1
output<=to_integer(unsigned(cnt));-- Zeile 50
ModelSim beschwert sich nicht, solange input <= A ist. Ist input = B
kommt die Fehlermeldung:
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
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...
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:
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.
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.
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.
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.
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.
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.
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
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...
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(3downto0)));
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.
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.