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
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.
> Sollte man das ganze besser mit numeric_std machen?
Ja, wäre wohl grundsätzlich besser, die
1
useieee.std_logic_arith.all;
2
useieee.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
libraryieee;
2
useieee.std_logic_1164.all;
3
useieee.numeric_std.all;
4
5
entityDeTiSub1is
6
port(TimReq:inunsigned(17downto0);
7
MTimReq:outunsigned(17downto0);
8
ct20us:inintegerrange0to2047
9
);
10
endDeTiSub1;
11
12
architectureDeTiSubEofDeTiSub1is
13
signaldetimm:unsigned(17downto0);
14
begin
15
detimm<=to_unsigned(ct20us,detimm'length);
16
MTimReq<=TimReq-detimm;
17
endDeTiSubE;
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-detimmwhenTimReq>detimmelse0;
> ... 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... ;-)
> 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
useieee.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.
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?
> 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
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
libraryieee;
2
useieee.std_logic_1164.all;
3
useieee.numeric_std.all;
4
5
entityDeTiSub1is
6
port(TimReq:instd_logic_vector(17downto0);
7
MTimReq:outstd_logic_vector(17downto0);
8
ct20us:inintegerrange0to2047
9
);
10
endDeTiSub1;
11
12
architectureDeTiSubEofDeTiSub1is
13
signaldetimm:unsigned(17downto0);
14
signalTimReqM:unsigned(17downto0);
15
signalMTimReqM:unsigned(17downto0);
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
> 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.