Table of Contents
Comprendre la réinitialisation asynchrone dans le design numérique
La mise en œuvre de la logique de réinitialisation asynchrone dans VHDL est un aspect fondamental de la création de conceptions numériques robustes et fiables. Que vous développiez des systèmes FPGA ou des implémentations ASIC, il est essentiel de comprendre comment mettre en œuvre correctement les mécanismes de réinitialisation pour que vos circuits puissent être initialisés de façon fiable à un état connu.
Une réinitialisation asynchrone est un signal de commande qui fonctionne indépendamment du signal d'horloge, permettant de réinitialiser immédiatement les tongs et autres éléments séquentiels dès l'affirmation. Une réinitialisation asynchrone s'active dès que le signal de réinitialisation est affirmé. Cette caractéristique de réponse immédiate distingue les réinitialisations asynchrones de leurs homologues synchrones et les rend particulièrement utiles dans des scénarios de conception spécifiques.
Ce qui rend asynchrone de réinitialiser différent
Le circuit de réinitialisation asynchrone est indépendant de l'horloge libre. Ce qui signifie que le circuit de réinitialisation n'a pas eu connaissance de l'entrée de l'horloge. Cette indépendance du domaine de l'horloge fournit plusieurs caractéristiques uniques que les concepteurs doivent comprendre et expliquer dans leurs implémentations.
La distinction clé entre réinitialisation asynchrone et synchrone réside dans leur relation de synchronisation avec l'horloge du système. Une réinitialisation synchrone s'active sur le bord actif de l'horloge lorsque le signal de réinitialisation est affirmé. En revanche, les réinitialisations asynchrones prennent effet immédiatement, indépendamment de l'état ou du moment de l'horloge.
Quand utiliser Asynchronous Réinitialiser
L'un des principaux avantages est leur capacité à fournir des fonctionnalités de réinitialisation immédiates et indépendantes, car le signal de réinitialisation peut être affirmé à tout moment, indépendamment du signal de l'horloge. Cela peut être particulièrement utile dans les situations où un système doit être réinitialisé immédiatement, sans attendre le prochain cycle de l'horloge.
La réinitialisation peut se produire lorsque l'horloge ne tourne pas, par exemple lors de l'initialisation en mode d'alimentation ou lorsque les sources d'horloge sont instables. La réinitialisation asynchrone, par définition, n'a pas besoin d'une horloge pour être présente et il pourrait être nécessaire d'utiliser ce type de réinitialisation dans certaines situations – par exemple, les primitives MMCM et PLL de Xilinx ont une réinitialisation asynchrone pour s'assurer qu'ils vont à un état connu même si l'horloge d'entrée n'est pas présente.
Mise en œuvre de la réinitialisation asynchrone dans VHDL
La bonne mise en œuvre de la logique de réinitialisation asynchrone dans VHDL nécessite une attention particulière au style de codage et aux listes de sensibilité au processus. L'approche standard consiste à créer un processus sensible au signal d'horloge et au signal de réinitialisation, en veillant à ce que la réinitialisation puisse prendre effet immédiatement lorsqu'elle est affirmée.
Structure de base de remise en état asynchrone
La structure fondamentale pour la mise en œuvre de la réinitialisation asynchrone en VHDL suit un modèle bien établi. L'extrait de code ci-dessous montre une implémentation standard d'un processus synchrone avec une réinitialisation synchrone. Pour la réinitialisation asynchrone, la liste de sensibilité du processus doit comprendre à la fois les signaux d'horloge et de réinitialisation.
Voici un exemple de base de l'implémentation de réinitialisation asynchrone :
library IEEE;
use IEEE.std_logic_1164.all;
entity dff_async_reset is
port(
clk : in std_logic;
reset : in std_logic;
d : in std_logic;
q : out std_logic
);
end dff_async_reset;
architecture behavioral of dff_async_reset is
begin
process(clk, reset)
begin
if reset = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
end behavioral;
Dans cette implémentation, le processus est sensible à la fois clk et [reset[. Lorsque le signal de réinitialisation est affirmé (logical '1' dans ce cas), la sortie q est immédiatement réglée à '0', quel que soit l'état de l'horloge.
Registre multibits avec réinitialisation asynchrone
Pour les conceptions plus complexes impliquant des registres multibits ou des machines d'état, le même principe s'applique mais avec des signaux supplémentaires à gérer. Voici un exemple de registre 8 bits avec réinitialisation asynchrone:
library IEEE;
use IEEE.std_logic_1164.all;
entity register_async is
port(
clk : in std_logic;
reset : in std_logic;
d_in : in std_logic_vector(7 downto 0);
q_out : out std_logic_vector(7 downto 0)
);
end register_async;
architecture behavioral of register_async is
begin
process(clk, reset)
begin
if reset = '1' then
q_out <= (others => '0');
elsif rising_edge(clk) then
q_out <= d_in;
end if;
end process;
end behavioral;
La construction (autres => '0') offre un moyen pratique d'initialiser tous les bits du vecteur à zéro, assurant une couverture de réinitialisation complète sur toute la largeur du registre.
Lutte contre la mise en œuvre avec la réinitialisation asynchrone
Les compteurs sont des éléments de base communs dans les conceptions numériques et bénéficient de manière significative d'une mise en œuvre correcte de la réinitialisation. Voici un exemple complet d'un compteur avec réinitialisation asynchrone:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity counter_async is
port(
clk : in std_logic;
reset : in std_logic;
enable : in std_logic;
count : out std_logic_vector(7 downto 0)
);
end counter_async;
architecture behavioral of counter_async is
signal count_reg : unsigned(7 downto 0);
begin
process(clk, reset)
begin
if reset = '1' then
count_reg <= (others => '0');
elsif rising_edge(clk) then
if enable = '1' then
count_reg <= count_reg + 1;
end if;
end if;
end process;
count <= std_logic_vector(count_reg);
end behavioral;
Ce compteur démontre la structure hiérarchique de la logique conditionnelle dans les implémentations de réinitialisation asynchrones. La vérification de réinitialisation se produit en premier et prend la plus haute priorité, suivie par la détection du bord de l'horloge, et enfin la condition d'activation pour un fonctionnement normal.
Machine d'État avec réinitialisation asynchrone
Les machines à état finite (FSM) sont des composants critiques des systèmes numériques, et une mise en œuvre correcte de la réinitialisation garantit qu'elles démarrent toujours dans un état connu et sûr. Voici un exemple d'un simple FSM avec réinitialisation asynchrone:
library IEEE;
use IEEE.std_logic_1164.all;
entity fsm_async is
port(
clk : in std_logic;
reset : in std_logic;
input : in std_logic;
output: out std_logic
);
end fsm_async;
architecture behavioral of fsm_async is
type state_type is (IDLE, ACTIVE, DONE);
signal current_state, next_state : state_type;
begin
-- State register with asynchronous reset
process(clk, reset)
begin
if reset = '1' then
current_state <= IDLE;
elsif rising_edge(clk) then
current_state <= next_state;
end if;
end process;
-- Next state logic
process(current_state, input)
begin
case current_state is
when IDLE =>
if input = '1' then
next_state <= ACTIVE;
else
next_state <= IDLE;
end if;
when ACTIVE =>
next_state <= DONE;
when DONE =>
next_state <= IDLE;
end case;
end process;
-- Output logic
output <= '1' when current_state = ACTIVE else '0';
end behavioral;
Cette implémentation FSM sépare le registre d'état (avec réinitialisation asynchrone) de la logique combinée de l'état suivant, suivant les meilleures pratiques pour la conception de la machine d'état. La réinitialisation assure que le FSM commence toujours dans l'état IDLE, fournissant un comportement d'initialisation prévisible.
Défis critiques avec la réinitialisation asynchrone
Bien que les réinitialisateurs asynchrones offrent une réponse immédiate et une opération indépendante de l'horloge, ils présentent plusieurs défis que les concepteurs doivent relever avec soin pour assurer une exploitation fiable.
Métastabilité et réinitialisation de la désaffirmation
Le défi le plus important avec les réinitialisations asynchrones se produit lors de la désassertion de réinitialisation (release). Les réinitialisations asynchrones ont cependant un problème majeur : la désassertion de réinitialisation n'est pas garantie au même bord de l'horloge pour tous les primitifs synchrones dans la conception.
Cependant, lorsque la remise à zéro est annulée et ne passe pas le contrôle de temps de récupération (μtSU) ou de suppression (μtH) (l'analyse de récupération et de suppression de l'analyse de l'analyse de calendrier et des deux contrôles), le bord est dit être tombé dans la zone de métastabilité. Il faut du temps supplémentaire pour déterminer l'état correct, et le retard peut faire que le temps de configuration ne s'enregistre pas en aval, ce qui entraîne une défaillance du système.
Réinitialiser la distribution et le calendrier
En plus des problèmes de synchronisation, la distribution d'une réinitialisation asynchrone à des millions de tongs est difficile, nécessitant des techniques similaires à celles de la synthèse des arbres de clock (CTS) et nécessitant des ressources similaires pour les zones et les routages, ce qui fait de la réinitialisation de la distribution une préoccupation critique dans les conceptions modernes et complexes de FPGA et de ASIC.
L'opération de réinitialisation asynchrone doit être coordonnée avec le signal d'horloge logique synchrone pour éliminer les défaillances de synchronisation en raison d'une possible discorde entre la réinitialisation et l'horloge. Un manque de coordination conduit à des défaillances intermittentes sur la puissance vers le haut. Ces défaillances peuvent être particulièrement problématiques parce qu'elles ne peuvent pas apparaître lors des essais initiaux mais se manifester dans les environnements de production.
Sensibilité des glitchs
Contrairement aux réinitialisations synchrones, qui ne sont échantillonnées qu'aux bords de l'horloge et qui ont donc un filtrage naturel, les réinitialisations asynchrones répondent à toute transition sur le signal de réinitialisation. Cette sensibilité signifie que le conditionnement et le routage appropriés de la réinitialisation deviennent des considérations critiques de conception.
Réinitialiser les techniques de synchronisation
Pour relever les défis associés à la désassertion asynchrone de réinitialisation, les concepteurs utilisent généralement des techniques de réinitialisation qui combinent les avantages de l'affirmation asynchrone avec la désassertion synchrone.
Assert asynchrone, Deassert synchrone
Nous pouvons affirmer la réinitialisation de manière synchrone et la désasserger asynchrone. Un tel circuit est appelé synchroniseur de réinitialisation. Cette approche, souvent appelée « async affirm, synchronise désassert », fournit le meilleur des deux mondes : la capacité de réinitialisation immédiate au besoin, avec une libération contrôlée et synchronisée pour éviter les problèmes de métastabilité.
Voici une implémentation VHDL d'un synchroniseur de réinitialisation :
library IEEE;
use IEEE.std_logic_1164.all;
entity reset_synchronizer is
port(
clk : in std_logic;
async_reset: in std_logic;
sync_reset : out std_logic
);
end reset_synchronizer;
architecture behavioral of reset_synchronizer is
signal reset_sync_reg : std_logic_vector(1 downto 0);
attribute ASYNC_REG : string;
attribute ASYNC_REG of reset_sync_reg : signal is "TRUE";
begin
process(clk, async_reset)
begin
if async_reset = '1' then
reset_sync_reg <= (others => '1');
elsif rising_edge(clk) then
reset_sync_reg <= reset_sync_reg(0) & '0';
end if;
end process;
sync_reset <= reset_sync_reg(1);
end behavioral;
Ce synchroniseur utilise un registre de décalage à deux étapes pour synchroniser la désaffirmation de réinitialisation. Lorsque la réinitialisation asynchrone est affirmée, les deux étapes se tournent immédiatement vers «1». Lorsque la réinitialisation est libérée, les zéros sont déplacés par le registre de manière synchrone avec l'horloge, assurant ainsi que le signal de réinitialisation synchronisé final est désaffirmé proprement à un bord de l'horloge.
Cela garantira que les éléments synchrones de chaque domaine d'horloge sortent de la réinitialisation en même temps (c'est-à-dire au même bord de l'horloge). L'attribut ASYNC REG aide les outils de synthèse et de localisation et d'acheminement à comprendre que ces registres forment une chaîne de synchronisation et doivent être placés étroitement ensemble pour minimiser les risques de métastabilité.
Synchronisation multi-stage
Pour éviter cela, ajoutez quelques registres de suivi après le registre avec la réinitialisation asynchrone et utilisez la sortie de ces registres dans la conception. Le nombre d'étapes de synchronisation dépend des exigences spécifiques et des cibles MBBF (Mean Time Between Faills) pour votre conception.
Pour les applications critiques, un synchroniseur en trois étapes peut être approprié:
library IEEE;
use IEEE.std_logic_1164.all;
entity reset_sync_3stage is
port(
clk : in std_logic;
async_reset: in std_logic;
sync_reset : out std_logic
);
end reset_sync_3stage;
architecture behavioral of reset_sync_3stage is
signal sync_chain : std_logic_vector(2 downto 0);
attribute ASYNC_REG : string;
attribute ASYNC_REG of sync_chain : signal is "TRUE";
begin
process(clk, async_reset)
begin
if async_reset = '1' then
sync_chain <= (others => '1');
elsif rising_edge(clk) then
sync_chain <= sync_chain(1 downto 0) & '0';
end if;
end process;
sync_reset <= sync_chain(2);
end behavioral;
Chaque étape supplémentaire de la chaîne de synchronisation réduit la probabilité de métastabilité se propageant jusqu'à la logique de conception, au prix de la latence supplémentaire dans la désassertion de remise.
Synchronisation de la réinitialisation par domaine de verrouillage
En général, un de ces circuits de synchronisation sera nécessaire pour chaque domaine d'horloge asynchrone. Dans les conceptions multi-horloges, chaque domaine d'horloge devrait avoir son propre synchroniseur de réinitialisation pour assurer un séquençage de réinitialisation approprié dans ce domaine.
Voici un exemple d'architecture pour un système de domaine à double horloge :
library IEEE;
use IEEE.std_logic_1164.all;
entity multi_clock_reset is
port(
clk_a : in std_logic;
clk_b : in std_logic;
async_reset : in std_logic;
reset_a : out std_logic;
reset_b : out std_logic
);
end multi_clock_reset;
architecture behavioral of multi_clock_reset is
component reset_synchronizer is
port(
clk : in std_logic;
async_reset: in std_logic;
sync_reset : out std_logic
);
end component;
begin
-- Reset synchronizer for clock domain A
sync_a: reset_synchronizer
port map(
clk => clk_a,
async_reset => async_reset,
sync_reset => reset_a
);
-- Reset synchronizer for clock domain B
sync_b: reset_synchronizer
port map(
clk => clk_b,
async_reset => async_reset,
sync_reset => reset_b
);
end behavioral;
Cette architecture garantit que chaque domaine horloge a un signal de réinitialisation correctement synchronisé, empêchant les violations de calendrier et les problèmes de métastabilité qui pourraient survenir à l'aide d'une seule réinitialisation sur plusieurs domaines horloge.
Meilleures pratiques pour la mise en œuvre de la réinitialisation asynchrone
Pour réussir la mise en oeuvre de la logique de réinitialisation asynchrone, il faut respecter les pratiques exemplaires établies qui ont été affinées au fil des années d'expérience de l'industrie et des leçons tirées des échecs de conception.
Réinitialisation cohérente de la polarité
Choisissez une remise à niveau active-haute ou active-bas et collez-la à tous les modules. Bien que le choix entre une remise à niveau active-haute et active-bas soit souvent une question de convention ou de technologie cible, la cohérence est essentielle pour maintenir et réduire les erreurs.
Pour les modèles FPGA, considérez la polarité de réinitialisation native des tongs de l'appareil cible. Certaines familles FPGA ont des ressources de réinitialisation actives-hautes, tandis que d'autres utilisent des ressources actives-bas.
Couverture complète de la réinitialisation des signaux
La meilleure pratique est donc : si un processus synchrone a une réinitialisation, assurez-vous de réinitialiser tous les signaux écrits dans le processus. Ce principe s'applique également aux implémentations de réinitialisation asynchrones.
Voici un exemple montrant une couverture de réinitialisation complète adéquate :
-- GOOD: All signals reset
process(clk, reset)
begin
if reset = '1' then
signal_a <= '0';
signal_b <= '0';
signal_c <= (others => '0');
elsif rising_edge(clk) then
signal_a <= input_a;
signal_b <= input_b;
signal_c <= input_c;
end if;
end process;
-- BAD: Incomplete reset
process(clk, reset)
begin
if reset = '1' then
signal_a <= '0';
-- signal_b and signal_c not reset!
elsif rising_edge(clk) then
signal_a <= input_a;
signal_b <= input_b;
signal_c <= input_c;
end if;
end process;
Réinitialiser La synchronisation est obligatoire
Utilisez toujours des synchroniseurs de réinitialisation pour la désassertion asynchrone. La mise en garde est que vous devez synchroniser les sources de réinitialisation à chaque domaine d'horloge de votre FPGA, c'est-à-dire utiliser le synchroniseur de réinitialisation PietervanStar posté. Ce n'est pas optionnel pour des conceptions fiables – c'est une exigence fondamentale.
L'approche de réinitialisation synchronisée offre plusieurs avantages :
- Élimine les risques de métastabilité lors de la réinitialisation
- S'assure que toutes les flower-flops dans un domaine horloge réinitialisent simultanément
- Fournit une initialisation prévisible de la machine d'état
- Simplifie l'analyse du moment et la fermeture
- Réduit la probabilité de défaillances intermittentes
Gestion adéquate de la liste de sensibilité
Pour les processus de réinitialisation asynchrone, la liste de sensibilité doit comprendre à la fois les signaux d'horloge et de réinitialisation. L'omission de la réinitialisation de la liste de sensibilité entraînera une inadéquation synthèse-simulation, où la simulation se comporte différemment du matériel synthétisé.
-- CORRECT: Both clk and reset in sensitivity list
process(clk, reset)
begin
if reset = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
-- INCORRECT: Missing reset in sensitivity list
process(clk) -- WRONG!
begin
if reset = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
Réinitialiser l'acheminement et la distribution des signaux
Faites attention à réinitialiser le routage des signaux, en particulier dans les grands modèles. Utilisez des ressources dédiées de réinitialisation globale lorsque disponibles dans votre FPGA cible. Ces ressources sont spécifiquement conçues pour la distribution basse-couture des signaux de contrôle comme la réinitialisation.
Pour les très grandes conceptions, envisagez de mettre en place un réseau de distribution de réinitialisation hiérarchique où un synchroniseur de réinitialisation primaire alimente des synchroniseurs secondaires pour différentes régions ou modules de la conception.
Évitez de mélanger les types de réinitialisation
Le gros problème que de nombreux concepteurs font est qu'ils mélangent leurs réinitialisations synchrones et asynchrones ensemble pour conduire le port de réinitialisation asynchrone sur le FF. Cette pratique crée des scénarios de chronométrage complexes et peut conduire à des problèmes difficiles à résoudre.
Si vous avez besoin de réinitialiser (asynchrone) et de réinitialiser (synchrone) les fonctions, mettez-les en œuvre séparément et documentez clairement leurs buts et interactions.
Vérification de l'échantillon
Inclure des tests complets de remise à zéro dans vos testbenches.
- Réinitialise l'affirmation correctement initialise tous les éléments d'état
- La réinitialisation peut être affirmée à tout moment pendant l'opération
- La conception récupère correctement de la réinitialisation
- Réinitialiser la désassertion ne provoque pas de métastabilité ou de violations de calendrier
- Plusieurs cycles de réinitialisation/libération fonctionnent correctement
Voici un modèle de testbench qui comprend des tests de réinitialisation approfondis :
library IEEE;
use IEEE.std_logic_1164.all;
entity tb_reset_test is
end tb_reset_test;
architecture testbench of tb_reset_test is
signal clk : std_logic := '0';
signal reset : std_logic := '1';
signal data : std_logic := '0';
signal q : std_logic;
constant CLK_PERIOD : time := 10 ns;
begin
-- Clock generation
clk <= not clk after CLK_PERIOD/2;
-- DUT instantiation
dut: entity work.dff_async_reset
port map(
clk => clk,
reset => reset,
d => data,
q => q
);
-- Test process
process
begin
-- Test 1: Initial reset
reset <= '1';
wait for 50 ns;
assert q = '0' report "Reset failed" severity error;
-- Test 2: Release reset and verify operation
reset <= '0';
wait for 20 ns;
data <= '1';
wait until rising_edge(clk);
wait for 1 ns;
assert q = '1' report "Normal operation failed" severity error;
-- Test 3: Asynchronous reset during operation
wait for 30 ns;
reset <= '1';
wait for 1 ns;
assert q = '0' report "Async reset failed" severity error;
-- Test 4: Reset release at various clock phases
reset <= '0';
wait for 3 ns; -- Release at arbitrary time
wait until rising_edge(clk);
wait for 50 ns;
-- Test 5: Multiple reset cycles
for i in 1 to 5 loop
reset <= '1';
wait for 15 ns;
reset <= '0';
wait for 25 ns;
end loop;
report "All tests passed" severity note;
wait;
end process;
end testbench;
Asynchrone vs synchrone reset: Faire le choix
Le choix entre une remise à zéro synchrone ou asynchrone dépend de la nature de la logique en cours de remise à zéro et des exigences du projet. Il est essentiel de comprendre les compromis entre ces approches pour prendre des décisions éclairées en matière de conception.
Avantages de la réinitialisation asynchrone
Les réinitialisateurs asynchrones offrent plusieurs avantages convaincants :
- Fonctionnement indépendant du verrouillage:[ Le circuit peut être réinitialisé même lorsque l'horloge ne tourne pas ou est instable
- Réponse immédiate :[ La réinitialisation prend effet instantanément sans attendre un bord de l'horloge
- Initialisation à puissance:[ Permet une initialisation fiable pendant les séquences de puissance avant que les horloges se stabilisent
- Simpler datapath: Contrairement à la réinitialisation synchrone, la réinitialisation asynchrone n'est pas insérée dans la datapath et n'a pas d'incidence négative sur les temps d'arrivée des données entre les registres.
- Efficacité du logiciel :[ Utilise des broches de réinitialisation dédiées sur les tongs plutôt que de consommer des ressources logiques
Avantages de la réinitialisation synchrone
Les réinitialisations synchrones offrent également des avantages importants :
- Temps prévisible: Les réinitialisations synchrones sont prévisibles (au bord de l'horloge) Les réinitialisations synchrones sont robustes a.o. contre les problèmes
- Aucun problème de métastabilité:[ En synchronisant le signal de réinitialisation à l'horloge, les concepteurs peuvent s'assurer que l'opération de réinitialisation se produit à un point connu et stable du moment du système, réduisant ainsi le risque de comportement imprévisible.
- Meilleur pour la synthèse FPGA: Les outils de synthèse peuvent fusionner un signal de réinitialisation synchrone dans la logique du chemin de données (c.-à-d. les LUT qui conduisent l'entrée Flip-Flop D). Cela réduit le fanout sur le signal de réinitialisation et aussi le nombre de commandes qui, à son tour, améliore l'emballage du dispositif.
- Compatibilité primordiale: Si vous comptez sur les outils pour déduire certains primitifs tels que DPS48s ou BRAMs, cela n'est possible que si vous avez codé une réinitialisation synchrone – ces primitifs ne supportent pas les réinitialisations asynchrones.
Pratiques et recommandations de l'industrie
En général, les réinitialisations synchrones sont recommandées à moins que le circuit particulier ne nécessite une réinitialisation asynchrone. Le choix peut dépendre de la technologie utilisée, p. ex. certains blocs FPGA peuvent seulement supporter une réinitialisation synchrone.
Pour les modèles ASIC, les réinitialisations asynchrones restent courantes, notamment pour les scénarios de réinitialisation en mode puissance. Pour les modèles FPGA, les recommandations des fournisseurs favorisent de plus en plus les réinitialisations synchrones ou l'approche hybride de l'affirmation asynchrone avec une désaffirmation synchrone.
Si non, préférez une réinitialisation synchrone. Utilisez uniquement une réinitialisation asynchrone avec des éléments logiques qui exigent explicitement cela (en particulier les primitives complexes FPGA et les cœurs IP, par exemple les émetteurs-récepteurs et les contrôleurs de bus), et même ainsi, essayez d'utiliser le signal de réinitialisation synchrone si possible.
Techniques et modèles de réinitialisation avancés
Au-delà de la mise en œuvre de la réinitialisation de base, plusieurs techniques avancées peuvent améliorer la robustesse et la fonctionnalité de la logique de réinitialisation dans des conceptions complexes.
Génération de puissance sur remise en marche
De nombreuses conceptions FPGA nécessitent une réinitialisation qui s'affirme automatiquement pendant la configuration du dispositif et se libère après la stabilisation des horloges. Voici un modèle pour générer une réinitialisation fiable :
library IEEE;
use IEEE.std_logic_1164.all;
entity power_on_reset is
generic(
RESET_CYCLES : integer := 16 -- Number of clock cycles to hold reset
);
port(
clk : in std_logic;
por_reset : out std_logic
);
end power_on_reset;
architecture behavioral of power_on_reset is
signal reset_counter : integer range 0 to RESET_CYCLES := RESET_CYCLES;
signal reset_reg : std_logic := '1';
begin
process(clk)
begin
if rising_edge(clk) then
if reset_counter > 0 then
reset_counter <= reset_counter - 1;
reset_reg <= '1';
else
reset_reg <= '0';
end if;
end if;
end process;
por_reset <= reset_reg;
end behavioral;
Ce générateur de réinitialisation utilise les capacités d'initialisation du FPGA pour démarrer le compteur à sa valeur maximale, assurant que la réinitialisation est assurée immédiatement après la configuration. La réinitialisation reste revendiquée pour un nombre programmable de cycles d'horloge, fournissant du temps pour les LPL et autres circuits à stabiliser.
Mise en œuvre de la remise en état conditionnelle
Dans certains modèles, tous les registres ne doivent pas être réinitialisés. Les registres de chemin de données qui sont garantis être chargés avec des données valides avant l'utilisation peuvent souvent omettre la logique de réinitialisation, économiser des ressources et améliorer le timing.
architecture behavioral of mixed_reset is
signal control_state : state_type;
signal data_pipeline : std_logic_vector(31 downto 0);
begin
-- Control logic: MUST have reset
control_proc: process(clk, reset)
begin
if reset = '1' then
control_state <= IDLE;
elsif rising_edge(clk) then
-- state machine logic
end if;
end process;
-- Data pipeline: No reset needed if always loaded before use
data_proc: process(clk)
begin
if rising_edge(clk) then
if data_valid = '1' then
data_pipeline <= input_data;
end if;
end if;
end process;
end behavioral;
Cette approche sélective de remise à zéro peut réduire considérablement l'utilisation des ressources dans les grands projets, mais elle nécessite une analyse minutieuse pour s'assurer que les registres non remis à zéro ne peuvent pas causer de problèmes lors de l'initialisation ou après la remise à zéro.
Réinitialiser les priorités et la hiérarchie
Dans les conceptions avec plusieurs sources de réinitialisation (power-on reset, bouton externe reset, réinitialisation du chronomètre de veille, etc.), établir une hiérarchie de priorité claire:
library IEEE;
use IEEE.std_logic_1164.all;
entity reset_manager is
port(
clk : in std_logic;
por_reset : in std_logic; -- Power-on reset (highest priority)
external_reset: in std_logic; -- External reset button
watchdog_reset: in std_logic; -- Watchdog timer reset
system_reset : out std_logic -- Combined system reset
);
end reset_manager;
architecture behavioral of reset_manager is
signal combined_reset : std_logic;
signal sync_reset : std_logic;
begin
-- Combine all reset sources (OR logic)
combined_reset <= por_reset or external_reset or watchdog_reset;
-- Synchronize the combined reset
sync_proc: process(clk, combined_reset)
variable sync_chain : std_logic_vector(1 downto 0) := (others => '1');
begin
if combined_reset = '1' then
sync_chain := (others => '1');
elsif rising_edge(clk) then
sync_chain := sync_chain(0) & '0';
end if;
sync_reset <= sync_chain(1);
end process;
system_reset <= sync_reset;
end behavioral;
Ce gestionnaire de réinitialisation combine plusieurs sources de réinitialisation et fournit une sortie de réinitialisation unique et synchronisée pour le reste de la conception, simplifie la réinitialisation de la distribution et assure un comportement cohérent.
Contraintes de calendrier et analyse pour la réinitialisation asynchrone
Des contraintes de temps adéquates sont essentielles pour garantir que les circuits de réinitialisation asynchrones répondent à leurs exigences de temps et fonctionnent de manière fiable.
Calendrier de récupération et de suppression
Les signaux de réinitialisation asynchrones doivent répondre aux exigences de temps de récupération et de suppression par rapport à l'horloge. TimeQuest analysera vos chemins de réinitialisation synchronisés via le temps de réinitialisation et de suppression. Ces vérifications de temps garantissent que lorsque la réinitialisation est annulée, il ne viole pas les exigences de configuration et de temps de maintien.
Le temps de récupération est analogue au temps de configuration — le temps minimum de réinitialisation doit être annulé avant le bord actif de l'horloge. Le temps de suppression est analogue au temps de maintien — le temps minimum de réinitialisation doit rester annulé après le bord actif de l'horloge.
Contraintes de la DSC pour la remise des chemins
Pour une analyse de temps appropriée, limitez vos chemins de réinitialisation de manière appropriée. Voici des contraintes SDC pour la réinitialisation asynchrone :
# Set false path for asynchronous reset assertion
# (Reset assertion is asynchronous and doesn't need timing analysis)
set_false_path -from [get_ports async_reset] -to [all_registers] -setup
# Constrain reset recovery/removal timing
# (Reset deassertion must meet timing)
set_max_delay -from [get_ports async_reset] -to [all_registers] 5.0
# For reset synchronizer chains, preserve registers
set_preserve_register [get_cells reset_sync_reg*]
# Mark synchronizer registers with ASYNC_REG property
set_property ASYNC_REG TRUE [get_cells reset_sync_reg*]
Ces contraintes indiquent à l'analyseur de temps d'ignorer l'affirmation asynchrone de réinitialisation (puisque cela est censé être asynchrone) tout en vérifiant que la réinitialisation de la désassertion répond aux exigences de chronométrage à travers la chaîne de synchronisation.
Réinitialiser le calendrier de distribution
Dans les grandes conceptions, la distribution de signaux de réinitialisation peut devenir un goulot d'étranglement de la chronologie.
- Utiliser des réseaux de réinitialisation mondiaux spécialisés fournis par le FPGA
- Mettre en œuvre des synchroniseurs régionaux de réinitialisation pour réduire les fan-out
- Signalisation de remise en état des pipelines pour des conceptions très importantes
- Utiliser le positionnement en fonction du moment pour réinitialiser les chaînes de synchronisation
Pièges courants et comment les éviter
Comprendre les erreurs courantes dans l'implémentation asynchrone de la réinitialisation aide les concepteurs à éviter les séances de débogage coûteuses et les défaillances potentielles sur le terrain.
Piège 1: Oublier la synchronisation de la réinitialisation
L'erreur la plus courante et la plus dangereuse est d'utiliser la réinitialisation asynchrone sans synchronisation appropriée de la désassertion. Cela peut conduire à des défaillances intermittentes qui sont extrêmement difficiles à déboguer car elles dépendent de la relation précise entre la réinitialisation et les bords de l'horloge.
Solution: Utilisez toujours un synchroniseur de réinitialisation pour la désassertion asynchrone. Faites de cette pratique une pratique standard dans votre méthodologie de conception.
Piège 2 : Listes incomplètes de sensibilité
L'omission du signal de réinitialisation de la liste de sensibilité de processus crée un décalage entre la synthèse et la simulation. La simulation traitera la réinitialisation comme synchrone (uniquement cochée aux bords de l'horloge), tandis que la synthèse mettra correctement en œuvre la réinitialisation asynchrone.
Solution: Inclure toujours à la fois l'horloge et la réinitialisation dans la liste de sensibilité pour les processus de réinitialisation asynchrone. Utilisez le de VHDL-2008 si vos outils le supportent, ou soyez méticuleux sur les listes de sensibilité.
Piège 3 : Mélanger les styles de remise à zéro
La combinaison de la logique de réinitialisation synchrone et asynchrone, ou l'utilisation de polarités de réinitialisation différentes dans différentes parties du modèle, crée de la confusion et augmente la probabilité d'erreurs.
Solution:[ Établir et documenter une stratégie de réinitialisation cohérente pour l'ensemble de votre projet.
Piège 4: Mauvaise remise en état Pulse Largeur
Si l'impulsion de réinitialisation est trop courte, certaines flipp-flops peuvent ne pas se réinitialiser correctement, en particulier dans les grandes conceptions avec un retard de distribution de réinitialisation important.
Solution: Assurez-vous que les impulsions de réinitialisation sont suffisamment larges pour garantir que toutes les tongs reçoivent une durée de réinitialisation adéquate.
Piège 5 : Ignorer la remise en état dans les bancs d'essai
De nombreux testbenches testent mal la fonctionnalité de réinitialisation, manquant des problèmes potentiels qui se manifestent seulement pendant les séquences de réinitialisation.
Solution:[ Inclure des tests complets de réinitialisation: réinitialisation initiale, réinitialisation pendant l'opération, plusieurs cycles de réinitialisation et réinitialisation à différentes phases de l'horloge.
Considérations spécifiques à l'AGPF
Différents fournisseurs et familles de fournisseurs de FPGA ont des caractéristiques et des recommandations spécifiques concernant la mise en œuvre de la remise en service que les concepteurs devraient comprendre.
Xilinx FPGA
Les FPGA Xilinx ont des capacités d'initialisation intégrées qui placent toutes les flower-flops à un état connu après la configuration. Cela signifie que pour de nombreux modèles, une logique de réinitialisation explicite peut ne pas être nécessaire pour l'initialisation.
Xilinx recommande généralement des réinitialisations synchrones pour la plupart des applications, car elles s'intègrent mieux au tissu FPGA et ne consomment pas les ressources dédiées à la mise en série/reset asynchrones qui pourraient être utilisées à d'autres fins.
Intel (Altera) FPGA
Les registres des appareils Altera ont des ports de réinitialisation asynchrones, de sorte que vous devriez écrire votre code de manière à ce qu'il les utilise. La mise en garde est que vous devez synchroniser les sources de réinitialisation à chaque domaine d'horloge de votre FPGA, c'est-à-dire utiliser le synchroniseur de réinitialisation PietervanStar posté.
Si vous écrivez votre code pour une réinitialisation synchrone, alors Quartus créera une logique pour implémenter votre réinitialisation synchrone, c'est-à-dire que vous utiliserez inutilement des entrées LUT. Ainsi, le "coût" d'utiliser un style incorrect, est un design plus grand, et un potentiel pour augmenter le chemin combinatoire dans votre conception.
Initialisation FPGA vs. Réinitialisation de l'exécution
Les fournisseurs FPGA ne recommandent pas d'utiliser des réinitialisations asynchrones pour les conceptions FPGA. Au lieu de cela, de nombreux modèles modernes FPGA tirent parti de l'initialisation intégrée de l'appareil pour l'état de puissance et utilisent des réinitialisations synchrones pour les exigences de réinitialisation de l'exécution.
Cette approche peut réduire considérablement l'utilisation des ressources tout en maintenant une capacité de remise en état robuste. Cependant, elle exige un examen attentif de la capacité de remise en état des temps d'exécution des registres par rapport à celle qui n'a besoin que d'initialisation.
Exemples de conception et études de cas
L'examen d'exemples complets de conception aide à mieux comprendre la mise en œuvre de la remise à zéro asynchrone dans des contextes réalistes.
Exemple 1: Récepteur UART avec réinitialisation asynchrone
Un récepteur UART démontre une utilisation pratique de réinitialisation asynchrone dans un périphérique de communication:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity uart_rx is
generic(
CLKS_PER_BIT : integer := 87 -- For 115200 baud at 10MHz clock
);
port(
clk : in std_logic;
reset : in std_logic;
rx_serial : in std_logic;
rx_data : out std_logic_vector(7 downto 0);
rx_valid : out std_logic
);
end uart_rx;
architecture behavioral of uart_rx is
type state_type is (IDLE, START_BIT, DATA_BITS, STOP_BIT);
signal state : state_type;
signal bit_counter : integer range 0 to 7;
signal clk_counter : integer range 0 to CLKS_PER_BIT-1;
signal rx_data_reg : std_logic_vector(7 downto 0);
begin
process(clk, reset)
begin
if reset = '1' then
state <= IDLE;
bit_counter <= 0;
clk_counter <= 0;
rx_data_reg <= (others => '0');
rx_valid <= '0';
elsif rising_edge(clk) then
rx_valid <= '0'; -- Default, pulse for one cycle
case state is
when IDLE =>
if rx_serial = '0' then -- Start bit detected
state <= START_BIT;
clk_counter <= 0;
end if;
when START_BIT =>
if clk_counter = CLKS_PER_BIT/2 then
if rx_serial = '0' then -- Verify start bit
state <= DATA_BITS;
clk_counter <= 0;
bit_counter <= 0;
else
state <= IDLE; -- False start
end if;
else
clk_counter <= clk_counter + 1;
end if;
when DATA_BITS =>
if clk_counter = CLKS_PER_BIT-1 then
clk_counter <= 0;
rx_data_reg(bit_counter) <= rx_serial;
if bit_counter = 7 then
state <= STOP_BIT;
else
bit_counter <= bit_counter + 1;
end if;
else
clk_counter <= clk_counter + 1;
end if;
when STOP_BIT =>
if clk_counter = CLKS_PER_BIT-1 then
if rx_serial = '1' then -- Valid stop bit
rx_valid <= '1';
rx_data <= rx_data_reg;
end if;
state <= IDLE;
else
clk_counter <= clk_counter + 1;
end if;
end case;
end if;
end process;
end behavioral;
Ce récepteur UART utilise la réinitialisation asynchrone pour s'assurer que la machine d'état peut être initialisée de manière fiable même si l'horloge n'est pas encore stable.
Exemple 2: FIFO multi-blocs avec synchronisation de réinitialisation
Un FIFO à deux heures démontre la synchronisation de réinitialisation entre les domaines de l'horloge :
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity async_fifo is
generic(
DATA_WIDTH : integer := 8;
ADDR_WIDTH : integer := 4
);
port(
-- Write clock domain
wr_clk : in std_logic;
wr_reset : in std_logic;
wr_en : in std_logic;
wr_data : in std_logic_vector(DATA_WIDTH-1 downto 0);
wr_full : out std_logic;
-- Read clock domain
rd_clk : in std_logic;
rd_reset : in std_logic;
rd_en : in std_logic;
rd_data : out std_logic_vector(DATA_WIDTH-1 downto 0);
rd_empty : out std_logic;
-- Asynchronous reset input
async_reset : in std_logic
);
end async_fifo;
architecture behavioral of async_fifo is
-- Synchronized resets for each domain
signal wr_reset_sync : std_logic;
signal rd_reset_sync : std_logic;
-- FIFO memory and pointers
type memory_type is array (0 to 2**ADDR_WIDTH-1) of
std_logic_vector(DATA_WIDTH-1 downto 0);
signal memory : memory_type;
signal wr_ptr : unsigned(ADDR_WIDTH downto 0);
signal rd_ptr : unsigned(ADDR_WIDTH downto 0);
begin
-- Reset synchronizer for write clock domain
wr_sync: entity work.reset_synchronizer
port map(
clk => wr_clk,
async_reset => async_reset,
sync_reset => wr_reset_sync
);
-- Reset synchronizer for read clock domain
rd_sync: entity work.reset_synchronizer
port map(
clk => rd_clk,
async_reset => async_reset,
sync_reset => rd_reset_sync
);
-- Write process
wr_proc: process(wr_clk, wr_reset_sync)
begin
if wr_reset_sync = '1' then
wr_ptr <= (others => '0');
elsif rising_edge(wr_clk) then
if wr_en = '1' and wr_full = '0' then
memory(to_integer(wr_ptr(ADDR_WIDTH-1 downto 0))) <= wr_data;
wr_ptr <= wr_ptr + 1;
end if;
end if;
end process;
-- Read process
rd_proc: process(rd_clk, rd_reset_sync)
begin
if rd_reset_sync = '1' then
rd_ptr <= (others => '0');
elsif rising_edge(rd_clk) then
if rd_en = '1' and rd_empty = '0' then
rd_data <= memory(to_integer(rd_ptr(ADDR_WIDTH-1 downto 0)));
rd_ptr <= rd_ptr + 1;
end if;
end if;
end process;
-- Status flags (simplified - full implementation needs Gray code)
wr_full <= '1' when (wr_ptr + 1) = rd_ptr else '0';
rd_empty <= '1' when wr_ptr = rd_ptr else '0';
end behavioral;
Ce FIFO démontre une synchronisation correcte de réinitialisation pour chaque domaine d'horloge, en veillant à ce que les côtés écriture et lecture sortent de réinitialisation proprement sans problèmes de métastabilité.
Stratégies de débogage et de vérification
Le débogage et la vérification efficaces de la logique de réinitialisation asynchrone nécessitent des stratégies et des outils spécifiques.
Techniques de simulation
Lorsque vous simulez des conceptions avec une remise à zéro asynchrone, prêtez une attention particulière à:
- Remise du timing:[ Essai réinitialiser l'affirmation et la désaffirmation à différents points du cycle de l'horloge
- Domaines multiples: Vérifiez que chaque domaine d'horloge gère correctement la réinitialisation
- Durée de remise en fonction:[ Assurez-vous que les impulsions de remise en marche sont suffisamment longues pour que toute logique puisse réinitialiser
- Compatibilité après remise:[ Vérifier que le design fonctionne correctement après la réinitialisation
Analyse statique du temps
Utilisez vos outils d'analyse de temps pour vérifier :
- Calendrier de récupération et de suppression pour tous les chemins de réinitialisation asynchrones
- Synchronisation appropriée de la désassertion de réinitialisation
- Rétablir les retards de distribution dans les grands projets
- Relations de temps entre les horloges et les réinitialisateurs
Essais matériels
Lors de l'essai dans le matériel:
- Essai de comportement de réinitialisation de puissance sur plusieurs cycles de puissance
- Vérifier que la réinitialisation fonctionne à différentes fréquences d'exploitation
- Réinitialisation de l'essai dans diverses conditions de température et de tension
- Effectuer des essais de contrainte prolongés avec des cycles de réinitialisation fréquents
- Surveiller les défaillances intermittentes qui pourraient indiquer des problèmes de métastabilité
Normes et lignes directrices de l'industrie
Plusieurs ressources de l'industrie fournissent des conseils supplémentaires sur la mise en oeuvre de la réinitialisation.Les lignes directrices Sigasi VHDL reinitialisent[ offrent une couverture complète des pratiques de réinitialisation.
Les documents de Clifford Cummings sur la synchronisation de réinitialisation sont largement considérés comme faisant autorité dans le domaine. Le site Embedded.com héberge de nombreux articles sur les techniques de réinitialisation avancées pour les conceptions ASIC et FPGA.
Pour ceux qui travaillent avec des familles FPGA spécifiques, la documentation du fournisseur fournit des informations essentielles spécifiques à un appareil. La documentation FPGA d'Intel et La documentation AMD Xilinx[ comprend des lignes directrices détaillées sur la mise en œuvre de la remise en service adaptées à leurs architectures respectives.
Résumé et principales captures
La mise en œuvre de la logique de réinitialisation asynchrone dans VHDL est une compétence critique pour les concepteurs numériques travaillant sur les projets FPGA et ASIC. Bien que les réinitialisations asynchrones fournissent une réponse immédiate et une opération indépendante de l'horloge, elles nécessitent une mise en œuvre soigneuse pour éviter les problèmes de métastabilité et de synchronisation.
Les principes clés pour une mise en œuvre robuste de la remise à zéro asynchrone sont les suivants:
- Synchronisez toujours la désassertion de réinitialisation en utilisant un synchroniseur multi-étapes
- Inclure à la fois l'horloge et la réinitialisation dans la liste de sensibilité du processus
- Réinitialisez tous les signaux écrits dans un processus pour assurer une initialisation complète
- Mettre en œuvre la synchronisation de la réinitialisation par secteur à l'heure dans les conceptions multi-heures
- Utilisez la polarité de réinitialisation constante tout au long de votre conception
- Appliquer des contraintes de temps appropriées pour l'analyse de récupération et de retrait
- Testez minutieusement la fonctionnalité de remise à zéro dans la simulation et le matériel
- Considérez les compromis entre la réinitialisation asynchrone et synchrone pour votre application spécifique
En suivant ces meilleures pratiques et en comprenant les principes sous-jacents, les ingénieurs peuvent créer des systèmes numériques robustes et fiables qui initialisent de façon prévisible et récupèrent gracieusement les conditions de réinitialisation. Que vous conçoyiez une machine d'état simple ou un système multi-horloges complexe, la réinitialisation appropriée constitue la base d'un fonctionnement fiable du matériel.
Rappelez-vous que le choix entre la remise asynchrone et la remise synchrone dépend de vos exigences spécifiques, de la technologie cible et des contraintes de conception. Dans de nombreux modèles modernes FPGA, l'approche hybride de l'affirmation asynchrone avec la désassertion synchrone offre un équilibre optimal de la capacité de remise immédiate et un fonctionnement fiable et sans métastabilité.