Forum: FPGA, VHDL & Co. Unsigned mit Offset zu 2 Compl VHDL


von FPGA (Gast)


Lesenswert?

Hallo

Meine Datenquelle liefert die Daten unsigned mit einem Offset. Die 
Datensenke benötigt ein signed 2 complement.

Wie kann dies in VHDL realisiert werden?
irgendwie so?

out <= std_logic_vector(to_signed(to_integer(unsigned(inputdata(15 
downto 0))- 32767), 16))

(0-64k soll auf -32k...+32k abgebildet werden)

von Gustl B. (-gb-)


Lesenswert?

Dein signed geht von -2**15 bis +2**15-1. Damit du wirklich die -2**15 
bekommst musst du statt 32767 die 32768 abziehen.

von Josef G. (bome) (Gast)


Lesenswert?

Einfach das höchste Bit invertieren.

von FPGA (Gast)


Lesenswert?

Gustl B. schrieb:
> Dein signed geht von -2**15 bis +2**15-1. Damit du wirklich die
> -2**15
> bekommst musst du statt 32767 die 32768 abziehen.

Danke
Habe irgendwo gesehen, dass die Umrechnung gerne overflow macht? Geht 
dies so wie oben beschrieben oder müsste:

out <= 
std_logic_vector(resize(to_signed(to_integer(unsigned(inputdata(15
downto 0))- 32768), 16), 17);

?

von Gustl B. (-gb-)


Lesenswert?

Josef G. (bome) schrieb:
> Einfach das höchste Bit invertieren.

Exakt, das ist die einfachste Lösung.

FPGA schrieb im Beitrag #6457488:
> Geht dies so wie oben beschrieben oder müsste:

Ich würde mal sagen ja, bin mir aber nicht ganz sicher.

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


Angehängte Dateien:

Lesenswert?

FPGA schrieb im Beitrag #6457488:
> Habe irgendwo gesehen
Ja, im Internet sieht man so viel...

> (0-64k soll auf -32k...+32k abgebildet werden)
Also etwa so:
1
   input     -->    output
2
dez    hex       dez      hex          
3
0      0000  --> -32768   8000
4
1      0001  --> -32767   8001
5
:
6
32767  7fff  -->     -1   ffff
7
32768  8000  -->      0   0000
8
32769  8001  -->     +1   0001
9
:
10
65534  fffe  --> +32767   7ffe
11
65535  ffff  --> +32768   7fff

FPGA schrieb im Beitrag #6457488:
> oder müsste:
> out <= std_logic_vector(resize(to_signed(to_integer(unsigned(inputdata(15 downto 
0))- 32768), 16), 17);

Wie sollen da aus 16 Bits auf einmal 17 werden? Warum sollte sich der 
Wertebereich verdoppeln?

> unsigned(inputdata(15 downto 0))-32768
Du kannst hier auch einfach so schreiben, wenn inputdata eh nur 16 Bit 
breit ist:
unsigned(inputdata)-32768
Und dann passiert ganau das hier:
1
  input   -32768 => output
2
dez    hex       dez      hex          
3
0      0000  --> -32768   8000
4
1      0001  --> -32767   8001
5
:
6
32767  7fff  -->     -1   ffff
7
32768  8000  -->      0   0000
8
32769  8001  -->     +1   0001
9
:
10
65534  fffe  --> +32767   7ffe
11
65535  ffff  --> +32768   7fff

Ergo gibt es mehrere Lösungen:
1
-- 1
2
       outval <= inval xor x"8000";
3
-- 2
4
       outval <= std_logic_vector(signed(inval)-32768);
5
-- 3
6
       outval <= std_logic_vector(unsigned(inval)-32768);
7
-- 4
8
       outval <= std_logic_vector(signed(inval)+to_signed(-32768,16));
9
-- 5
10
       outval <= std_logic_vector(signed(inval)-to_signed(-32768,16));
Die vierte "Lösung" ist dabei noch nachvollziehbar, aber zumindest die 
fünfte dann doch recht überreaschend... ;-)

Hier noch ein kurzer Test der vorgeschlagenen Lösungen:
https://www.edaplayground.com/x/bgZF
Man sieht in der Waveform, dass überall das selbe rauskommt.

Josef G. (bome) schrieb:
> Einfach das höchste Bit invertieren.
Wie wahr. Und wie elegant.

: Bearbeitet durch Moderator
von Weltbester FPGA-Pongo (Gast)


Lesenswert?

Lothar M. schrieb:
> Josef G. (bome) schrieb:
>> Einfach das höchste Bit invertieren.
> Wie wahr. Und wie elegant.

Auf Bit-Ebene die Daten zu manipulieren war schon immer das Schlauste, 
wenn man weiß, was man tut. Es widerspricht aber der Lesbarkeit und 
Transportierbarkeit des Codes und ich glaube nicht, dass durch einen 
sauberen Cast schaltungstechnisch etwas anderes herauskommt :-)

von FPGA (Gast)


Lesenswert?

Lothar M. schrieb:
> Ergo gibt es mehrere Lösungen:-- 1
>        outval <= inval xor x"8000";
> -- 2
>        outval <= std_logic_vector(signed(inval)-32768);
> -- 3
>        outval <= std_logic_vector(unsigned(inval)-32768);
> -- 4
>        outval <= std_logic_vector(signed(inval)+to_signed(-32768,16));
> -- 5
>        outval <= std_logic_vector(signed(inval)-to_signed(-32768,16));

super Danke!

Wenn ichs richtig verstanden habe gehen alle?

Beitrag #6504797 wurde von einem Moderator gelöscht.
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.