Lors de l'écriture de VHDL, je recommande fortement d'utiliser std_logic_vector (slv) au lieu de integer (int) pour SIGNALS . (D'un autre côté, utiliser int pour les génériques, certaines constantes et certaines variables peuvent être très utiles.) Autrement dit, si vous déclarez un signal de type int, ou devez spécifier une plage pour un entier, vous faites probablement Quelque chose ne va pas.
Le problème avec int est que le programmeur VHDL n'a aucune idée de la représentation logique interne de l'int, et nous ne pouvons donc pas en profiter. Par exemple, si je définis un entier compris entre 1 et 10, je n'ai aucune idée de la façon dont le compilateur code ces valeurs. Espérons que ce serait codé en 4 bits, mais nous ne savons pas grand-chose au-delà. Si vous pouviez sonder les signaux à l'intérieur du FPGA, il pourrait être codé de "0001" à "1010", ou codé de "0000" à "1001". Il est également possible qu'il soit codé d'une manière qui n'a absolument aucun sens pour nous, les humains.
Au lieu de cela, nous devrions simplement utiliser slv au lieu de int, car nous contrôlons alors le codage et avons également un accès direct aux bits individuels. Avoir un accès direct est important, comme vous le verrez plus tard.
Nous pourrions simplement lancer un int en slv chaque fois que nous avons besoin d'accéder aux bits individuels, mais cela devient vraiment désordonné, très rapide. C'est comme obtenir le pire des deux mondes au lieu du meilleur des deux mondes. Votre code sera difficile à optimiser pour le compilateur et presque impossible à lire. Je ne le recommande pas.
Donc, comme je l'ai dit, avec slv, vous avez le contrôle sur les codages de bits et l'accès direct aux bits. Alors, que pouvez-vous faire avec ça? Je vais vous montrer quelques exemples. Disons que vous devez émettre une impulsion toutes les 4 294 000 000 d'horloges. Voici comment procéder avec int:
signal count :integer range 0 to 4293999999; -- a 32 bit integer
process (clk)
begin
if rising_edge(clk) then
if count = 4293999999 then -- The important line!
count <= 0;
pulse <= '1';
else
count <= count + 1;
pulse <= '0';
end if;
end if;
end process;
Et le même code en utilisant slv:
use ieee.numeric_std.all;
signal count :std_logic_vector (32 downto 0); -- a 33 bit integer, one extra bit!
process (clk)
begin
if rising_edge(clk) then
if count(count'high)='1' then -- The important line!
count <= std_logic_vector(4293999999-1,count'length);
pulse <= '1';
else
count <= count - 1;
pulse <= '0';
end if;
end if;
end process;
La plupart de ce code est identique entre int et slv, au moins dans le sens de la taille et de la vitesse de la logique résultante. Bien sûr, l'un compte et l'autre compte à rebours, mais ce n'est pas important pour cet exemple.
La différence réside dans "la ligne importante".
Avec l'exemple int, cela va aboutir à un comparateur à 32 entrées. Avec les LUT à 4 entrées utilisées par le Xilinx Spartan-3, cela nécessitera 11 LUT et 3 niveaux de logique. Certains compilateurs peuvent convertir cela en une soustraction qui utilisera la chaîne de transport et s'étendra sur l'équivalent de 32 LUT mais pourrait fonctionner plus rapidement que 3 niveaux de logique.
Avec l'exemple slv, il n'y a pas de comparaison 32 bits, c'est donc "zéro LUT, zéro niveau de logique". La seule pénalité est que notre compteur est un bit supplémentaire. Étant donné que la synchronisation supplémentaire pour ce bit supplémentaire de compteur est entièrement dans la chaîne de transport, il y a un retard de synchronisation supplémentaire "presque nul".
Bien sûr, c'est un exemple extrême, car la plupart des gens n'utiliseraient pas un compteur 32 bits de cette manière. Cela s'applique aux compteurs plus petits, mais la différence sera moins dramatique, mais toujours significative.
Ce n'est qu'un exemple de la façon d'utiliser slv over int pour obtenir un timing plus rapide. Il existe de nombreuses autres façons d'utiliser slv - cela ne prend que de l'imagination.
Mise à jour: ajout de trucs pour répondre aux commentaires de Martin Thompson sur l'utilisation de int avec "if (count-1) <0"
(Remarque: je suppose que vous vouliez dire "si count <0", car cela le rendrait plus équivalent à ma version slv et éliminerait le besoin de cette soustraction supplémentaire.)
Dans certaines circonstances, cela peut générer l'implémentation logique prévue, mais il n'est pas garanti de fonctionner tout le temps. Cela dépendra de votre code et de la façon dont votre compilateur code la valeur int.
En fonction de votre compilateur et de la façon dont vous spécifiez la plage de votre int, il est tout à fait possible qu'une valeur int de zéro ne soit pas codée en un vecteur binaire "0000 ... 0000" lorsqu'elle est intégrée dans la logique FPGA. Pour que votre variation fonctionne, elle doit coder en "0000 ... 0000".
Par exemple, disons que vous définissez un int pour avoir une plage de -5 à +5. Vous vous attendez à ce qu'une valeur de 0 soit codée en 4 bits comme "0000", et +5 en "0101" et -5 en "1011". Il s'agit du schéma de codage typique à deux compléments.
Mais ne supposez pas que le compilateur va utiliser deux compléments. Bien que inhabituel, le complément à un pourrait entraîner une "meilleure" logique. Ou bien, le compilateur pourrait utiliser une sorte de codage "biaisé" où -5 est codé comme "0000", 0 comme "0101" et +5 comme "1010".
Si le codage de l'int est "correct", le compilateur déduira probablement quoi faire avec le bit de retenue. Mais si elle est incorrecte, la logique résultante sera horrible.
Il est possible que l'utilisation d'un int de cette manière puisse entraîner une taille et une vitesse logiques raisonnables, mais ce n'est pas une garantie. Le passage à un autre compilateur (XST vers Synopsis par exemple) ou le passage à une architecture FPGA différente pourrait provoquer la mauvaise chose exacte.
Non signé / signé vs slv est encore un autre débat. Vous pouvez remercier le comité du gouvernement américain de nous avoir donné autant d'options en VHDL. :) J'utilise slv car c'est la norme d'interface entre les modules et les cœurs. En dehors de cela, et de certains autres cas dans les simulations, je ne pense pas qu'il y ait un énorme avantage à utiliser slv sur signé / non signé. Je ne suis pas sûr non plus que les signaux à trois états pris en charge signés / non signés.