Unsigned mit Offset zu 2 Compl VHDL

Gast #6457449
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)
Gast #6457488
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);

?
Moderator (Firma: Titel) Persönliche Seite #6457606
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.
Angehängte Dateien:
Gast #6458655
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 :-)
Gast #6459164
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren