Forum: FPGA, VHDL & Co. std_logic_vector als signed oder unsigned interpretieren


von Quecksilber (Gast)


Lesenswert?

Hallo Leute

welche Möglichkeiten, außer den folgenden, gibt es eine Zahl als 
unsigned zu interpretieren? Ich kenne drei. Die erste ist ein wenig 
krude:
1
positiv <= '0' & unbekannt;

Die zweite ist, alle relevanten Größen grundsätzlich als "signed" oder 
"unsigned" zu deklarieren.

Die dritte gehört eigentlich zur zweiten nämlich das casting unsigned().

Leider fallen die Möglichkeiten 2 und 3 bei mir aus, weil ich in 
derselben Architecture auch signed-Operationen durchführe und ich nicht 
IEEE.STD_LOGIC_ARITH.ALL und IEEE.STD_LOGIC_SIGNED.ALL verwenden kann. 
Die erste finde ich persönlich 1. ein wenig krude, 2. würde es "positiv" 
verbreitern, was auch unschön ist. (das soll nämlich später dividiert 
werden)

danke für eure Hilfe, bitte schreibt mir auch ein paar Worte, wenn es 
keine weiteren Möglichkeiten gibt.

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


Lesenswert?

Quecksilber schrieb:
> und ich nicht
> IEEE.STD_LOGIC_ARITH.ALL und IEEE.STD_LOGIC_SIGNED.ALL verwenden kann.
Das ist gut so.
Schmeiß diese alten Synopsys Libs STD_LOGIC_ARITH und ihre Anhänger 
STD_LOGIC_SIGNED und STD_LOGIC_UNSIGNED raus. Denn für diese Probleme, 
die du gerade hast, gibt es die NUMERIC_STD mit ihren Datentypen signed 
und unsigend und jeder Menge passender Casts und Konvertierungen:
http://www.lothar-miller.de/s9y/archives/14-Numeric_Std.html

von Quecksilber (Gast)


Lesenswert?

ok mach ich, danke für den Tipp und Link. Dann hab ich aber nochmal ne 
Frage: In welcher alternativen Lib sind die arithmetischen Operatoren 
definiert? Nur mit der IEEE.NUMERIC_STD.ALL komm ich da nicht weit.

von Queck S. (Firma: Uni) (kiigass)


Lesenswert?

Ok, streiche die letzte Frage. Aber dafür hab ich ne neue: Würde es dann 
nicht Sinn machen ausschließlich mit signed und unsigned zu arbeiten? 
Welche Verwendung findet dann noch der std_logic_vector?

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


Lesenswert?

Queck Silber schrieb:
> Aber dafür hab ich ne neue: Würde es dann nicht Sinn machen
> ausschließlich mit signed und unsigned zu arbeiten?
Für Berechnungen: ja, und mit Integer.
> Welche Verwendung findet dann noch der std_logic_vector?
Der wird ganz gern als "Standard-Datenübergabeformat" an den Ports 
verwendet.

von Queck S. (Firma: Uni) (kiigass)


Lesenswert?

ok, danke dir.

Leider hab ich ein paar anfängliche Probleme bei der Umstellung auf die 
neue Lib. Warum funktioniert das nicht mehr?
1
signal r : unsigned(7 downto 0);
2
...
3
if (r /= 0) then
4
...

da sagt mir mein Isim immer: "Instance /test/uut/ : Warning: 
NUMERIC_STD."/=": metavalue detected, returning TRUE"

von Christian R. (supachris)


Lesenswert?

Ist das auch zu jeder Zeit definiert? Also kein X, U oder sonstwas 
enthalten? Solche Warnungn gibts eigentlich nur bei X, U, Z... im 
Vektor.

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


Lesenswert?

Probiers mal mit einer Initialisierung des Signals:
1
signal r : unsigned(7 downto 0) := (others=>'0');

von Queck S. (Firma: Uni) (kiigass)


Lesenswert?

ok das Prob scheint tatsächlich zu sein, dass "r" plötzlich ein 'U' 
enthält, aber nur auf dem LSB. Das führt zu der Frage: Was genau machen 
die Casts signed/ unsigned? Verändern die die Bits in irgendeiner Weise?

von Christian R. (supachris)


Lesenswert?

Nö, die verändern nix. Ein U kommt von einem nicht intialisierten 
Signal. Das muss vor dem Cast schon nicht initialisiert sein.

von Queck S. (Firma: Uni) (kiigass)


Lesenswert?

hmm ok konnte das Prob lösen, war für mich anfangs etwas verwirrend, 
weil die alte Synopsis Lib immer meckert, wenn man ein 7 Bit breites 
Signal einem 8 Bit breiten zuordnen will. Die neue hat einfach das LSB 
auf 'U' gesetzt und den Rest zugeordnet.

Dennoch habe ich eine weitere Frage:
Angenommen ich habe:
1
signal t : signed (7 downto 0);
2
signal p : unsigned (7 downto 0);
3
signal r : unsigned (8 downto 0);
4
...
5
r <= t+p;

Dann sagt der Compiler, dass das nicht gehe. Wie kann ich also eine 
negative Zahl mit einer Positiven addieren? (p = 251, das MSB ist also 
'1')

PS:
ich hab auch schon das hier gefunden: 
http://www.mikrocontroller.net/articles/Rechnen_in_VHDL#Besser:_Rechnen_mit_numeric_std

aber das funktioniert bei mir nicht. Die Fehlermeldung ist diesselbe:
Line 50: found '0' definitions of operator "+", cannot determine exact 
overloaded matching definition for "+"
Es funktioniert nur, wenn ich eines der Signale entsprechend caste, aber 
dann hab ich doch nen anderen Wert oder nicht?

von Christian R. (supachris)


Lesenswert?

Bei einem signed Summanden muss die Summe natürlich auch signed sein. 
Wenn du sichergestellt hast, dass da kein negativer Anteil mehr drin 
ist, kannst du die natürlich nach der Summenbildung wieder nach unsigned 
casten. Außerdem müssen die Summanden die gleiche Breite haben wie die 
Summer, also erst mit Resize entsprechend erweitern.
1
r <= unsigned(resize(t, 9) + signed(resize(p, 9)));

könnte klappen...so aus der Hüfte geschossen...

von Duke Scarring (Gast)


Lesenswert?

Christian R. schrieb:
> Außerdem müssen die Summanden die gleiche Breite haben wie die
> Summer, also erst mit Resize entsprechend erweitern.
Laut [1] reicht es, wenn ein Summand die nötige Breite aufweist:
1
length of result = max(length of 1st par, length of 2nd par)

Das mit der Addition/Subtraktion ist m.E. in VHDL unschön gelöst. Bei 
der Multiplikation wird automatisch auf die richtige Bitbreite geachtet, 
bei der Addition muß man selber Platz für den Überlauf schaffen.

Duke

[1] http://www.eda.org/comp.lang.vhdl/FAQ1.html#4.8.1

von Queck S. (Firma: Uni) (kiigass)


Lesenswert?

Christian R. schrieb:
> Bei einem signed Summanden muss die Summe natürlich auch signed sein.

ja das ist klar, aber es funktioniert trotzdem nicht^^. Er meldet in der 
Zeile mit dem y <= x + y : "found '0' definitions of operator "+", 
cannot determine exact overloaded matching definition for "+""

PS: Ist das Absicht, dass du p signed castest und t unsigned oder hast 
du das nur verwechselt?

von Duke Scarring (Gast)


Lesenswert?

Was denn nun? x oder y oder p oder t?
Zeig bitte die Definition Deiner Signale, sowie die verwendeten 
Bibliotheken.

Duke

von Queck S. (Firma: Uni) (kiigass)


Lesenswert?

Duke Scarring schrieb:
> Was denn nun? x oder y oder p oder t?
> Zeig bitte die Definition Deiner Signale, sowie die verwendeten
> Bibliotheken.
>
> Duke

Nun, sowohl als auch, es ist eigentlich beides male das Gleich nur bei 
der P-T-Geschichte ist das Ergebnis unsigned, bei der X-Y-Geschichte 
signed. Dennoch funktionieren beide nicht.

Hier ist nochmal der gesamte Code der Test-Area:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity area51 is
6
port(
7
  clk : std_logic;
8
  eins : out std_logic_vector(3 downto 0);
9
  zwei : out std_logic_vector(3 downto 0)
10
);
11
end area51;
12
13
architecture Behavioral of area51 is
14
signal x: unsigned(3 downto 0) := "0101" ; -- Zahlenbereich: 0 bis 2**8-1
15
signal y: signed(3 downto 0) := "1111" ; -- Zahlenbereich: -2**7 bis 2**7-1
16
17
begin
18
19
x <= x + 1;
20
y <= x + y;
21
22
eins <= std_logic_vector(x);
23
zwei <= std_logic_vector(y);
24
25
end Behavioral;

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


Lesenswert?

Queck Silber schrieb:
> begin
>
> x <= x + 1;   --- Hoppala, eine kombinatorische Schleife....
>
> :
> end Behavioral;
Das hast du aber nicht mit einer Testbench ausprobiert, oder?

> Dennoch funktionieren beide nicht.
Was funktioniert denn nicht? Was erwartest du?

> y <= x + y;
Das kann ja nur solange funktionieren, wie es bei der Addition nicht 
zu einem Überlauf kommt. Denn die Addition und die Subtraktion ist 
sowohl bei signed wie auch bei unsigned beides mal exakt die selbe, es 
wird dabei auch das selbe Rechenwerk und die selben Rechenvorschriften 
verwendet! Nur das Bitmuster des Ergebnisses wird anders 
interpretiert...

von Queck S. (Firma: Uni) (kiigass)


Lesenswert?

Lothar Miller schrieb:
> Queck Silber schrieb:
>> begin
>>
>> x <= x + 1;   --- Hoppala, eine kombinatorische Schleife....

Das stammt von hier: 
http://www.mikrocontroller.net/articles/Rechnen_in_VHDL#Besser:_Rechnen_mit_numeric_std

>> end Behavioral;
> Das hast du aber nicht mit einer Testbench ausprobiert, oder?

doch hab ich, allerdings hab ich in der Zeile "y <= x + y" das x 
gecastet.

>> Dennoch funktionieren beide nicht.
> Was funktioniert denn nicht? Was erwartest du?

Queck Silber schrieb:
> ja das ist klar, aber es funktioniert trotzdem nicht^^. Er meldet in der
> Zeile mit dem y <= x + y : "found '0' definitions of operator "+",
> cannot determine exact overloaded matching definition for "+""

schon das compilen funktioniert nicht. Ich würde also erwarten, dass es 
das zumindest mal tut.

von Duke Scarring (Gast)


Lesenswert?

Queck Silber schrieb:
> Er meldet in der
> Zeile mit dem y <= x + y : "found '0' definitions of operator "+",
> cannot determine exact overloaded matching definition for "+""
Ok. x ist unsigned und y ist signed:
1
signed <= unsigned + signed;

In der numeric_std sind folgende Additionen (siehe [1]) definiert:
1
operator   1st par 2nd par   return  remarks
2
+     uns   uns   uns   unsigned add; length of result = max(length of 1st par, length of 2nd par)
3
+     sgn   sgn   uns   signed add (two's-complement); length of result = max(length of 1st par, length of 2nd par)
4
+     uns   nat   uns   add an uns with a non-negative int; length of result = length of 1st par
5
+     nat   uns   uns   add an uns with a non-negative int; length of result = length of 2nd par
6
+     sgn   int   sgn   add a sgn with an int; length of result = length of 1st par
7
+     int   sgn   sgn   add a sgn with an int; length of result = length of 2nd par

Genau das besagt die Fehlermeldung. Er findet keine Funktion um einen 
signed mit einem unsigned zu addieren. Du kannst dem Compiler mit casts 
oder konvertierungen auf die Sprünge helfen.

Duke


[1] http://www.eda.org/comp.lang.vhdl/FAQ1.html#4.8.1

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


Lesenswert?

Queck Silber schrieb:
>>> x <= x + 1;   --- Hoppala, eine kombinatorische Schleife....
> Das stammt von hier:
> http://www.mikrocontroller.net/articles/Rechnen_in...
Aber sicher nicht ohne Takt!
http://www.lothar-miller.de/s9y/categories/36-Kombinatorische-Schleife

> schon das compilen funktioniert nicht.
Sieh mal im Quelltext der numeric_std nach, für welche Operatoren die 
Addition definiert ist, dann siehst du klar, dass es signed+unsigend 
dort nicht gibt:
1
     -- Id: A.3
2
  function "+" (L,R: UNSIGNED ) return UNSIGNED;
3
     -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0).
4
     -- Result: Adds two UNSIGNED vectors that may be of different lengths.
5
 
6
     -- Id: A.4
7
  function "+" ( L,R: SIGNED) return SIGNED;
8
     -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0).
9
     -- Result: Adds two SIGNED vectors that may be of different lengths.
10
 
11
     -- Id: A.5
12
  function "+" ( L: UNSIGNED; R: NATURAL) return UNSIGNED;
13
     -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0).
14
     -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R.
15
 
16
     -- Id: A.6
17
  function "+" ( L: NATURAL; R: UNSIGNED) return UNSIGNED;
18
     -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0).
19
     -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R.
20
 
21
     -- Id: A.7
22
  function "+" ( L: INTEGER; R: SIGNED) return SIGNED;
23
     -- Result subtype: SIGNED (R'LENGTH-1 downto 0).
24
     -- Result: Adds an INTEGER, L (may be positive or negative), to a SIGNED
25
     --         vector, R.
26
 
27
     -- Id: A.8
28
  function "+" ( L: SIGNED; R: INTEGER) return SIGNED;
29
     -- Result subtype: SIGNED (L'LENGTH-1 downto 0).
30
     -- Result: Adds a SIGNED vector, L, to an INTEGER, R.
Quelle:
http://www.csee.umbc.edu/portal/help/VHDL/packages/numeric_std.vhd

Und damit gibt es nur 2 Wege: überlade den Operator + so, dass er auch 
signed+unsigned kann, oder machs, wie du es schon gemacht hast mit einem 
Cast. Vorher würde ich dann aber noch einen resize() erwägen, damit du 
nicht in die Bredoullie mit dem MSB kommst.

Denn es ist einfach so, dass du einen 4 Bit signed und einen 4 Bit 
unsigned nicht so ohne weiteres miteinander addieren darfst. Einmal 
ist "1111" ja ein Wert von 15 und das andere mal -1. Und was soll dann 
bei einer Addition herauskommen? 14 oder -2? Kurz: solange du in diesen 
4 Bit bleibst, kommt beides gleichzeitig heraus, es bleibt nur die 
Frage, wie du das Ergebnis interpretierst...

EDIT: Pech, Zweiter...  ;-)

von Duke Scarring (Gast)


Lesenswert?

Lothar Miller schrieb:
> EDIT: Pech, Zweiter...  ;-)
Dafür ausführlicher und (wie immer) besser erklärt :-)

von Queck S. (Firma: Uni) (kiigass)


Lesenswert?

Danke euch für eure Mühe und Hilfe, das hat mir sehr geholfen! und 
gelernt hab ich auch gleich ne Menge! Da ich mich noch nicht so recht an 
das Überladen von Funktionen in VHDL ran traue, hab ich das jetzt mit 
Casts gelöst. Ist nicht an jeder Stelle elegant, funktioniert aber. 
Soweit ich weiß, wird die Hälfte ja eh bei der Synthese rausoptimiert.^^

Wegen des Links:
Lothar Miller schrieb:
>> Das stammt von hier:
>> http://www.mikrocontroller.net/articles/Rechnen_in...
> Aber sicher nicht ohne Takt!

Da hast du meiner Ansicht nach Recht. Ich wollte damit auch vielmehr 
implizit auf einen möglichen Fehler aufmerksam machen, damit jemand, mit 
mehr Ahnung als ich, diesen (sofern es denn einer ist) beheben kann.

Danke nochmals!

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.