Opérateurs logiques, relationnels, arithmétiques et de décalage en VHDL.
Catégories d'opérateurs
VHDL dispose de plusieurs familles d'opérateurs, présentées par priorité croissante :
Priorité
Catégorie
Opérateurs
1 (plus faible)
Logiques
and, or, nand, nor, xor, xnor
2
Relationnels
=, /=, <, <=, >, >=
3
Décalage / rotation
shift_left, shift_right, ,
rotate_left
rotate_right
4
Additifs
+, -, &
5
Multiplicatifs
*, /, mod, rem
6 (plus fort)
Divers
**, abs, not
Important : En VHDL, les opérateurs logiques ont la même priorité. Utilisez des parenthèses !
Opérateurs logiques
Opèrent sur std_logic, std_logic_vector, bit, boolean.
-- 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
Priorité - attention !
-- 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);
Opérateurs relationnels
Retournent un boolean. Utilisables dans les if, when, etc.
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
Pour comparer des unsigned/signed, utiliser NUMERIC_STD. Pour des std_logic_vector, la comparaison est lexicographique (bits à bits) - utiliser unsigned pour de l'arithmétique.
Opérateurs arithmétiques
Nécessitent IEEE.NUMERIC_STD pour les types unsigned/signed.
/, mod et rem existent en VHDL, mais ils ne doivent pas être utilisés comme de simples opérations "gratuites" en FPGA. Une division ou un modulo par une valeur variable peut inférer un circuit coûteux. Pour un compteur modulo fixe, on préfère souvent un test explicite :
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
La différence apparaît avec les valeurs négatives :
A mod B prend le signe de B ;
A rem B prend le signe de A.
Exemple :
(-7) mod 4 = 1(-7) rem 4 = -3
En RTL synthétisable, gardez surtout cette règle pratique : sur des compteurs et des indices positifs, mod est généralement celui qu'on veut ; pour du matériel efficace, remplacez-le par une comparaison quand le modulo est connu.
Décalages et rotations
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);
Les opérateurs sll, srl, sla, sra, rol et ror existent dans VHDL. En pratique, pour du code RTL moderne avec numeric_std, on privilégie les fonctions shift_left, shift_right, rotate_left et rotate_right sur les types unsigned et signed : l'intention est plus claire, les surcharges sont mieux maîtrisées, et le sens du décalage ne dépend pas d'un opérateur moins explicite.
Pour un unsigned, shift_right remplit à gauche avec des 0. Pour un signed, shift_right conserve le signe en recopiant le bit de poids fort. C'est la différence importante entre décalage logique et décalage arithmétique.