Ich habe einen Mod-16-Zähler gebaut, und das Ausgabeergebnis ist ein INTEGER (alle Beispiele, die ich gesehen habe, haben INTEGER verwendet).
Ich habe einen Hex-to-7-Segment-Display-Decoder gebaut, und seine Eingabe ist ein STD_LOGIC_VECTOR (habe es so geschrieben, weil es einfach war, die Wahrheitstabelle abzubilden).
Ich möchte den Ausgang des Zählers mit dem Eingang des Decoders verbinden, erhalte aber beim Versuch, in QuartusII zu kompilieren, „type mismatch“-Fehler.
Gibt es eine Möglichkeit, in einer VHDL-Auflistung von einem INTEGER-Typ in einen STD_LOGIC_VECTOR-Typ zu konvertieren?
Wie andere sagten, verwenden Sie ieee.numeric_std
, never ieee.std_logic_unsigned
, was nicht wirklich ein IEEE-Paket ist.
Wenn Sie jedoch Tools mit VHDL 2008-Unterstützung verwenden, können Sie das neue Paket verwenden ieee.numeric_std_unsigned
, das std_logic_vector
sich im Wesentlichen wie unsigniert verhält.
Da ich es nicht explizit angegeben habe, ist hier ein tatsächliches Codebeispiel zum Konvertieren von einer (vorzeichenlosen) Ganzzahl in eine std_logic_vector
:
use ieee.numeric_std.all;
...
my_slv <= std_logic_vector(to_unsigned(my_int, my_slv'length));
Wie LoneTech sagt, use ieee.numeric_std
ist Ihr Freund. Sie können a std_logic_vector
in ein konvertieren integer
, aber Sie müssen es zuerst als signed
oder umwandeln unsigned
(da der Compiler keine Ahnung hat, was Sie meinen). VHDL ist eine stark typisierte Sprache. Mehr zu diesem Thema habe ich in meinem Blog geschrieben
Grundsätzlich würde ich Ihren 7seg-Konverter so ändern, dass er ein integer
(oder eigentlich ein natural
, da er nur positive Zahlen verarbeitet) aufnimmt - die Konvertierung ist dann eine einfache Array-Suche. Richten Sie ein konstantes Array mit den Konvertierungen ein und indizieren Sie es einfach mit der Ganzzahl, die Sie für die Entität als Eingabe verwenden.
Um eine Ganzzahl in std_logic_vector umzuwandeln, haben Sie mehrere Möglichkeiten. Verwendung von numeric_std:
vect <= std_logic_vector( to_unsigned( your_int, vect'length));
oder
vect <= std_logic_vector( to_signed( your_int, vect'length));
Verwenden von std_logic_arith:
vect <= conv_std_logic_vector( your_int, vect'length);
std_logic_arith ist kein IEEE-Standard, aber die meisten Tools kompilieren es in die IEEE-Bibliothek und es wird häufig verwendet.
Wie die Hauptantwort sagt, ist die empfohlene Methode wie folgt:
use ieee.numeric_std.all;
...
my_slv <= std_logic_vector(to_unsigned(my_int, my_slv'length));
Ich möchte jedoch näher darauf eingehen, warum dies empfohlen wird und warum VHDL eine so scheinbar komplizierte Methode zum Konvertieren von Ganzzahlen in std_logic_vectors hat.
Es kommt darauf an, wie diese Typen von den Tools angezeigt werden.
Ein standard_logic_vector ist buchstäblich ein Bündel von Einsen oder Nullen. Ich habe 10001. Welche Nummer ist das? Es hängt davon ab. Ist es signiert oder unsigniert? Ths SLV weiß es nicht oder kümmert sich nicht darum. Wie viele Bits? Wie lang ist dein SLV?
Eine Ganzzahl ist signiert und normalerweise 32 Bit (wenn ich mich richtig erinnere).
Stufe 1: Machen Sie meine Ganzzahl kürzer und ohne Vorzeichen. Das ist dieser Teil:
to_unsigned(my_int, my_slv'length));
"Ich habe diese Ganzzahl, ich möchte, dass sie unsigniert ist, und ich möchte, dass sie in die Länge meines SLV passt."
Stufe 2: Nehmen Sie dann diese Bits und verwenden Sie sie, um den my_slv zu steuern.
my_slv <= std_logic_vector(...)
"Nimm diese Bits und benutze sie, um meinen Slv zu fahren"
(Ein Hinweis zur Terminologie. A <= B
in VHDL wird laut vorgelesen als "A wird von B angetrieben")
Kombiniert erhalten Sie:
my_slv <= std_logic_vector(to_unsigned(my_int, my_slv'length));
Wenn man aus einem traditionellen Programmierhintergrund kommt, ist es sehr leicht, in einer Programmier-Denkweise stecken zu bleiben. Aber in VHDL hat der von Ihnen geschriebene Code physische Auswirkungen auf die Hardware. Zu wissen, warum diese Methode funktioniert und empfohlen wird, ist einen Schritt näher daran, darüber nachzudenken, was Sie in Hardware-Begriffen schreiben.
Bonus-Tipp: Funktionen mit dem Präfix to_ sind solche, die die Operanden verkürzen/ändern. Sie machen sie unsigniert oder haben eine bestimmte Länge oder beides. Aus diesem Grund erfordert to_unsigned die Angabe der Länge. Die Funktionen ohne to_ (gerade std_logic_vector(...) in diesem Beispiel) werden verwendet, wenn Typen bereits direkt kompatibel sind. "Nehmen Sie diese Bits und stopfen Sie sie in diesen Typ, keine Änderungen erforderlich". Diese haben kein Längenargument, da beide Seiten bereits gleich sind. Wenn ich solche Dinge konstruiere, muss ich also nicht nachschlagen, ich denke nur darüber nach, wie ich die Daten ändere.
Möglicherweise interessieren Sie sich für die Verwendung der Typen unsigned
und signed
von ieee.numeric_std
. Sie sind mit kompatibel std_logic_vector
, haben aber eine numerische Interpretation (binär oder Zweierkomplement). Es gibt auch die Möglichkeit, eine solche Interpretation anzugeben std_logic_vector
, aber dies wird nicht empfohlen .
VHDL-2019-Beispiel für die Konvertierung von integer
auf std_logic_vector
EDA Playground .
Sie können einfach Folgendes tun:
slv <= std_logic_vector(to_signed(i));
Oder als Funktion für Signale und Variablen:
function ConvertToSlv(constant i: in integer) return TResult of std_logic_vector is
variable result: TResult;
begin
result := std_logic_vector(to_signed(i, result'length));
return result;
end function;
Verwendung
signal int: integer := -5;
signal nat: natural := 5;
signal sig1: std_logic_vector(7 downto 0);
signal sig2: std_logic_vector(15 downto 0);
...
variable var1: std_logic_vector(7 downto 0);
variable var2: std_logic_vector(15 downto 0);
...
sig1 <= ConvertToSlv(int);
sig2 <= ConvertToSlv(nat);
...
var1 := ConvertToSlv(int);
var2 := ConvertToSlv(nat);
Schreiben Sie Konvertierungsprozeduren, die sicherstellen, dass wir das length
Attribut von signal
oder lesen, das variable
wir ändern, etwa so:
Für Signale:
procedure ConvertToSlvSig(constant i: in integer; signal slv: out std_logic_vector) is
begin
slv <= std_logic_vector(to_signed(i, slv'length));
end procedure;
Für Variablen:
procedure ConvertToSlvVar(constant i: in integer; variable slv: out std_logic_vector) is
begin
slv := std_logic_vector(to_signed(i, slv'length));
end procedure;
Verwendung:
signal int: integer := -5;
signal nat: natural := 5;
signal sig1: std_logic_vector(7 downto 0);
signal sig2: std_logic_vector(15 downto 0);
...
variable var1: std_logic_vector(7 downto 0);
variable var2: std_logic_vector(15 downto 0);
...
ConvertToSlvSig(int, sig1);
ConvertToSlvSig(nat, sig2);
ConvertToSlvVar(int, var1);
ConvertToSlvVar(nat, var2);
Dies verhindert Fehler wie:
the_wrong_slv <= std_logic_vector(to_unsigned(int, the_right_slv'length));
Angenommen, Ihr 4-Bit-Zähler hatte einen INTEGER-Ausgang SOME_INTEGER, und Sie wollten ihn in einen 4-Bit-STD_LOGIC_VECTOR konvertieren
SOME_VECTOR <= conv_std_logic_vector(SOME_INTEGER, 4);
Sie können dies auch verwenden, um Vektoren mit sinnvollen Zahlen zu initialisieren
SOME_VECTOR <= conv_std_logic_vector(9, 4); -- instead of "1001"
Ich denke, Sie müssen möglicherweise "use IEEE.STD_LOGIC_ARITH.ALL;" hinzufügen. und/oder STD_LOGIC_UNSIGNED.
Die komplementäre Operation ist conv_integer(vector). Ich benutze das gerne, wenn ich Vergleiche mache. Also könnte ich erklären
constant SOME_CONSTANT : integer := 999;
Und später kann ich das in einer if-Anweisung verwenden
if (conv_integer(SOME_VECTOR)=SOME_CONSTANT)
then OTHER_VECTOR <= (others => '0');
end if;
EDIT: Sie sollten die Variable nicht als Integer deklarieren müssen. Versuchen Sie stattdessen, die Deklaration in std_logic_vector zu ändern. Die + und - Operatoren funktionieren auf std_logic_vectors.
J. Pölfer
MattG