Aller au contenu

Syntaxe VHDL fondamentale

Éléments lexicaux

VHDL ne distingue pas majuscules et minuscules. Clock, CLOCK et clock désignent le même identificateur. Un commentaire commence par deux tirets.

signal count : unsigned(7 downto 0); -- Huit bits

Une mise en forme régulière reste essentielle à la lecture.

Déclarations

Chaque objet possède un type.

constant CLOCK_HZ : positive := 100_000_000;
signal   enabled  : std_logic := '0';
signal   count    : unsigned(7 downto 0) := (others => '0');
variable result   : natural;
Objet Signification
Constante Valeur fixe après l'élaboration
Signal Connexion évoluant dans le temps avec un ou plusieurs pilotes
Variable Mise à jour immédiate dans sa région séquentielle
Fichier Flux externe, normalement réservé au banc de test
Alias Autre nom ou vue en tranche d'un objet existant

Signaux et variables

L'affectation d'un signal utilise <=. La nouvelle valeur est planifiée et devient visible après la suspension du processus, ou après le délai indiqué.

L'affectation d'une variable utilise :=. Sa nouvelle valeur est immédiatement visible par l'instruction suivante.

process(clk_i)
  variable incremented : unsigned(7 downto 0);
begin
  if rising_edge(clk_i) then
    incremented := count_q + 1;
    count_q     <= incremented;
  end if;
end process;

Piège classique

Deux affectations successives du même signal dans un processus ne réalisent pas deux étapes de calcul. La dernière affectation prévue pour le même instant l'emporte. Utilisez une variable pour un calcul intermédiaire.

Littéraux et agrégats

bit_s    <= '1';
vector_s <= "1010";
hex_s    <= x"AF";
count_s  <= 16#2A#;
all_zero <= (others => '0');
pair_s   <= (7 => '1', 0 => '1', others => '0');

Une unité de temps est séparée par un espace : 10 ns, 2 us, 1 ms.

Opérateurs

Famille Exemples
Divers abs, not, exponentiation
Multiplication *, /, mod, rem
Signe + et - unaires
Addition +, -, concaténation &
Décalage/rotation sll, srl, rol
Relation =, /=, <, >=
Logique and, or, xor, xnor

Utilisez des parenthèses dès que le matériel attendu n'est pas immédiatement évident.

Affectations concurrentes

Sélection prioritaire :

y_o <= a_i when sel_i = "00" else
       b_i when sel_i = "01" else
       c_i when sel_i = "10" else
       d_i;

Multiplexeur sans priorité implicite :

with sel_i select
  y_o <= a_i when "00",
         b_i when "01",
         c_i when "10",
         d_i when others;

Instructions if et case

Elles sont séquentielles et vivent donc dans un processus, une fonction ou une procédure.

if value_i = 0 then
  zero_o <= '1';
elsif value_i > threshold_i then
  high_o <= '1';
else
  zero_o <= '0';
  high_o <= '0';
end if;

En logique combinatoire, affectez toutes les sorties sur tous les chemins. En logique cadencée, l'absence d'affectation signifie généralement que le registre conserve sa valeur.

case opcode_i is
  when "00"   => result_o <= a_i + b_i;
  when "01"   => result_o <= a_i - b_i;
  when "10"   => result_o <= a_i and b_i;
  when others => result_o <= (others => '0');
end case;

Toutes les valeurs possibles doivent être couvertes. others couvre également les métavaleurs telles que X.

Boucles

La synthèse déroule une boucle dont les bornes sont connues :

parity_v := '0';
for index in data_i'range loop
  parity_v := parity_v xor data_i(index);
end loop;

La variable de boucle est déclarée implicitement. Réservez les boucles while aux bancs de test sauf si le synthétiseur peut prouver une borne statique.

Attributs

Attribut Signification
'left, 'right Indices gauche et droit
'high, 'low Indices maximum et minimum
'range, 'reverse_range Plage d'indices
'length Nombre d'éléments
'event Le signal a changé pendant le cycle courant
'image Conversion d'une valeur en texte
'value Conversion d'un texte en valeur
'pos, 'val Position d'une valeur d'énumération
result_o <= resize(a_i, result_o'length) + resize(b_i, result_o'length);
for index in data_i'range loop
  -- Indépendant du sens de déclaration du tableau.
end loop;

Génération de matériel

generate réplique ou inclut conditionnellement du matériel à l'élaboration :

gen_bits : for bit_index in data_i'range generate
  result_o(bit_index) <= data_i(bit_index) and enable_i;
end generate;

gen_parity : if G_INCLUDE_PARITY generate
  parity_o <= xor data_i;
end generate;

Les génériques configurent le circuit synthétisé ; ils ne constituent pas un choix d'exécution.

Assertions

assert G_WIDTH > 0
  report "G_WIDTH must be positive"
  severity failure;

Les niveaux sont note, warning, error et failure. Le script de test doit également vérifier le code de retour du simulateur.

VHDL-2008 utilisé ici

  • process(all) crée automatiquement une liste de sensibilité complète.
  • std.env.finish termine proprement un test réussi.
  • Une architecture peut relire ses ports de sortie.
  • Les paquetages génériques et autres possibilités avancées sont améliorés.

Compilez avec xvhdl -2008 et choisissez VHDL 2008 comme type de fichier dans Vivado.