VHDL: conversion d'un type INTEGER en un STD_LOGIC_VECTOR

28

J'ai construit un compteur mod-16, et le résultat de sortie est un INTEGER (tous les exemples que j'ai vus utilisaient INTEGER).

J'ai construit un décodeur d'affichage hexadécimal à 7 segments, et son entrée est un STD_LOGIC_VECTOR (écrit de cette façon car il était facile de cartographier la table de vérité).

Je voudrais connecter la sortie du compteur à l'entrée du décodeur, mais j'obtiens des erreurs de `` discordance de type '' lorsque j'essaie de compiler dans QuartusII.

Existe-t-il un moyen de convertir d'un type INTEGER en un type STD_LOGIC_VECTOR dans une liste VHDL?

J. Polfer
la source

Réponses:

20

Comme d'autres l'ont dit, utilisez ieee.numeric_std, jamais ieee.std_logic_unsigned, ce qui n'est pas vraiment un package IEEE.

Cependant, si vous utilisez des outils avec prise en charge de VHDL 2008, vous pouvez utiliser le nouveau package ieee.numeric_std_unsigned, qui fait essentiellement se std_logic_vectorcomporter comme non signé.

De plus, comme je ne l'ai pas vu explicitement, voici un exemple de code réel pour convertir d'un entier (non signé) en std_logic_vector:

use ieee.numeric_std.all;
...
my_slv <= std_logic_vector(to_unsigned(my_int, my_slv'length));
wjl
la source
16

Comme le dit LoneTech, use ieee.numeric_stdc'est votre ami. Vous pouvez convertir un std_logic_vectoren un integer, mais vous devrez le convertir en premier signedou en tant unsignedque (car le compilateur n'a aucune idée de ce que vous voulez dire). VHDL est un langage fortement typé. J'en ai écrit plus sur ce sujet sur mon blog

Fondamentalement, je changerais votre convertisseur 7seg pour en prendre un integer(ou en fait un natural, étant donné qu'il ne traitera que des nombres positifs) - la conversion est alors une simple recherche de tableau. Configurez un tableau constant avec les conversions et indexez-le simplement avec l'entier que vous utilisez sur l'entité comme entrée.

Martin Thompson
la source
Merci pour cela. J'apprécie beaucoup vos commentaires. J'étais dans une position d'AT en quelque sorte, apprenant le VHDL pour aider un prof à démarrer qui était un peu secoué sur les concepts de programmation. Je vais lui transmettre vos informations - le manuel que nous avons utilisé ne plongeait pas dans les questions de «moralité» du VHDL.
J. Polfer
1
Il s'agit moins d'une question de «moralité» que de garantie de cohérence. La bibliothèque numeric_std est une véritable norme instituée par l'IEEE, tandis que la bibliothèque std_logic_unsigned a été constituée par un fournisseur et adoptée dans l'industrie sans aucune définition formelle réelle. Il n'y a aucune garantie de compatibilité entre les fournisseurs avec les bibliothèques non standard, bien que cela fonctionne généralement bien. Il est cependant bon de passer à la norme maintenant.
MattG
1

Disons que votre compteur 4 bits avait une sortie INTEGER SOME_INTEGER, et que vous vouliez la convertir en un STD_LOGIC_VECTOR 4 bits

SOME_VECTOR <= conv_std_logic_vector(SOME_INTEGER, 4);

Vous pouvez également l'utiliser pour initialiser des vecteurs avec des nombres significatifs

SOME_VECTOR <= conv_std_logic_vector(9, 4); -- instead of "1001"

Je pense que vous devrez peut-être ajouter "use IEEE.STD_LOGIC_ARITH.ALL;" et / ou STD_LOGIC_UNSIGNED.

L'opération complémentaire est conv_integer (vecteur). J'aime l'utiliser lorsque je fais des comparaisons. Je pourrais donc déclarer

constant SOME_CONSTANT : integer := 999;

Et puis, plus tard, je peux l'utiliser dans une instruction if

if (conv_integer(SOME_VECTOR)=SOME_CONSTANT)
  then OTHER_VECTOR <= (others => '0');
end if;

EDIT: vous ne devriez pas avoir besoin de déclarer la variable comme un entier. Essayez de remplacer la déclaration par std_logic_vector à la place. Les opérateurs + et - fonctionnent sur std_logic_vectors.

ajs410
la source
3
Veuillez ne pas faire ça! Utilisez numeric_std (voir LoneTech et mes réponses)
Martin Thompson
Si vous avez une meilleure façon de le faire, c'est bien, mais ma suggestion fonctionne donc je pense que votre vote négatif n'était pas nécessaire. J'utilise std_logic_arith depuis des années et je n'ai jamais eu de problème avec. Je pense que les craintes que les fournisseurs modifient leurs implémentations ne sont pas fondées; quel fournisseur sensé risquerait de casser les conceptions de ses clients?
ajs410
1
Vous avez déjà une réponse à ce que le fournisseur mettra volontairement des éléments spécifiques au fournisseur dans l'espace de noms IEEE. Il reste grossier, en particulier lorsqu'il s'agit de valeurs signées et non signées.
Yann Vernier
"Les opérateurs + et - fonctionnent sur std_logic_vectors." AFAIK, ils ne fonctionnent pas, sauf si je comprends mal votre sens. il est généralement nécessaire de convertir en un type contenant en premier des données signées / non signées.
stanri
1

Vous pouvez être intéressé par l'utilisation des types unsignedet signedde ieee.numeric_std. Ils sont compatibles avec std_logic_vector, mais ont une interprétation numérique (binaire ou complément à 2). Il y a aussi la possibilité de mettre une telle interprétation std_logic_vector, mais ce n'est pas recommandé .

Yann Vernier
la source
0

Comme le dit la réponse principale, la méthode recommandée est la suivante:

use ieee.numeric_std.all;
...
my_slv <= std_logic_vector(to_unsigned(my_int, my_slv'length));

Cependant, je voudrais expliquer pourquoi cela est recommandé et pourquoi VHDL a une manière si compliquée de convertir des entiers en std_logic_vectors.

Cela revient à la façon dont ces types sont vus par les outils.

Un standard_logic_vector est littéralement un groupe de 1 ou de 0. J'ai 10001. De quel numéro s'agit-il? En fait ça dépend. Est-il signé ou non signé? Ce SLV ne sait pas ou ne se soucie pas. Combien de bits? Eh bien, combien de temps dure votre SLV?

Un entier est signé, et généralement 32 bits (si je me souviens bien).

Étape 1: rendre mon entier plus court et non signé. Voilà cette partie:

to_unsigned(my_int, my_slv'length));

"J'ai cet entier, je veux qu'il ne soit pas signé, et je veux qu'il tienne dans la longueur de mon SLV."

Étape 2: Ensuite, prenez ces bits et utilisez-les pour piloter le my_slv.

my_slv <= std_logic_vector(...)

"Prenez ces morceaux et utilisez-les pour conduire mon slv"

(Une note sur la terminologie. A <= BEn VHDL est lue à haute voix comme "A est entraîné par B")

Combiné, cela vous donne:

my_slv <= std_logic_vector(to_unsigned(my_int, my_slv'length));

En venant d'un contexte de programmation traditionnel, il est très facile de rester coincé dans une manière de penser la programmation. Mais en VHDL, le code que vous écrivez a des implications physiques sur le matériel. Savoir pourquoi cette méthode fonctionne et est recommandée est un pas de plus vers la réflexion sur ce que vous écrivez en termes matériels.

Astuce bonus: les fonctions préfixées par to_ sont celles qui raccourcissent / modifient les opérandes. Ils les rendent non signés ou d'une certaine longueur ou les deux. C'est pourquoi to_unsigned vous oblige à spécifier la longueur. Les fonctions sans to_ (straight std_logic_vector (...) dans cet exemple) sont utilisées lorsque les types sont déjà directement compatibles. "Prenez ces bits et remplissez-les de ce type, aucune modification requise". Ceux-ci n'ont pas d'argument de longueur car les deux côtés sont déjà identiques. Donc, quand je construis des choses comme ça, je n'ai pas besoin de le chercher, je pense juste à la façon dont je modifie les données.

Stanri
la source
0

Pour convertir un entier en std_logic_vector, vous avez plusieurs options. Utilisation de numeric_std:

vect <= std_logic_vector( to_unsigned( your_int, vect'length));

ou

vect <= std_logic_vector( to_signed( your_int, vect'length));

Utilisation de std_logic_arith:

vect <= conv_std_logic_vector( your_int, vect'length);

std_logic_arith n'est pas un standard ieee, mais la plupart des outils le compilent dans la bibliothèque IEEE et il est largement utilisé.

Craig
la source