Forum: FPGA, VHDL & Co. Subtrahieren bei STD_LOGIC_VECTOR


von B. U. (peggy)


Lesenswert?

Hallo,

ich möchte zwei STD_LOGIC_VECTOR Variablen voneinander abziehen.
Das Programm dazu sieht wie folgt aus:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity DeTiSub1 is
port (   TimReq : in std_logic_vector(17 downto 0);
  MTimReq : out std_logic_vector (17 downto 0);
  ct20us : in integer range 0 to 2047
  );
end DeTiSub1;

architecture DeTiSubE of DeTiSub1 is
  signal detimm: std_logic_vector (17 downto 0);
begin
  detimm <= "0000000" & conv_std_logic_vector(ct20us,11);
  MTimReq <= TimReq - detimm;
end DeTiSubE;

Es lässt sich auch ohne Probleme komplieren und so.
Aber was passiert wenn detimm größer wird als TimReq? Leider finde ich 
nicht, warum das subtrahieren überhaupt funktioniert... in welcher 
Library steht das? Da es sich, wie die Variablennamen schon verraten um 
Zeiten handelt, ist dieser Fall schon wichtig.
Sollte man das ganze besser mit numeric_std machen? wie sieht das 
Programm dann aus?

Weiß einer hier ein Buch, vorzugsweise auf Deutsch, in dem die ganzen 
Librarys mit Ihren Funktion erklärt werden? Also schon zum Nachschlagen, 
ähnlich dem Kernighan and Ritchie für C?
Schon mal vielen Dank für Eure Hilfe,

Lg Peggy

von jm (Gast)


Lesenswert?

Schon in die
ieee.std_logic_arith.all;
geschaut?

Einfach mal simulieren, dann siehst du was passiert. Vermutlich wird das 
Ergebnis im zweierkomplement negativ wenn der subtrahend größer ist.

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


Lesenswert?

> Sollte man das ganze besser mit numeric_std machen?
Ja, wäre wohl grundsätzlich besser, die
1
use ieee.std_logic_arith.all;
2
use ieee.std_logic_unsigned.all;
zu vergessen, und auf die herstellerunabhängige numeric_std 
umzuschalten. Dann gibt es nämlich nur noch 1 Library, in der du nach 
Rechenoperationen schauen mußt.
Und dann sieht das in etwa so aus:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity DeTiSub1 is
6
port (   TimReq  : in  unsigned(17 downto 0);
7
         MTimReq : out unsigned(17 downto 0);
8
         ct20us  : in integer range 0 to 2047
9
  );
10
end DeTiSub1;
11
12
architecture DeTiSubE of DeTiSub1 is
13
  signal detimm: unsigned(17 downto 0);
14
begin
15
  detimm  <= to_unsigned(ct20us,detimm'length);
16
  MTimReq <= TimReq-detimm;
17
end DeTiSubE;

Ungeachtet dessen bleibt dir der pragmatische Weg mit der Simulation 
nicht nicht versperrt. Der instatiierte Subtrahierer wird detimm auch 
dann abziehen, wenn es größer ist als TimReq.
Wenn du das nicht willst, mußt du das händisch abfangen:
1
  MTimReq <=  TimReq-detimm when TimReq>detimm else 0;



> ... zum Nachschlagen, ähnlich dem Kernighan and Ritchie für C?
Im K&R werden auch nicht alle Funktionen irgendwelcher Libraries 
erklärt. Zum Beispiel ist da keine einzige Fkt zum Ansteuern eines LCD 
näher erläutert... ;-)

von Morin (Gast)


Lesenswert?

> Aber was passiert wenn detimm größer wird als TimReq?

Dann gibts es einen "wrap-around", soll heißen bei einem vector (17 
downto 0) ist 0 dasselbe wie 2^18 und eine negative Zahl wird 
entsprechend auf eine "große" Zahl abgebildet, z.B. -1 auf 2^18-1, -2 
auf 2^18-2 usw.

> Vermutlich wird das
> Ergebnis im zweierkomplement negativ wenn der subtrahend größer ist.

Nein, denn
1
use ieee.std_logic_unsigned.all;

gibt an, dass vorzeichenlos gerechnet wird. Mit "...signed" hättest du 
recht.

> und auf die herstellerunabhängige numeric_std umzuschalten.

Gefragt war, was in der "...unsigned" Bibliothek passiert, nicht welche 
Bibliothek besser ist.

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


Lesenswert?

Morin wrote:
> use ieee.std_logic_unsigned.all;
> gibt an, dass vorzeichenlos gerechnet wird. Mit "...signed" hättest du
> recht.
Ist es nicht so, dass die Rechnung (Subtraktion) immer dieselbe ist, nur 
das Ergebnis anders interpretiert wird, z.B. bei einem Vergleich?


>> und auf die herstellerunabhängige numeric_std umzuschalten.
> Gefragt war, was in der "...unsigned" Bibliothek passiert, nicht welche
> Bibliothek besser ist.

Oh, habe ich die ursprüngliche Frage sooo falsch interpretiert ;-)
>>> Sollte man das ganze besser mit numeric_std machen?

von Morin (Gast)


Lesenswert?

> Ist es nicht so, dass die Rechnung (Subtraktion) immer dieselbe ist, nur
> das Ergebnis anders interpretiert wird, z.B. bei einem Vergleich?

Ja, zumindest ein "ja" in dem Sinne wie du es meinst: Soweit es das 
Bitmuster betrifft, ist die Operation die selbe, soweit es die 
Interpretation als Zahl betrifft, eine andere.

> Oh, habe ich die ursprüngliche Frage sooo falsch interpretiert ;-)

Ich bitte tausendmal um Verzeihung, das hatte ich überlesen schäm

von B. U. (peggy)


Lesenswert?

Vielen Dank für Eure Hilfe!

Werd das dann gleich mal fleißig simulieren ;-)

von B. U. (peggy)


Lesenswert?

So hab jetzt simuliert, geht so wie´s soll. Also Wrap Around mit Einsen 
dann
 00 0000 0000 0000 0000
-00 0000 0010 0101 1000
______________________
 11 1111 1101 1010 1000

also alles prima ;-)

Trotzdem musste ich noch mehr casten, weil ich an den Ausgängen auch 
unbedingt den Datentyp std_logic_vector brauche:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity DeTiSub1 is
6
port (   TimReq  : in  std_logic_vector(17 downto 0);
7
         MTimReq : out std_logic_vector(17 downto 0);
8
         ct20us  : in integer range 0 to 2047
9
  );
10
end DeTiSub1;
11
12
architecture DeTiSubE of DeTiSub1 is
13
  signal detimm: unsigned(17 downto 0);
14
  signal TimReqM: unsigned(17 downto 0);
15
  signal MTimReqM: unsigned (17 downto 0);  
16
17
begin
18
  TimReqM <= unsigned (TimReq); --Cast des Eingangs zu unsigned
19
  detimm  <= to_unsigned(ct20us,detimm'length); --Cast der Konstante Datentyp integer=>unsigned
20
  MTimReqM <= TimReqM-detimm;
21
  MTimReq <= std_logic_vector (MTimReqM);--Cast zu std_logic_vector fuer Ausgang
22
end DeTiSubE;

oder weiß jemand was besseres?

von Duke Scarring (Gast)


Lesenswert?

Sieht gut aus. Du kannst Deine Signale etwas generischer generieren:
1
  signal detimm, TimReqM: unsigned(TimReq'range);
2
  signal MTimReqM: unsigned(MTimReq'range);

Duke

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


Lesenswert?

> Trotzdem musste ich noch mehr casten, weil ich an den Ausgängen auch
> unbedingt den Datentyp std_logic_vector brauche
> :
> oder weiß jemand was besseres?
Nein, nicht mit Standard-Libs, VHDL ist da ein wenig geschwätzig ;-)

Natürlich könntest du selber die Operatoren überladen. Aber wenn du 
"nur" an den Schnittstellen std_logic_vector verwendest, hält sich der 
Cast-Aufwand in Grenzen.

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.