Ich habe mal eine einfache Frage zu Generics und muss mal ein wenig über
den Integer-Typ rum heulen ;-)
Als Beispiel mal ein einfaches Schieberegister, welches mitzählt wie
viel Bits geladen wurden. Das Schieben wird über das Signal shift_enable
aktiviert und das Register wird gleichzeitig darüber zurück gesetzt (ist
in Ordnung das so zu machen, oder?) :-)
-- Reset des Dateninhaltes fuer naechstes Schieben
34
ShiftReg<=(others=>'0');
35
-- Zaehler ruecksetzen
36
bit_ctr<=to_unsigned(0,bit_ctr'length);
37
endif;
38
endprocessShiftInData;
39
endBehavioral;
Alles ganz toll, oder?
Nur was ist, wenn ich jetzt z.B. RegWidth auf 32 setze? Mein bit_ctr ist
dann leider zu klein.
Wie macht man da normalerweise? Integer benutzen?
Jetzt kommt das Geheule über Integer-Typen :-)
Ich habe mittlerweile versucht so wenig Integer wie möglich zu nutzen,
da die hin- und her-Konvertiererei etwas nervig wurde. Außerdem werden
die Grenzen von Integer-Werten in ISim z.B. nicht geprüft, in ModelSim
aber schon. Außerdem will man ja oftmals einen Überlauf haben (der sich
mit Unsigned-Werten viel schöner beschreiben lässt).
Ein anderes Problem mit Integern habe ich, wenn ich z.B. einen 4-Bit
Unsigned habe, den ich in einen Integer konvertieren will, der nur einen
Range von 0 bis 12 hat. Jetzt kann es unter Umständen mal vorkommen,
dass ein 4-Bit Wert >12 verarbeitet wird (was aber für die Funktion egal
ist). Da gibt die Simulation in ModelSim natürlich auch einen Fehler
aus.
Natürlich könnte ich den Integer-Bereich jetzt auch erweitern. Aber
genau so gut kann ich eigentlich auch gleich komplett Unsigned-Typen
verwenden.
Außerdem passiert es schnell mal, dass man einen Integer z.B. mit Range
"0 to 32" beschreibt, obwohl man eigentlich Range "0 to 31" meinte (weil
evtl. nicht immer sofort 100% klar ist wie viel Bits für den Integer
drauf gehen).
Also irgendwie mag ich Integer nicht so gerne - berechtigt oder bin ich
zu doof? :-)
Und wie sieht die Lösung für das Generics-Problem aus?
Marius S. schrieb:> Nur was ist, wenn ich jetzt z.B. RegWidth auf 32 setze? Mein bit_ctr ist> dann leider zu klein.
Parametrisiere einfach die Größe von bit_ctr anhand der RegWidth. Du
brauchst ceil(log2(RegWidth)) Bits. Und sollte bit_ctr nicht eher ein
internes Signal sein?
Marius S. schrieb:> Mein bit_ctr ist dann leider zu klein.
Am einfachsten machst ma einen Zähler sowieso als eingeschränkten
Integer (solange der Zähler nicht weiter als bis 2.147.483.647 zählen
muss). Dann spart man sich auch dieses Rumgewürge beim Zurücksetzen des
Zählers.
Und das "Ausrechnen" des Zähler-Wertebereichs ist, naja, sagen wir mal:
unnötig
1
signalbit_ctr:integerrange0toRegWidth-1;
Einfacher und klarer geht es kaum...
Marius S. schrieb:> Ein anderes Problem mit Integern habe ich, wenn ich z.B. einen 4-Bit> Unsigned habe, den ich in einen Integer konvertieren will, der nur einen> Range von 0 bis 12 hat. Jetzt kann es unter Umständen mal vorkommen,> dass ein 4-Bit Wert >12 verarbeitet wird (was aber für die Funktion egal> ist). Da gibt die Simulation in ModelSim natürlich auch einen Fehler> aus.
Ist ja auch richtig: du selber hast den Wertebereich so definiert und
für richtig befunden. Der Simulator zeigt dir nur, dass da etwas anders
läuft als du dir gedacht hast. Er arbeitet nicht gegen, sondern für
dich... ;-)
> Jetzt kann es unter Umständen mal vorkommen, dass ein 4-Bit Wert >12> verarbeitet wird (was aber für die Funktion egal ist).
Dann ist der Wertebereich des Integers falsch definiert. Wenn es
passieren kann aber egal ist und keine Fehlfunktion auftreten
kann, dann musst du den Wertebereich schon so definieren, dass auch kein
Fehler angemeckert wird.
Aber es gibt eben Fälle, wo es nicht egal ist, wenn ein eingeschränkter
Wertebereich verlassen wird, weil z.B. abhängig von diesem Wert eine FSM
eine Weiterschltung vornimmt...
> Außerdem passiert es schnell mal, dass man einen Integer z.B. mit Range> "0 to 32" beschreibt, obwohl man eigentlich Range "0 to 31" meinte (weil> evtl. nicht immer sofort 100% klar ist wie viel Bits für den Integer> drauf gehen).
Halb so schlimm: der Synthesizer schmeißt dir das unnötige Bit raus und
weist dich darauf hin.
> Also irgendwie mag ich Integer nicht so gerne
Ich nehme für Zähler&Co nur wegen des eingeschränkten Wertebereichs bei
mehr als 31 Bit den Datentyp unsigned. Und das ist selten der Fall...
Lothar Miller schrieb:> Am einfachsten machst ma einen Zähler sowieso als eingeschränkten> Integer (solange der Zähler nicht weiter als bis 2.147.483.647 zählen> muss). Dann spart man sich auch dieses Rumgewürge beim Zurücksetzen des> Zählers.
Synthetisiert das denn zu effizienter Hardware? Ich meine in
"VHDL-Synthese" von Reichardt/Schwarz mal gelesen zu haben, dass Integer
generell nur eingeschränkt synthesefähig wäre und man damit äußerst
vorsichtig sein sollte. Ist das überholt und mit heutigen Tools kein
Problem mehr?
greg schrieb:> Synthetisiert das denn zu effizienter Hardware?
Es synthetisiert zur selben Hardware. Ob die effizient ist, steht auf
einem andern Blatt...
> Ich meine in "VHDL-Synthese" von Reichardt/Schwarz mal gelesen zu haben,> dass Integer generell nur eingeschränkt synthesefähig wäre
Findest du die Stelle nochmal? Das hast du sicher falsch aufgefasst.
> Ist das überholt
Es gab nie Probleme damit. Es kann nur dann holprig werden, wenn
ausschließlich uneingeschränkte Integer verwendet werden, denn dann
muss hinterher der Optimizer aufräumen. Und dann hagelt es Warnungen...
:-/
greg schrieb:> Synthetisiert das denn zu effizienter Hardware?
Ob du einen Zähler mit einem eingeschränkten Integer oder mit Unsigned
beschreibst hat keinen einfluss auf die generierte Hardware. Sowas haben
die Tools im Griff (und wäre auch schlecht wenn nicht).
Trotzdem, nicht alles ist Synthesefähig, das gilt ja für unsigned auch
:-)
Ich habe mir angewöhnt für diese Zwecke nicht integer sondern positive
zu nehmen (im Standard definierter eingeschränkter Integertyp von 1 bis
max. Integerwert). Wenn die 0 auch erlaubt sein soll, natural.
Damit niemand auf die Idee kommt, mir eine negative Zahl in den Generic
zu schreiben (an vielen Stellen würde nichts passieren, Fehler währen
warscheinlich mühsam zu suchen).
greg schrieb:> integer(ceil(log2(real(RegWidth))))-1
Na, wenn das mal nicht einfach und eindeutig ist :-)
Ein Package habe ich mir schon angelegt, hab auch eine einfache log2
Funktion für integers. Aber will eigtl. nicht für jede Kleinigkeit das
Package einbinden.
Lothar Miller schrieb:> Ich nehme für Zähler&Co nur wegen des eingeschränkten Wertebereichs bei> mehr als 31 Bit den Datentyp unsigned. Und das ist selten der Fall...
Und den Überlauf für die Zähler beschreibst du dann auch entsprechend
von Hand?
Marius S. schrieb:> Und den Überlauf für die Zähler beschreibst du dann auch entsprechend> von Hand?
Ja. Und der Syntesizer ist so schlau und macht da das Richtige draus.
Und ausserdem: nur ganz selten reicht ein Zähler mit implizitem Überlauf
aus. Meist muss der Zähler doch sowieso bei 13 oder 97 oder 135 oder
ähnlich unbinären Werten zurückgesetzt werden. Warum dann nicht einfach
alle Zähler gleich beschreiben?
Christoph Z. schrieb:> generic (> RegWidth : integer := 14>> Ich habe mir angewöhnt für diese Zwecke nicht integer sondern positive> zu nehmen (im Standard definierter eingeschränkter Integertyp von 1 bis> max. Integerwert). Wenn die 0 auch erlaubt sein soll, natural.>> Damit niemand auf die Idee kommt, mir eine negative Zahl in den Generic> zu schreiben
Man könnte das natürlich auch einfach so schreiben:
1
generic(
2
RegWidth:integerrange4to16:=14
3
);
Denn Natural und Positive sind ja auch nur eingeschränkte Integer:
Eine eigene Frage?
Dieser Thread ist über 12 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.