Opérateurs logiques, relationnels, arithmétiques et de décalage en VHDL.
Une expression VHDL se lit avec les types des opérandes et la priorité des opérateurs. Les parenthèses rendent le regroupement explicite et évitent les interprétations erronées.
Priorité
Catégorie
Opérateurs
1, la plus faible
Logiques
and, , , , ,
or
nand
nor
xor
xnor
2
Relationnels
=, /=, <, <=, >, >=
3
Décalage et rotation
sll, srl, sla, sra, rol, ror
4
Additifs
+, -, &
5
Signe unaire
+, -
6
Multiplicatifs
*, /, mod, rem
7, la plus forte
Divers
**, abs, not
Combiner et comparer
Les opérations logiques existent notamment sur std_logic, std_logic_vector, bit et boolean. Sur un vecteur, elles travaillent bit à bit :
-- Sur std_logic (1 bit)w_y <= i_a AND i_b;w_y <= i_a OR i_b;w_y <= i_a XOR i_b;w_y <= NOT i_a;w_y <= i_a NAND i_b;w_y <= i_a NOR i_b;w_y <= i_a XNOR i_b;-- Sur std_logic_vector (bit à bit)w_mask <= w_data AND "11110000"; -- masquage des 4 bits de poids faiblew_set <= w_data OR "00001111"; -- forçage des 4 bits de poids faible
Les opérateurs logiques partagent une même priorité. Le langage impose des restrictions sur leur mélange ; utilise des parenthèses pour préciser les groupes :
-- INCORRECT : ambiguïté de prioritéw_y <= i_a AND i_b OR i_c; -- erreur de compilation !-- CORRECT : parenthèses obligatoires si mélangew_y <= (i_a AND i_b) OR i_c;w_y <= i_a AND (i_b OR i_c);
Une comparaison retourne un boolean utilisable dans une condition :
if i_a = i_b then -- égalitéif i_a /= i_b then -- différentif r_counter < 100 then -- strictement inférieurif r_counter >= c_MAX then -- supérieur ou égal
Avec numeric_std, unsigned et signed se comparent comme des nombres. La comparaison d'un std_logic_vector est lexicographique ; convertis-le vers le type numérique voulu avant une comparaison arithmétique.
Calculer avec les bonnes largeurs
numeric_std définit l'arithmétique sur les vecteurs numériques. Élargis les opérandes avant l'addition lorsque tu veux conserver la retenue. La largeur d'un produit est la somme des largeurs des deux opérandes :
Une division ou un modulo par une valeur variable peut demander beaucoup de logique. Pour un compteur à modulo fixe, une comparaison explicite rend souvent le circuit plus simple :
if r_count = 9 then r_count <= 0;else r_count <= r_count + 1;end if;
mod et rem donnent le même résultat avec des entiers positifs :
7 mod 4 = 37 rem 4 = 3
Pour un résultat non nul, A mod B prend le signe de B, tandis que A rem B prend celui de A :
(-7) mod 4 = 1(-7) rem 4 = -3
Cette différence compte si le calcul accepte des valeurs négatives.
Décaler, tourner et concaténer
Les fonctions shift_left, shift_right, rotate_left et rotate_right de numeric_std rendent le type et la direction du déplacement visibles :
signal w_data : std_logic_vector(7 downto 0);signal w_uns : unsigned(7 downto 0);signal w_sig : signed(7 downto 0);-- Décalage logique (remplissage par '0')w_uns <= shift_left(w_uns, 2); -- décalage gauche de 2 (×4)w_uns <= shift_right(w_uns, 1); -- décalage droit de 1 (÷2)-- Décalage arithmétique sur signed : shift_right propage le bit de signew_sig <= shift_right(w_sig, 1);-- Rotationw_uns <= rotate_left(w_uns, 3);w_uns <= rotate_right(w_uns, 3);
shift_right ajoute des zéros à gauche d'un unsigned et répète le bit de signe d'un signed. Les opérateurs sll, srl, sla, sra, rol et ror existent aussi, avec leurs règles et surcharges propres.