Forum: FPGA, VHDL & Co. signed Vektoren unterschiedlicher Breite korrekt addieren


von Calc (Gast)


Lesenswert?

Hallo zusammen,

ich habe folgende Vektoren:
1
variable sum1    : signed(17 DOWNTO 0);
2
variable sum2    : signed(31 DOWNTO 0);

Das Bit 17 bei sum1 ist also das "Vorzeichenbit".
Bei sum2 ist Bit 31 das "Vorzeichenbit".

Wie kann ich diese beiden signed Vektoren nun korrekt addieren, damit 
mir nicht die Vorzeichen um die Ohren fliegen?

Wenn ich einfach
1
sum := sum1 + sum2;
rechne, wird das Vorzeichenbit von sum1 ja nicht korrekt bewertet, oder?
Oder ist der signed Typ genau dafür da, dass genau das funktioniert?

Muss ich so rechnen?
1
sum := sum1(17) & "00000000000000" & sum1(16 DOWNTO 0) + sum2;

Vielen Dank!

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


Lesenswert?

Calc schrieb:
> Wenn ich einfach sum := sum1 + sum2;
> rechne, wird das Vorzeichenbit von sum1 ja nicht korrekt bewertet, oder?
> Oder ist der signed Typ genau dafür da, dass genau das funktioniert?
Einfach mal den "+" Operator in der numeric_std ansehen:
http://www.csee.umbc.edu/portal/help/VHDL/numeric_std.vhdl
Denn dort steht dann:
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.

Calc schrieb:
> sum := sum1(17) & "00000000000000" & sum1(16 DOWNTO 0)
Das ist für signed FALSCH. Denn alle die Bits, die da jetzt '0' sind, 
müssten sum(17) sein:
> sum := sum1(17) & sum1(17) & ... & sum1(17) & sum1(16 DOWNTO 0)

Ein Tipp: um dir das alles zu ersparen sieh dir mal die Funktion 
resize() aus der numeric_std an...

: Bearbeitet durch Moderator
von Rolf S. (audiorolf)


Lesenswert?

Was macht die Funktion  resize praktisch? Anschauen ob es signed ist 
und dann anders rechnen?

Was spricht dagegen, das per Hand zu machen oder nur eine Sorte zu 
benutzen in einem VHDL Modul?

von Calc (Gast)


Lesenswert?

Vielen Dank! Das ist ein guter Hinweis...

Wenn ich zwei signed Values mit gleicher Vektorlänge addiere, dann passt 
das noch gut mit dem + zusammen, ist aber wohl unsauber.

Also muss ich das so
1
sum := signed(std_logic_vector(  unsigned(std_logic_vector(sum1)) + unsigned(std_logic_vector(sum2)) ));
machen?

dann bin ich aber immer noch nicht schlauer, was das Vorzeichen betrifft 
:-/

Vielen Dank!

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


Lesenswert?

Rolf S. schrieb:
> Was macht die Funktion  resize praktisch?
Das, was in der Beschreibung steht: bei singed wird mit dem "linkesten" 
Bit aufgefüllt. Bei unsigned mit '0'...

> Anschauen ob es signed ist und dann anders rechnen?
Warum siehst du dir die numeric_std nicht einfach mal an?
Dort ziemlich weit unten:
http://www.eda.org/rassp/vhdl/models/standards/numeric_std.vhd

> Was spricht dagegen, das per Hand zu machen oder nur eine Sorte zu
> benutzen in einem VHDL Modul?
Kann man machen, wenn man nur 1 Datentypen braucht. Aber wozu singed 
verwenden, wenn bestimmte Werte nur unsigned sein können?

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


Lesenswert?

Calc schrieb:
> Also muss ich das so
> sum := signed(std_logic_vector(
> unsigned(std_logic_vector(sum1)) + unsigned(std_logic_vector(sum2)) ));
> machen?
Nein, so: sum := sum1 + sum2;

Calc schrieb:
> Das Bit 17 bei sum1 ist also das "Vorzeichenbit".
> Bei sum2 ist Bit 31 das "Vorzeichenbit".
Da fällt mir auf: das stimmt NICHT für normale Zweierkomplementzahlen.
Hast du ein anderes Zahlensystem?

von Calc (Gast)


Lesenswert?

Da habe ich mit der Antwort zu lange gebraucht....

resize(..) schaue ich mir mal an... Danke! :)

von Calc (Gast)


Lesenswert?

Lothar M. schrieb:
> Da fällt mir auf: das stimmt NICHT für normale Zweierkomplementzahlen.
> Hast du ein anderes Zahlensystem?

Nein, habe ich nicht.
Wieso sollte diese Darstellung nicht für normale 
Zweierkomplementzahlengelten?

Ich habe eine Summe, die positiv und negativ sein kann.
Wenn ich also bis maximal 2^3 in die eine Richtung zählen kann, füge ich 
ein Bit hinzu und kann genauso weit in die andere Richtung zählen, oder 
nicht?

-8...0...7  so kenne ich das, oder habe ich da auch noch einen 
Denkfehler?

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


Lesenswert?

Calc schrieb:
> -8...0...7  so kenne ich das, oder habe ich da auch noch einen
> Denkfehler?
Die Übertragung ins Zweierkomplement...
Wie sieht 1 aus? Und wie -1? Sind die etwa gleich nur mit 
unterschiedlichem "Vorzeichenbit"? Reicht es aus, das "Vorzeichenbit" zu 
setzen, um das Vorzeichen umzukehren?

Fazit: es gibt kein "Vorzeichenbit". Sondern man kann einfach nur am 
signifikanten Bit erkennen  ob die Zahl positiv oder negativ ist.

von Markus F. (mfro)


Lesenswert?

Rechner mit Einerkomplementdarstellung gab's auch mal...

Da durfte man dann grübeln was besser ist: "+0" oder "-0" ;)

von Burkhard K. (buks)


Lesenswert?

Markus F. schrieb:
> Rechner mit Einerkomplementdarstellung gab's auch mal...
>

Aber auch beim Einerkomplement gibt es kein Vorzeichenbit. Anders sieht 
das bei der "Sign-Magnitude" Darstellung aus.

@Calc - Lothars Link lohnt sich, einfach mal weiterlesen:
1
 -- Id: A.4
2
  function "+" (L, R: SIGNED) return SIGNED;
3
  -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0).
4
  -- Result: Adds two SIGNED vectors that may be of different lengths.
Das Addieren funktioniert also auch für signed-Zahlen mit 
unterschiederlicher Breite - beantwortet das Deine Frage?

BTW: unsigned lässt sich auf mehr als eine Art in einen signed-Vektor 
transformieren:
 * durch Erweiterung um den negativen Wertebereich - zusätzliches Bit
 * durch Subtraktion von 2**(N-1) - gleichbeibende Wortbreite

Letzteres Verfahren ist z.B. angebracht, wenn Werte aus einem ADC mit 
unipolarem Ausgang symmetriert werden sollen, weil sie z.B. einem 
Audio-Codec zugeführt werden.

von J. S. (engineer) Benutzerseite


Lesenswert?

Wer nur rechnen will, bleibt am Besten bei der Numeric. Da ist 
sichergestellt, dass die Ergebnisse passen und nicht irgendwie 
verschnitten werden.

Bei den Vektoren muss man immer gedanklich mitschleppen, wie viele 
Kommastellen es da gab und mit welchem Vorfaktor das Ergebnis hinterlegt 
ist. Das ist nur bei wenigen Applikationen sinnvoll, da aufwändiger, 
wenn auch zumindest beim Kontakt des VHDL mit der Außenwelt zumindest an 
zwei Stellen unumgänglich, wenn es auf die PORTS geht.

Wenn man allerdings jetzt noch den Sachverhalt hinzunimmt, dass man bei 
komplizierteren Berechnungen sowieso die Repräsentation und Überläufe in 
den "Variablen" vorberechnen und das Ganze designen muss, kann man die 
Vektoroperationen gleich mitrechnen lassen. Der Vorteil ist dann der, 
dass man wirklich sieht, wo man Bits einsparen kann. Und man kann es 
sogar ein wenig steuern und trimmen.

von Rolf S. (audiorolf)


Lesenswert?

Lothar M. schrieb:
> Das, was in der Beschreibung steht: bei singed wird mit dem "linkesten"
> Bit aufgefüllt. Bei unsigned mit '0'...
Man lernst nie aus...

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.