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 peut devenir incohérente avec la synthèse. Un latch est inféré surtout quand toutes les sorties ne sont pas assignées sur tous les chemins.
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 architectureNotez 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.
📝 Tester mes connaissances - Quiz du chapitre 7 questions. XP maximale au premier essai.