Forum: FPGA, VHDL & Co. std_logic_vector => signed zum Rechnen


von Christian Z. (Gast)


Lesenswert?

Hallo zusammen,

ich habe einen 8bit std_logic_vector als Eingang.
Dieser enthält periodische signale von -100mV bis 100mV.
0x00 entspricht dabei -100mV
0x7F entspricht dabei    0mV
0xFF entspricht dabei  100mV

Wenn ich nun erst Gain und dann Offset ändern möchte, muss ich den 
Vektor ja irgendwie in ein Format bringen, der wieder 
"achsensymmetrisch" ist. Denn wenn ich von 0 auf 255 einen Faktor 
multipliziere, wird die Kurve ja nur gestaucht und der -100mV Wert wird 
z.B. so belassen, weil 0*irgendwas immer noch 0 ist.

Kann ich diesen Effekt einfach mit
1
signal input : std_logic_vector(7 downto 0);
2
signal input_signed : signed(7 downto 0);
3
... 
4
input_signed <= signed(input);
erzielen?

Dann mit einem Faktor multiplizieren
1
signal input_signed : signed(7 downto 0);
2
signal faktor : signed(7 downto 0);
3
signal result_gain : signed(15 downto 0);
4
...
5
result_gain <= input_signed * faktor;

Dann mit dem Offset addieren
1
signal result_gain : signed(15 downto 0);
2
signal offset : signed(15 downto 0);
3
signal result_offset : signed(15 downto 0);
4
...
5
result_offset <= result_gain + offset;
6
-- dann noch Überlauf abfangen etc.

Und am Ende dann wieder casten.
1
signal output  : std_logic_vector(15 downto 0);
2
signal result_offset : signed(15 downto 0);
3
...
4
output <= std_logic_vector(result_offset);

Funktioniert das in etwa so?
Habe zur zeit leider keinen Rechner dabei, auf dem die FPGA Tools sind, 
so dass ich es schnell simulieren könnte :(

Daher meine theoretischen Gedanken zu diesem Thema.

Vielen Dank!
Chris

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


Lesenswert?

Christian Z. schrieb:
> Kann ich diesen Effekt einfach mit
> signal input : std_logic_vector(7 downto 0);
> signal input_signed : signed(7 downto 0);
> ...
> input_signed <= signed(input);
> erzielen?
Wie sind signed und usigned in der Integer-Arithmetik?
Richtig: 0x80=maxneg, 0=0, 0x7f=maxpos

Also musst du vor dem Skalieren  erst mal den Offset abziehen:
> 0x7F entspricht dabei    0mV
--> ADwert-0x7f = 0x00 = 0mV
Und erst dann kannst du sorgenfrei multiplizieren und rechnen.

Was du dann zurückgibst, hängt allein davon ab, wie der Empfänger das 
Ergebnis interpretiert. Aber sinnvollerweise geht man frühestmöglich 
auf die normale vorzeichenbehaftetet Integerarithmetik über.

von Christian Z. (Gast)


Lesenswert?

Hallo,

danke für die Antwort!

Du meinst also etwa so?
1
input_signed <= signed(input - x"7F");
Jetzt mal abgesehen ob die Syntax das so zulässt, vermutlich nicht...

Vielen Dank!
Chris

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


Lesenswert?

Ja, die Richtung stimmt. Allerdings wird es sinnvollerweise eher so 
sein, dass du erst nach signed wandelst und dann 0x80 subtrahierst:
input_signed <= signed(input) - 16#80;
Oder einfach:
input_signed <= signed(input) - 128;

Denn deine Skalierung ist sehr aussergewöhnlich, nichtlinear (du hast 
für 100mV mehr positive Schritte als negative, ein Integer hat aber mehr 
negative Schritte als positive) und bringt ein Problem, wenn du 0xff 
(=maxpos) - 0x7f (=0) rechnest. Dabei kommt nämlich 0x80 heraus, und das 
ist maxneg...   :-o

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.