Logique séquentielle
Bascules D, registres, compteurs — les éléments de mémoire de la logique numérique.
De la combinatoire à la séquentielle
La logique combinatoire n'a pas de mémoire. Pour mémoriser un état, on utilise des éléments de mémoire synchronisés sur une horloge.
Circuit synchrone : Entrées → Logique combinatoire → Registres → Sorties (avec rétroaction d'état courant)
Image à ajouter
Ce modèle est la base de tout circuit numérique synchrone.
La bascule D (Flip-Flop D)
La bascule D est l'élément de mémorisation fondamental.
Comportement
| Événement | Action |
|---|---|
| Front montant de CLK | Q ← D |
| Entre deux fronts | Q conserve sa valeur |
| RST actif (synchrone) | Q ← 0 au prochain front |
-- Bascule D simple
process(i_clk)
begin
if rising_edge(i_clk) then
r_q <= i_d;
end if;
end process;Bascule D avec reset synchrone et enable
process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_q <= '0';
elsif i_en = '1' then
r_q <= i_d;
end if;
end if;
end process;Registres
Un registre est un groupe de N bascules D partageant la même horloge — mémorise N bits simultanément.
Registre simple N bits
entity registre_8bit is
port (
i_clk : in std_logic;
i_rst : in std_logic;
i_en : in std_logic;
i_data : in std_logic_vector(7 downto 0);
o_data : out std_logic_vector(7 downto 0)
);
end entity registre_8bit;
architecture rtl of registre_8bit is
signal r_data : std_logic_vector(7 downto 0);
begin
process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_data <= (others => '0');
elsif i_en = '1' then
r_data <= i_data;
end if;
end if;
end process;
o_data <= r_data;
end architecture registre_8bit;Registre à décalage (Shift Register)
architecture rtl of shift_reg is
signal r_shift : std_logic_vector(7 downto 0);
begin
process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_shift <= (others => '0');
else
-- Décalage vers la droite, entrée série sur MSB
r_shift <= i_serial & r_shift(7 downto 1);
end if;
end if;
end process;
o_parallel <= r_shift; -- sortie parallèle
o_serial <= r_shift(0); -- sortie série
end architecture rtl;Usage : conversion série/parallèle (UART, SPI), délai de N cycles.
Compteurs
Compteur binaire simple
architecture rtl of counter is
signal r_count : unsigned(7 downto 0);
begin
process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_count <= (others => '0');
else
r_count <= r_count + 1; -- déborde naturellement : 255 → 0
end if;
end if;
end process;
o_count <= std_logic_vector(r_count);
end architecture rtl;Compteur avec limite (modulo N)
architecture rtl of counter_mod is
constant c_MAX : integer := 99; -- compte de 0 à 99
signal r_count : integer range 0 to c_MAX;
begin
process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_count <= 0;
elsif r_count = c_MAX then
r_count <= 0;
o_tick <= '1'; -- impulsion de dépassement
else
r_count <= r_count + 1;
o_tick <= '0';
end if;
end if;
end process;
end architecture rtl;Compteur up/down
process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_count <= (others => '0');
elsif i_up = '1' then
r_count <= r_count + 1;
elsif i_down = '1' then
r_count <= r_count - 1;
end if;
end if;
end process;Domaines d'horloge et synchronisation
Lorsque des données traversent des domaines d'horloge différents (CDC — Clock Domain Crossing), des problèmes de métastabilité peuvent survenir.
La solution standard : le double registre (double-flop synchronizer)
-- Synchroniseur 2 étages pour signal 1 bit
signal r_sync1, r_sync2 : std_logic;
process(i_clk_dst)
begin
if rising_edge(i_clk_dst) then
r_sync1 <= i_signal_src; -- premier registre : peut être métastable
r_sync2 <= r_sync1; -- deuxième registre : stable avec haute probabilité
end if;
end process;
o_signal_dst <= r_sync2;Le premier registre peut se retrouver en état métastable, mais le second cycle lui laisse le temps de se stabiliser.
Règle : ne jamais utiliser directement un signal issu d'un autre domaine d'horloge sans synchroniseur.