VHDL: Konvertieren von einem INTEGER-Typ in einen STD_LOGIC_VECTOR

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?

Antworten (7)

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_vectorsich 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_stdist Ihr Freund. Sie können a std_logic_vectorin ein konvertieren integer, aber Sie müssen es zuerst als signedoder 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.

Danke dafür. Ich schätze Ihre Kommentare sehr. Ich war in einer Art TA-Position und lernte VHDL, um einem Prof beim Einstieg zu helfen, der mit Programmierkonzepten etwas wackelig war. Ich werde Ihre Informationen an ihn weitergeben - das Lehrbuch, das wir verwendet haben, hat sich nicht mit Fragen zur VHDL-Moral befasst.
Es ist weniger eine Frage der „Moral“, als vielmehr eine Garantie für Konsistenz. Die Bibliothek numeric_std ist ein echter Standard, der vom IEEE eingeführt wurde, während die Bibliothek std_logic_unsigned von einem Anbieter erstellt und in der Industrie ohne wirkliche formale Definition übernommen wurde. Es gibt keine Garantie für die herstellerübergreifende Kompatibilität mit den nicht standardmäßigen Bibliotheken, obwohl es normalerweise gut funktioniert. Es gehört aber zum guten Ton, jetzt zum Standard überzugehen.

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 <= Bin 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 unsignedund signedvon 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 .

Für VHDL 2019

VHDL-2019-Beispiel für die Konvertierung von integerauf std_logic_vectorEDA 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);

Für frühere Versionen von VHDL

Schreiben Sie Konvertierungsprozeduren, die sicherstellen, dass wir das lengthAttribut von signaloder lesen, das variablewir ä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.

Bitte tun Sie dies nicht! Verwenden Sie numeric_std (siehe LoneTechs und meine Antworten)
Wenn Sie einen besseren Weg haben, ist das in Ordnung, aber mein Vorschlag funktioniert, daher denke ich, dass Ihre Ablehnung unnötig war. Ich benutze std_logic_arith seit Jahren und hatte nie Probleme damit. Ich denke, dass Befürchtungen, dass Anbieter ihre Implementierungen ändern könnten, unbegründet sind; Welcher Anbieter, der bei klarem Verstand ist, riskiert, die Designs seiner Kunden zu brechen?
Sie haben bereits eine Antwort darauf, welcher Anbieter absichtlich herstellerspezifische Dinge in den Namensraum von IEEE stellt. Es bleibt grob, insbesondere wenn es um vorzeichenbehaftete und vorzeichenlose Werte geht.
"Die Operatoren + und - funktionieren auf std_logic_vectors." AFAIK, sie funktionieren nicht, es sei denn, ich verstehe Ihre Bedeutung falsch. Es ist normalerweise notwendig, zuerst in einen Typ umzuwandeln, der signierte/unsignierte Daten enthält.