Les Process
Le bloc process : liste de sensibilité, instructions séquentielles, et patterns combinatoire/séquentiel.
Qu'est-ce qu'un process ?
Le process est le seul endroit en VHDL où les instructions s'exécutent séquentiellement (comme dans un langage de programmation classique).
-- Structure générale
process(liste_de_sensibilite)
-- déclarations locales (variables)
begin
-- instructions séquentielles
end process;Un process est un bloc concurrent par rapport au reste de l'architecture : plusieurs process s'exécutent en parallèle entre eux, mais les instructions internes à un process sont séquentielles.
La liste de sensibilité
Le process se "réveille" uniquement quand un signal de sa liste de sensibilité change.
Process combinatoire
-- Tous les signaux lus dans le process doivent être dans la liste
process(i_a, i_b, i_sel)
begin
if i_sel = '0' then
w_mux <= i_a;
else
w_mux <= i_b;
end if;
end process;Si un signal est oublié dans la liste de sensibilité d'un process combinatoire, la simulation sera incorrecte (mémoire implicite). La synthèse peut lever un avertissement.
Process séquentiel
-- Uniquement l'horloge (et le reset asynchrone si utilisé)
process(i_clk)
begin
if rising_edge(i_clk) then
r_q <= i_d;
end if;
end process;VHDL-2008 : process(all)
-- Capture automatiquement tous les signaux lus
process(all)
begin
w_result <= i_a + i_b;
end process;Pattern combinatoire
architecture rtl of alu is
signal w_result : std_logic_vector(7 downto 0);
begin
p_alu : process(i_op, i_a, i_b)
begin
case i_op is
when "00" => w_result <= i_a AND i_b;
when "01" => w_result <= i_a OR i_b;
when "10" => w_result <= i_a XOR i_b;
when others => w_result <= (others => '0');
end case;
end process p_alu;
o_result <= w_result;
end architecture rtl;Notez le label de process (p_alu :) — bonne pratique pour la lisibilité.
Pattern séquentiel (registre + reset synchrone)
p_reg : process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_data <= (others => '0');
r_valid <= '0';
r_counter <= (others => '0');
else
r_data <= i_data;
r_valid <= i_valid;
r_counter <= r_counter + 1;
end if;
end if;
end process p_reg;Instructions séquentielles dans un process
if / elsif / else
process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_state <= IDLE;
elsif i_enable = '1' then
r_state <= ACTIVE;
else
r_state <= r_state; -- inutile mais explicite
end if;
end if;
end process;case
process(i_clk)
begin
if rising_edge(i_clk) then
case r_state is
when IDLE =>
if i_start = '1' then
r_state <= RUNNING;
end if;
when RUNNING =>
if r_done = '1' then
r_state <= IDLE;
end if;
when others =>
r_state <= IDLE;
end case;
end if;
end process;
when othersest obligatoire dans uncasesur des types non énumérés. C'est une bonne pratique même pour les types énumérés (couvre les cas imprévus).
for / loop
process(i_clk)
variable v_sum : unsigned(15 downto 0);
begin
if rising_edge(i_clk) then
v_sum := (others => '0');
for i in 0 to 7 loop
if w_data(i) = '1' then
v_sum := v_sum + 1;
end if;
end loop;
r_popcount <= v_sum(3 downto 0);
end if;
end process;Erreurs courantes
Latch inféré (erreur de logique combinatoire)
-- MAUVAIS : toutes les branches ne couvrent pas toutes les sorties
process(i_sel, i_a, i_b)
begin
if i_sel = '0' then
w_out <= i_a;
end if;
-- i_sel = '1' → w_out non assigné → latch inféré !
end process;
-- BON : valeur par défaut + couverture complète
process(i_sel, i_a, i_b)
begin
w_out <= i_a; -- valeur par défaut
if i_sel = '1' then
w_out <= i_b;
end if;
end process;Les latches sont à éviter sur FPGA (mauvais timing, ressources inefficaces). Toujours couvrir tous les cas dans un process combinatoire.