Je ne suis pas sûr de comprendre la différence entre "downto" et "to" dans vhdl.
J'ai vu des explications en ligne, mais je ne pense toujours pas comprendre. Quelqu'un peut-il me le présenter?
On monte, on descend:
-- gives 0, 1, 2, 3:
for i in 0 to 3 loop
-- gives 3, 2, 1, 0:
for i in 3 downto 0 loop
Si vous prenez un processeur, pour les systèmes Little endian, nous pouvons utiliser "downto" et pour les systèmes bigendiens, nous utilisons "to".
Par exemple,
signal t1 : std_logic_vector(7 downto 0); --7th bit is MSB and 0th bit is LSB here.
et,
signal t2 : std_logic_vector(0 to 7); --0th bit is MSB and 7th bit is LSB here.
Vous êtes libre d'utiliser les deux types de représentations, il suffit de vous assurer que les autres parties de la conception sont écrites en conséquence.
Ce post dit quelque chose de différent:
"Le terme big endian (ou little endian) désigne l'ordre des octets dans les processeurs orientés octets et ne convient pas aux vecteurs de bits VHDL. Le terme technique est une plage de tableaux ascendante et descendante. Les types numériques prédéfinis comme signé et non signé sont limités aux plages descendantes. par convention."
Donc, cette réponse peut être déroutante ...
Une référence en ligne intéressante que j'ai trouvée est ici , où entre autres, dans la section "Affectations de tableaux", vous pouvez lire:
Deux objets de tableau peuvent être assignés l'un à l'autre, à condition qu'ils soient du même type et de la même taille. Il est important de noter que l'affectation se fait par poste et non par numéro d'index. Il n'y a aucun concept d'un bit le plus significatif défini dans le langage. Il est strictement interprété par l'utilisateur qui utilise le tableau. Voici des exemples d'affectations de tableaux:
avec la déclaration suivante:
....
SIGNAL z_bus: BIT_VECTOR (3 DOWNTO 0);
SIGNAL a_bus: BIT_VECTOR (1 TO 4);
....
z_bus <= a_bus;
est le même que:
z_bus(3) <= a_bus(1);
z_bus(2) <= a_bus(2);
z_bus(1) <= a_bus(3);
z_bus(0) <= a_bus(4);
Observations:
1) Toute différence entre "downto" et "to" apparaît lorsque nous voulons utiliser un vecteur de bits non seulement pour représenter un tableau de bits, où chaque bit a un comportement indépendant, mais pour représenter un nombre entier. Ensuite, il y a une différence de signification des bits, en raison de la façon dont les nombres sont traités par des circuits tels que des additionneurs, des multiplicateurs, etc.
Dans ce cas sans doute spécial, en supposant 0 <x <y, c'est une convention habituelle que lors de l'utilisation de x to y
, x est le bit le plus significatif (MSB) et y le bit le moins significatif (LSB). Inversement, lorsque vous utilisez y downto x
, y est le MSB et x le LSB. Vous pouvez dire que la différence, pour les vecteurs binaires représentant des entiers, vient du fait que l'index du MSB vient en premier, que vous utilisiez "to" ou "downto" (bien que le premier index soit plus petit que le second lorsque vous utilisez "to" et plus grand lors de l'utilisation de "downto").
2) Vous devez noter que y downto x
ce qui signifie que y est le MSB et, inversement, x to y
ce qui signifie que x est le MSB sont des conventions connues, généralement utilisées dans les cœurs de propriété intellectuelle (IP) que vous pouvez trouver mis en œuvre et même gratuitement. C'est aussi la convention utilisée par les bibliothèques IEEE VHDL, je pense, lors de la conversion entre les vecteurs bits et les entiers. Mais, la modélisation structurelle n'a rien de difficile, par exemple, un additionneur 32 bits qui utilise des vecteurs binaires d'entrée de la forme y downto x
et utilisez y comme LSB, ou utilise des vecteurs binaires d'entrée de la forme x to y
où x est utilisé comme LSB ...
Néanmoins, il est raisonnable d'utiliser la notation x downto 0
pour un entier non négatif, car les positions des bits correspondent à la puissance de 2 multipliée par le chiffre pour correspondre à la valeur numérique. Cela semble avoir été étendu également dans la plupart des autres pratiques impliquant des nombres entiers.
3) L'ordre des bits n'a rien à voir avec endianness. L'endianisme fait référence à l'ordre des octets (enfin, l'ordre des octets est une forme d'ordre des bits ...). L'endianisme est un problème exposé au niveau de l'architecture du jeu d'instructions (ISA), c'est-à-dire qu'il est visible pour le programmeur qui peut accéder à la même adresse mémoire avec différentes tailles d'opérandes (par exemple, Word, octet, double mot, etc.). L'ordre des bits dans l'implémentation (comme dans la question) n'est jamais exposé au niveau ISA. Seule la sémantique des positions de bits relatives est visible pour le programmeur (par exemple, la logique de décalage vers la gauche peut être réellement implémentée) en décalant vers la droite un registre dont la signification des bits est inversée dans l'implémentation).
(C'est incroyable le nombre de réponses qui mentionnent cela ont été votées!)
Dans les types vectoriels, le bit le plus à gauche est le plus significatif. Par conséquent, pour 0 to n
plage, bit 0
est le msb, pour un n downto 0
bit de plage n
est le msb.
Cela est pratique lorsque vous combinez IP qui utilise à la fois des ordres de bits big-endian et little-endian pour garder la tête droite!
Par exemple, Microblaze est big-endian et utilise 0
comme son msb. J'en ai interfacé un avec un périphérique externe peu endian, j'ai donc utilisé 15 downto 0
sur les broches externes et les a remappées en 16 to 31
à l'extrémité microblaze de mon cœur d'interface.
VHDL vous oblige à être explicite à ce sujet, vous ne pouvez donc pas faire le_vec <= be_vec;
directement.
Généralement, cela vous empêche de mélanger l'ordre des bits lorsque vous instanciez des composants. Vous ne voudriez pas stocker le LSB dans X(0)
et le transmettre à un composant qui attend que X(0)
contienne le MSB.
En pratique, j'ai tendance à utiliser DOWNTO
pour les vecteurs de bits (STD_LOGIC_VECTOR(7 DOWNTO 0)
ou UNSIGNED(31 DOWNTO 0)
) et TO
pour les RAM (TYPE data_ram IS ARRAY(RANGE NATURAL<>) OF UNSIGNED(15 DOWNTO 0); SIGNAL r : data_ram(0 TO 1023);
) et compteurs intégrés (SIGNAL counter : NATURAL RANGE 0 TO max_delay;
).
Pour développer @ la réponse de KerrekSB , considérez un encodeur prioritaire:
ENTITY prio
PORT (
a : IN STD_LOGIC_VECTOR(7 DOWNTO 1);
y : OUT STD_LOGIC_VECTOR(2 DOWNTO 0)
);
END ENTITY;
ARCHITECTURE seq OF prio IS
BEGIN
PROCESS (a)
BEGIN
y <= "000";
FOR i IN a'LOW TO a'HIGH LOOP
IF a(i) = '1' THEN
y <= STD_LOGIC_VECTOR(TO_UNSIGNED(i, y'LENGTH));
END IF;
END LOOP;
END PROCESS;
END ENTITY;
La direction de la boucle (TO
ou DOWNTO
) contrôle ce qui se passe lorsque plusieurs entrées sont affirmées (exemple: a := "0010100"
). Avec TO
, l'entrée numérotée la plus élevée gagne (y <= "100"
). Avec DOWNTO
, l'entrée la moins numérotée gagne (y <= "010"
). En effet, la dernière affectation d'un processus est prioritaire. Mais vous pouvez également utiliser EXIT FOR
pour déterminer la priorité.
On m'a appris qu'une bonne règle est d'utiliser "downto" pour les questions où le maintien de l'ordre binaire est important (par exemple un signal 8 bits contenant un caractère) et "to" est utilisé lorsque le signal n'est pas nécessairement interconnecté par exemple si chaque bit du signal représente une LED que vous allumez et éteignez.
connecter un 4 bits "vers le bas" et un 4 bits "vers" ressemble à quelque chose comme
sig1 (3 jusqu'à 0) <= sig2 (0 à 3)
------- 3 -------------------- 0
------- 2 -------------------- 1
------- 1 -------------------- 2
------- 0 -------------------- 3
prendre une partie du signal à la place sig1 (2 à 1) <= sig2 (0 à 1)
------- 2 -------------------- 0
------- 1 -------------------- 1
Bien qu'il n'y ait rien de mal à l'une des réponses ci-dessus, j'ai toujours cru que la fourniture des deux est de soutenir deux paradigmes.
Le premier est la représentation numérique. Si j'écris le numéro 7249, vous l'interprétez immédiatement comme 7 mille 2 cent quarante-neuf. Les chiffres se lisent de gauche à droite où le chiffre le plus significatif se trouve à gauche. Il s'agit du cas "descendant".
La seconde est la représentation du temps où l'on pense toujours au temps progressant de gauche à droite. Sur une horloge, les nombres augmentent avec le temps et 2 suit toujours 1. Ici, j'écris naturellement l'ordre des bits de gauche à droite dans l'ordre croissant du temps, quelle que soit la représentation des bits. Dans RS232 par exemple, nous commençons avec un bit de début suivi de 8 bits de données (LSB en premier) puis un bit d'arrêt. Ici, le MSB est à droite; le cas "à".
Comme je l'ai dit, le plus important est de ne pas les mélanger arbitrairement. En décodant un flux RS232, nous pourrions finir par faire exactement cela pour transformer les bits reçus dans l'ordre temporel en octets qui sont MSB en premier, mais c'est vraiment l'exception plutôt que la règle.