Chapitre 23 — Développement d’un système numérique complet
Projet final — Finalité du chapitre Mobiliser l’ensemble des acquis du cours pour spécifier, concevoir, vérifier, synthétiser, implanter et valider un système numérique hiérarchique sur FPGA. |
Objectifs pédagogiques
À la fin de ce chapitre, l’étudiant devra être capable de :
- transformer un besoin en cahier des charges vérifiable ;
- décomposer un système en composants hiérarchiques ;
- associer circuits combinatoires, registres, compteurs et machines à états ;
- définir les interfaces et les contrats temporels entre blocs ;
- développer des bancs de test unitaires et un testbench d’intégration ;
- lire les rapports de synthèse, d’utilisation et de timing ;
- créer les contraintes de broches et d’horloge ;
- générer puis charger le bitstream ;
- mettre en œuvre une validation matérielle reproductible ;
- présenter une architecture, des résultats et des limites de manière professionnelle.
Notions mobilisées
Notion | Utilisation dans le projet |
|---|---|
| Conception hiérarchique | Décomposition en blocs testables et réutilisables |
| Combinatoire | Décodage, multiplexage, calculs et génération des sorties |
| Séquentiel | Registres, mémorisation, synchronisation et pipeline |
| Machines à états | Séquençage des modes et protocoles |
| Compteurs et registres | Temporisation, mesure, stockage et décalage |
| Testbench | Vérification automatique des blocs et du système |
| Synthèse | Transformation en ressources matérielles |
| Contraintes | Broches, horloges et exigences temporelles |
| Programmation FPGA | Génération et chargement du bitstream |
| Validation matérielle | Essais réels, instrumentation et diagnostic |
Organisation du chapitre
Partie | Contenu |
|---|---|
| 23.1 | Démarche complète de développement |
| 23.2 | Architecture hiérarchique et intégration |
| 23.3 | Stratégie de vérification |
| 23.4 | Synthèse, contraintes et implantation |
| 23.5 | Validation matérielle et documentation |
| Projets 1 à 7 | Sept sujets détaillés et extensibles |
| Évaluation | Livrables, soutenance et barème |
Critère de réussite — Projet démontrable Un projet réussi ne se limite pas à un code qui compile. Il doit fournir des preuves : tests automatisés, rapports de synthèse, timing respecté, comportement observable sur carte et documentation. |
23.1 Démarche complète de développement
23.1.1 Analyse du besoin
Le projet commence par une description fonctionnelle indépendante du code VHDL.
Question | Exemple |
|---|---|
| Que doit faire le système ? | Mesurer un temps et l’afficher |
| Quelles sont les entrées ? | Boutons, clavier, liaison série |
| Quelles sont les sorties ? | LED, afficheurs, PWM, UART |
| Quelles performances ? | Précision, fréquence, latence |
| Quels cas d’erreur ? | Code faux, timeout, overflow |
| Comment valider ? | Scénarios simulés et essais sur carte |
23.1.2 Cahier des charges vérifiable
| Exemple d’exigences | Spécification |
| REQ-01 : Le système utilise l'horloge de la carte. REQ-02 : Une pression validée produit une seule action. REQ-03 : Le reset ramène le système à l'état initial. REQ-04 : La sortie est mise à jour dans la latence spécifiée. REQ-05 : Aucun latch involontaire n'est synthétisé. REQ-06 : Le timing respecte la fréquence de la carte. |
23.1.3 Exigences fonctionnelles et non fonctionnelles
Type | Exemples |
|---|---|
| Fonctionnelles | Modes, opérations, séquences, affichage, communication |
| Temporelles | Durée, fréquence, timeout, latence |
| Matérielles | Broches, tension, nombre d’afficheurs, mémoire |
| Qualité | Portabilité, réutilisation, documentation, testabilité |
| Sécurité | État sûr au reset, limitation d’essais, arrêt moteur |
23.1.4 Diagramme de contexte
| Contexte générique | Architecture |
| +----------------------+ Entrées utilisateur --->| |---> Affichage Capteurs -------------> | SYSTÈME FPGA |---> Communication Horloge / reset -------> | |---> Actionneur +----------------------+ |
23.1.5 Décomposition en fonctions
1. Acquisition et adaptation des entrées.
2. Traitement de contrôle par FSM.
3. Chemin de données : registres, compteurs, UAL ou mémoire.
4. Génération de temps et de ticks.
5. Formatage et pilotage des sorties.
6. Diagnostic et gestion des erreurs.
23.1.6 Définition des interfaces
Signal | Questions à préciser |
|---|---|
| data | Largeur, signe, format Q, ordre des bits |
| valid / ready | Quand le transfert est-il effectif ? |
| start / busy / done | Durée des impulsions et latence |
| enable | Quel registre est mis à jour ? |
| reset | Polarité et stratégie synchrone/asynchrone |
| clk | Domaine et fréquence |
23.1.7 Planification
Jalon | Résultat attendu |
|---|---|
| J1 — Spécification | Exigences, interface et architecture |
| J2 — Blocs élémentaires | Simulation unitaire réussie |
| J3 — Intégration | Testbench système réussi |
| J4 — Synthèse | Ressources et RTL analysés |
| J5 — Implantation | Timing respecté, bitstream généré |
| J6 — Validation | Scénarios matériels documentés |
| J7 — Livraison | Rapport, code, démonstration et soutenance |
23.1.8 Gestion des versions
- conserver un dépôt par projet ;
- séparer sources, tests, contraintes et documentation ;
- effectuer des commits fonctionnels ;
- étiqueter la version démontrée ;
- ne pas modifier plusieurs sous-systèmes sans test intermédiaire.
23.1.9 Arborescence recommandée
| Organisation du dépôt | Arborescence |
| projet_fpga/ ├── rtl/ │ ├── packages/ │ ├── common/ │ ├── control/ │ ├── datapath/ │ └── top/ ├── sim/ │ ├── unit/ │ └── integration/ ├── constraints/ ├── scripts/ ├── reports/ ├── doc/ └── README.md |
23.1.10 Critères de passage entre étapes
Passage | Condition minimale |
|---|---|
| Codage → intégration | Tests unitaires réussis |
| Intégration → synthèse | Testbench système sans erreur |
| Synthèse → implantation | Aucun latch ou warning critique |
| Implantation → carte | Timing respecté et broches vérifiées |
| Carte → livraison | Scénarios matériels reproductibles |
23.2 Architecture hiérarchique et intégration
23.2.1 Niveau supérieur
Le top-level associe les broches physiques aux blocs génériques et adapte les polarités.
| Squelette du top-level | VHDL |
| architecture structurelle of systeme_top is signal bouton_sync : std_logic; signal bouton_filtre : std_logic; signal impulsion : std_logic; signal affichage : std_logic_vector(15 downto 0); begin U_ENTREES : entity work.gestion_entrees(rtl) port map (...); U_CONTROLE : entity work.controleur(rtl) port map (...); U_DONNEES : entity work.chemin_donnees(rtl) port map (...); U_SORTIES : entity work.gestion_sorties(rtl) port map (...); end architecture structurelle; |
23.2.2 Séparation contrôle / chemin de données
Contrôle | Chemin de données |
|---|---|
| FSM et priorités | Registres et compteurs |
| start, enable, load | Calculs et comparaisons |
| gestion des modes | Mémoires et UAL |
| gestion des erreurs | Données affichées ou transmises |
23.2.3 Contrat entre blocs
| Handshake simple | VHDL |
| -- La source maintient data tant que ready = 0. -- Le transfert a lieu lorsque valid = 1 et ready = 1. transfert <= valid and ready; |
23.2.4 Paramétrage
| Génériques communs | VHDL |
| generic ( F_CLK_HZ : positive := 50_000_000; LARGEUR_DONNEES : positive := 8; DUREE_MS : positive := 1000 ); |
23.2.5 Paquetage du projet
| projet_pkg.vhd — Déclarations | VHDL |
| library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; package projet_pkg is subtype octet_t is std_logic_vector(7 downto 0); subtype compteur_t is unsigned(15 downto 0); type mode_t is (ARRET, ACTIF, ERREUR); function clog2(n : positive) return natural; end package projet_pkg; |
| projet_pkg.vhd — Fonction clog2 | VHDL |
| package body projet_pkg is function clog2(n : positive) return natural is variable valeur : natural := n - 1; variable bits : natural := 0; begin while valeur > 0 loop valeur := valeur / 2; bits := bits + 1; end loop; return bits; end function; end package body projet_pkg; |
23.2.6 Gestion des entrées
| Chaîne recommandée | Architecture |
| entrée_physique -> adaptation_polarité -> synchroniseur_2_ff -> anti_rebond_si_nécessaire -> détection_de_front -> logique_du_projet |
23.2.7 Base de temps partagée
Un générateur de ticks évite de créer plusieurs horloges logiques.
| Tick d’une milliseconde | VHDL |
| constant DIVISEUR_1MS : positive := F_CLK_HZ / 1000; process(clk) begin if rising_edge(clk) then tick_1ms <= '0'; if compteur_ms = DIVISEUR_1MS-1 then compteur_ms <= 0; tick_1ms <= '1'; else compteur_ms <= compteur_ms + 1; end if; end if; end process; |
23.2.8 Intégration incrémentale
1. Intégrer d’abord l’horloge, le reset et une LED de vie.
2. Ajouter la chaîne d’entrée et vérifier les impulsions.
3. Ajouter le chemin de données.
4. Ajouter la FSM de contrôle.
5. Ajouter l’affichage ou la communication.
6. Ajouter les erreurs et le diagnostic.
23.2.9 Signaux de diagnostic
- état courant de la FSM ;
- ticks et compteurs terminaux ;
- impulsions de boutons ;
- flags overflow, timeout ou erreur ;
- valid, busy et done des interfaces.
23.3 Stratégie de vérification
23.3.1 Plan de vérification
Exigence | Test | Preuve |
|---|---|---|
| Reset | Activer pendant chaque mode | État initial observé |
| Fonction nominale | Scénario principal | Assertions réussies |
| Limites | Min/max, débordement | Flags corrects |
| Erreur | Stimulus invalide | État sûr ou alarme |
| Timing fonctionnel | Compter les cycles | Latence conforme |
| Carte | Répéter le scénario | Tableau de validation |
23.3.2 Tests unitaires
- générateur de tick ;
- anti-rebond ;
- compteur ou UAL ;
- FSM ;
- driver d’affichage ;
- interface de communication.
23.3.3 Testbench d’intégration
| Squelette | VHDL |
| entity tb_systeme is end entity; architecture simulation of tb_systeme is constant PERIODE : time := 20 ns; signal clk : std_logic := '0'; signal reset : std_logic := '0'; begin clk <= not clk after PERIODE/2; DUT : entity work.systeme_top(rtl) generic map ( -- Valeurs réduites pour la simulation. F_CLK_HZ => 1000 ) port map (...); stimuli : process begin -- Reset, scénarios nominaux et erreurs. wait; end process; end architecture; |
23.3.4 Valeurs accélérées pour la simulation
Simulation — Conserver le comportement Réduire un nombre de cycles est acceptable si le rapport entre événements reste cohérent. Les valeurs réelles sont restaurées pour la synthèse. |
23.3.5 Procédures de stimulus
| Appui de bouton réutilisable | VHDL |
| procedure appuyer( signal bouton : out std_logic; constant duree : time ) is begin bouton <= '1'; wait for duree; bouton <= '0'; end procedure; |
23.3.6 Assertions
| Validation d’un état | VHDL |
| assert etat_observe = ETAT_ATTENDU report "État incorrect après le scénario" severity error; |
| Timeout global | VHDL |
| timeout : process begin wait for 10 ms; assert false report "Timeout du projet final" severity failure; end process; |
23.3.7 Couverture des scénarios
Catégorie | Exemples |
|---|---|
| Nominal | Utilisation prévue du début à la fin |
| Limite | Valeur maximale, passage 59→00, duty 0/100 % |
| Erreur | Code faux, trame invalide, overflow |
| Reset | Reset dans chaque état |
| Concurrence | Deux boutons simultanés ou demandes proches |
| Endurance | Nombreuses répétitions |
23.3.8 Régression
Chaque bug découvert pendant l’intégration ou sur carte devient un cas de test permanent.
23.4 Synthèse, contraintes et implantation
23.4.1 Vérifications avant synthèse
- aucune erreur du testbench ;
- aucun latch involontaire ;
- toutes les tailles et conversions vérifiées ;
- entité supérieure correcte ;
- valeurs réelles des génériques restaurées ;
- sources de simulation exclues du top synthétisable.
23.4.2 Ressources à analyser
Ressource | Question |
|---|---|
| LUT | La logique combinatoire est-elle raisonnable ? |
| Bascules | Les registres correspondent-ils à l’architecture ? |
| BRAM | Les mémoires sont-elles inférées ? |
| DSP | Les multiplications utilisent-elles les blocs dédiés ? |
| Clocking | Les horloges utilisent-elles les ressources prévues ? |
| I/O | Le nombre de broches est-il compatible ? |
23.4.3 Contraintes d’horloge
| Exemple XDC | Contraintes |
| create_clock -period 20.000 \ -name clk_carte \ [get_ports clk_carte] |
23.4.4 Contraintes de broches
| Exemple conceptuel | Contraintes |
| set_property PACKAGE_PIN <PIN_CLK> [get_ports clk_carte] set_property IOSTANDARD LVCMOS33 [get_ports clk_carte] set_property PACKAGE_PIN <PIN_LED0> [get_ports {leds[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {leds[0]}] |
23.4.5 Analyse temporelle
Indicateur | Condition |
|---|---|
| WNS | Doit être positif ou nul pour le setup |
| TNS | Doit être nul en absence de violation |
| Hold | Aucune violation de maintien |
| Unconstrained paths | Aucun chemin important non contraint |
| Fmax | Compatible avec la fréquence réelle |
23.4.6 Signaux optimisés
Un bloc ou un signal qui n’influence aucune sortie peut disparaître. Vérifier les warnings et le schéma RTL.
23.4.7 Génération du bitstream
1. Synthèse complète.
2. Placement et routage.
3. Analyse des rapports.
4. Correction des violations.
5. Génération du fichier de programmation.
6. Archivage du bitstream avec la version du code.
23.5 Validation matérielle et documentation
23.5.1 Plan de validation
Test | Action | Résultat attendu |
|---|---|---|
| Mise sous tension | Programmer puis relâcher reset | État initial |
| Entrées | Activer chaque bouton/interrupteur | Une seule action |
| Sorties | Parcourir les modes | Affichage cohérent |
| Limites | Atteindre les valeurs maximales | Transition correcte |
| Erreur | Provoquer un cas invalide | Alarme ou état sûr |
| Endurance | Répéter le scénario | Aucune dérive |
23.5.2 Instrumentation
- LED de vie ;
- LED ou code d’état ;
- compteur d’erreurs ;
- UART de diagnostic ;
- analyseur logique embarqué ;
- analyseur logique externe ou oscilloscope.
23.5.3 Comparaison simulation / carte
Simulation | Carte |
|---|---|
| Entrées idéales | Rebond, bruit et asynchronisme |
| Horloge exacte | Fréquence physique et jitter |
| Tous signaux visibles | Instrumentation nécessaire |
| Pas de brochage | Broches, tension et polarité |
| Délais RTL idéaux | Routage et timing réel |
23.5.4 Rapport final
1. Introduction et objectifs.
2. Cahier des charges.
3. Architecture hiérarchique.
4. Description des blocs.
5. Plan de vérification et résultats.
6. Synthèse, ressources et timing.
7. Contraintes et implantation.
8. Validation matérielle.
9. Difficultés, corrections et limites.
10. Conclusion et perspectives.
23.5.5 Démonstration
- préparer une procédure courte et reproductible ;
- montrer le reset et le scénario nominal ;
- montrer un cas limite ou une erreur ;
- expliquer un chronogramme et un rapport ;
- prévoir une solution de secours : vidéo ou captures.
Projet 1 — Chronomètre numérique
1. Objectif
Réaliser un chronomètre minutes-secondes commandé par boutons et affiché sur quatre afficheurs sept segments.
2. Cahier des charges minimal
- affichage MM:SS de 00:00 à 59:59 ;
- boutons démarrage, arrêt et remise à zéro ;
- une seule action par appui ;
- mise à jour toutes les secondes ;
- multiplexage de quatre afficheurs sept segments ;
- reset prioritaire et état sûr.
3. Architecture
| Décomposition | Architecture |
| boutons -> synchronisation / anti-rebond / fronts -> FSM MARCHE-ARRET -> base de temps 1 ms et 1 s -> compteurs secondes / minutes -> conversion BCD -> multiplexeur d'afficheurs -> décodeur sept segments |
4. Blocs
Bloc | Fonction |
|---|---|
| gestion_boutons | Produire start_pulse, stop_pulse et reset_pulse |
| base_temps | Produire tick_1ms et tick_1s |
| controle_chrono | Mémoriser MARCHE ou ARRET |
| compteurs_temps | Compter secondes et minutes |
| affichage_4digits | Multiplexer et décoder les chiffres |
5. FSM de contrôle
| États | VHDL |
| type etat_t is (ARRET, MARCHE); signal etat : etat_t := ARRET; process(clk) begin if rising_edge(clk) then if reset = '1' then etat <= ARRET; else case etat is when ARRET => if start_pulse = '1' then etat <= MARCHE; end if; when MARCHE => if stop_pulse = '1' then etat <= ARRET; end if; end case; end if; end if; end process; |
6. Compteurs minutes-secondes
| Comptage BCD | VHDL |
| if rising_edge(clk) then if reset_chrono = '1' then sec_unites <= 0; sec_dizaines <= 0; min_unites <= 0; min_dizaines <= 0; elsif etat = MARCHE and tick_1s = '1' then if sec_unites < 9 then sec_unites <= sec_unites + 1; else sec_unites <= 0; if sec_dizaines < 5 then sec_dizaines <= sec_dizaines + 1; else sec_dizaines <= 0; -- Propagation vers les minutes. end if; end if; end if; end if; |
7. Décodeur sept segments
| Extrait | VHDL |
| with chiffre select segments <= "1000000" when "0000", -- 0 "1111001" when "0001", -- 1 "0100100" when "0010", -- 2 "0110000" when "0011", -- 3 "0011001" when "0100", -- 4 "0010010" when "0101", -- 5 "0000010" when "0110", -- 6 "1111000" when "0111", -- 7 "0000000" when "1000", -- 8 "0010000" when "1001", -- 9 "1111111" when others; |
8. Multiplexage
| Sélection des quatre chiffres | VHDL |
| if rising_edge(clk) then if tick_1ms = '1' then index_afficheur <= index_afficheur + 1; end if; end if; case index_afficheur is when "00" => chiffre <= sec_unites_bcd; when "01" => chiffre <= sec_dizaines_bcd; when "10" => chiffre <= min_unites_bcd; when others => chiffre <= min_dizaines_bcd; end case; |
9. Plan de test
Scénario | Résultat |
|---|---|
| Reset | 00:00 et état ARRET |
| Start | Le temps avance |
| Stop | Le temps reste stable |
| Reprise | Le comptage reprend |
| 59 s | Passage à 01:00 |
| 59:59 | Retour à 00:00 ou saturation selon spécification |
| Rebond simulé | Une seule transition de mode |
10. Testbench accéléré
| Scénario de référence | VHDL |
| -- En simulation, tick_1s est remplacé par un tick rapide. reset <= '1'; wait for 3 * PERIODE; reset <= '0'; start_pulse <= '1'; wait until rising_edge(clk); start_pulse <= '0'; for i in 1 to 60 loop tick_1s <= '1'; wait until rising_edge(clk); tick_1s <= '0'; wait until rising_edge(clk); end loop; assert min_unites = 1 and sec_unites = 0 report "Transition 00:59 vers 01:00 incorrecte" severity error; |
11. Extensions
- centièmes de seconde ;
- fonction tour/lap ;
- compte à rebours ;
- buzzer de fin ;
- transmission UART du temps.
Projet 2 — Feu de circulation intelligent
1. Objectif
Contrôler deux voies et un passage piéton avec temporisation, priorité contrôlée et mode clignotant.
2. Cahier des charges minimal
- une seule voie au vert ;
- phase orange avant le rouge ;
- temps de sécurité avec toutes les voies au rouge ;
- demande piéton mémorisée ;
- mode nocturne clignotant ;
- état visible sur LED.
3. États proposés
État | Voie A | Voie B | Piéton |
|---|---|---|---|
| A_VERT | Vert | Rouge | Rouge |
| A_ORANGE | Orange | Rouge | Rouge |
| TOUT_ROUGE_1 | Rouge | Rouge | Rouge |
| B_VERT | Rouge | Vert | Rouge |
| B_ORANGE | Rouge | Orange | Rouge |
| PIETON_VERT | Rouge | Rouge | Vert |
| CLIGNOTANT | Orange clignotant | Orange clignotant | Rouge |
4. Type d’état
| FSM | VHDL |
| type etat_t is ( A_VERT, A_ORANGE, TOUT_ROUGE_1, B_VERT, B_ORANGE, TOUT_ROUGE_2, PIETON_VERT, CLIGNOTANT ); |
5. Temporisation
| Compteur de durée | VHDL |
| if rising_edge(clk) then if reset_temps = '1' then compteur_ms <= 0; elsif tick_1ms = '1' then if compteur_ms < duree_etat_ms then compteur_ms <= compteur_ms + 1; end if; end if; end if; fin_temps <= '1' when compteur_ms = duree_etat_ms else '0'; |
6. Transition principale
| Extrait de logique suivante | VHDL |
| case etat is when A_VERT => if mode_clignotant = '1' then etat_suivant <= CLIGNOTANT; elsif fin_temps = '1' then etat_suivant <= A_ORANGE; end if; when A_ORANGE => if fin_temps = '1' then etat_suivant <= TOUT_ROUGE_1; end if; when TOUT_ROUGE_1 => if fin_temps = '1' then if demande_pieton = '1' then etat_suivant <= PIETON_VERT; else etat_suivant <= B_VERT; end if; end if; when others => -- Transitions complémentaires. null; end case; |
7. Mémorisation de la demande piéton
| Drapeau de demande | VHDL |
| if rising_edge(clk) then if reset = '1' then demande_pieton <= '0'; elsif impulsion_pieton = '1' then demande_pieton <= '1'; elsif etat = PIETON_VERT then demande_pieton <= '0'; end if; end if; |
8. Invariants de sécurité
| Assertions | VHDL |
| assert not (a_vert = '1' and b_vert = '1') report "Deux voies vertes simultanément" severity failure; assert not (pieton_vert = '1' and (a_vert = '1' or b_vert = '1')) report "Conflit véhicule-piéton" severity failure; |
9. Tests
- cycle normal complet ;
- demande piéton dans chaque état ;
- maintien de la demande jusqu’au traitement ;
- entrée et sortie du mode clignotant ;
- reset dans chaque état ;
- assertions de sécurité sur plusieurs cycles.
10. Extensions
- capteurs de présence et durée adaptative ;
- compte à rebours piéton ;
- priorité véhicule d’urgence ;
- journal d’événements ;
- configuration UART.
Projet 3 — Serrure électronique
1. Objectif
Réaliser une serrure contrôlée par clavier, avec vérification d’un code, limitation des tentatives et alarme.
2. Fonctions
- saisie de chiffres ;
- enregistrement du code saisi ;
- validation et comparaison ;
- ouverture temporaire en cas de succès ;
- incrémentation des échecs ;
- alarme après le nombre maximal de tentatives ;
- effacement et reconfiguration optionnelle.
3. Architecture
| Blocs | Architecture |
| clavier_matriciel -> scanner_lignes_colonnes -> anti_rebond / impulsion_touche -> encodeur_touche -> registre_code_saisi -> comparateur_code -> FSM_serrure -> temporisation_ouverture / alarme -> LED, afficheur ou buzzer |
4. États proposés
| Type d’état | VHDL |
| type etat_t is ( ATTENTE, SAISIE, VERIFICATION, OUVERT, REFUSE, BLOQUE, ALARME ); |
5. Registre de code
| Décalage des chiffres | VHDL |
| if rising_edge(clk) then if effacer_code = '1' then code_saisi <= (others => '0'); nb_chiffres <= 0; elsif chiffre_valide = '1' and nb_chiffres < 4 then code_saisi <= code_saisi(11 downto 0) & chiffre; nb_chiffres <= nb_chiffres + 1; end if; end if; |
6. Comparaison
| Code mémorisé | VHDL |
| constant CODE_SECRET : std_logic_vector(15 downto 0) := x"1234"; code_correct <= '1' when code_saisi = CODE_SECRET else '0'; |
7. Tentatives
| Limitation | VHDL |
| if rising_edge(clk) then if reset = '1' or code_correct = '1' then tentatives <= 0; elsif verification_fausse = '1' then if tentatives < MAX_TENTATIVES then tentatives <= tentatives + 1; end if; end if; end if; alarme <= '1' when tentatives >= MAX_TENTATIVES else '0'; |
8. Sécurité fonctionnelle
- ne pas afficher le code secret ;
- effacer le registre après validation ;
- bloquer temporairement après plusieurs erreurs ;
- définir l’état après coupure de courant ;
- réserver une procédure de maintenance.
9. Plan de test
Scénario | Résultat |
|---|---|
| Code correct | Ouverture puis retour ATTENTE |
| Code faux | Refus et compteur +1 |
| Trois codes faux | BLOQUE ou ALARME |
| Effacement | Registre de saisie remis à zéro |
| Touche maintenue | Un seul chiffre |
| Reset pendant ouverture | Retour à l’état sûr |
10. Extensions
- code programmable stocké en mémoire ;
- temporisation croissante après erreur ;
- journal UART des tentatives ;
- double authentification ;
- affichage masqué par tirets.
Projet 4 — Mini-calculatrice numérique
1. Objectif
Saisir deux opérandes, sélectionner une opération, utiliser une UAL et afficher le résultat avec gestion des erreurs.
2. Fonctions minimales
- saisie ou sélection de deux valeurs 8 bits ;
- addition et soustraction ;
- validation par bouton ;
- affichage du résultat ;
- indicateurs zéro, signe, retenue et overflow ;
- message ou LED d’erreur.
3. Architecture
| Décomposition | Architecture |
| entrées / clavier / interrupteurs -> registre A -> registre B -> sélection opération -> UAL 8 bits -> registre résultat -> conversion affichage -> flags et gestion erreur |
4. FSM de saisie
| États | VHDL |
| type etat_t is ( SAISIE_A, SAISIE_OP, SAISIE_B, CALCUL, AFFICHAGE, ERREUR ); |
5. Registres des opérandes
| Chargement | VHDL |
| if rising_edge(clk) then if reset = '1' then operande_a <= (others => '0'); operande_b <= (others => '0'); else if load_a = '1' then operande_a <= unsigned(entree_valeur); end if; if load_b = '1' then operande_b <= unsigned(entree_valeur); end if; end if; end if; |
6. UAL simplifiée
| Addition / soustraction | VHDL |
| process(all) variable ext : unsigned(8 downto 0); begin resultat_comb <= (others => '0'); carry_comb <= '0'; case operation is when '0' => ext := ('0' & operande_a) + ('0' & operande_b); resultat_comb <= ext(7 downto 0); carry_comb <= ext(8); when others => resultat_comb <= operande_a - operande_b; if operande_a < operande_b then carry_comb <= '1'; -- convention emprunt end if; end case; end process; |
7. Overflow signé
| Indicateur V | VHDL |
| overflow_add <= (not (a(7) xor b(7))) and (resultat(7) xor a(7)); overflow_sub <= (a(7) xor b(7)) and (resultat(7) xor a(7)); |
8. Affichage
Le résultat peut être affiché en hexadécimal ou converti en décimal par double dabble ou division séquentielle.
| Affichage hexadécimal | VHDL |
| digit_haut <= std_logic_vector(resultat(7 downto 4)); digit_bas <= std_logic_vector(resultat(3 downto 0)); |
9. Tests
Opération | A | B | Attendu |
|---|---|---|---|
| ADD | 10 | 20 | 30, flags nuls |
| ADD | 255 | 1 | 0, C=1, Z=1 |
| ADD signé | 127 | 1 | -128, V=1 |
| SUB | 10 | 3 | 7 |
| SUB | 0 | 1 | 255, emprunt=1 |
| SUB signé | -128 | 1 | 127, V=1 |
10. Extensions
- multiplication ;
- division séquentielle ;
- virgule fixe ;
- mémoire des résultats ;
- interface UART de calcul.
Projet 5 — Générateur de signal PWM
1. Objectif
Créer une PWM dont la fréquence et le rapport cyclique sont réglables par boutons, avec affichage et sortie vers LED ou étage de puissance.
2. Spécification minimale
- résolution de rapport cyclique définie ;
- fréquence choisie parmi plusieurs valeurs ;
- boutons + et - pour la consigne ;
- mise à jour sans glitch ;
- affichage de la valeur ;
- état sûr au reset.
3. Architecture
| Décomposition | Architecture |
| boutons -> anti-rebond / fronts -> registre duty demandé -> sélection fréquence -> prescaler -> compteur de phase -> registre duty actif -> comparateur PWM -> LED / driver de puissance |
4. Réglage du duty
| Incrément / décrément saturant | VHDL |
| if rising_edge(clk) then if reset = '1' then duty_demande <= to_unsigned(128, 8); elsif plus_pulse = '1' then if duty_demande < 255 then duty_demande <= duty_demande + 1; end if; elsif moins_pulse = '1' then if duty_demande > 0 then duty_demande <= duty_demande - 1; end if; end if; end if; |
5. Choix de fréquence
| Prescaler sélectionné | VHDL |
| case select_freq is when "00" => diviseur <= DIV_1KHZ; when "01" => diviseur <= DIV_5KHZ; when "10" => diviseur <= DIV_10KHZ; when others => diviseur <= DIV_20KHZ; end case; |
6. Mise à jour au début de période
| Duty sans glitch | VHDL |
| if rising_edge(clk) then if tick_phase = '1' then phase <= phase + 1; if phase = 0 then duty_actif <= duty_demande; end if; end if; end if; pwm_o <= '1' when phase < duty_actif else '0'; |
7. Fréquence et résolution
| Relations | Calcul |
| F_PWM = F_CLK / (DIVISEUR * 2^N) Résolution duty = 1 / 2^N Exemple N=8 : 256 niveaux. |
8. Validation
- mesurer la période à l’oscilloscope ;
- compter les cycles hauts dans le testbench ;
- tester duty 0, 1, 50 %, 254 et 255 ;
- changer la consigne au milieu d’une période ;
- vérifier la polarité de la LED ;
- retester le timing à la fréquence la plus élevée.
9. Sécurité moteur
Sécurité matérielle — Étage de puissance obligatoire La sortie FPGA commande un driver, un MOSFET ou un pont en H. Le moteur ne doit jamais être alimenté directement par une broche du FPGA. |
10. Extensions
- rampe progressive ;
- PWM centrée ;
- commande de servomoteur ;
- plusieurs canaux ;
- configuration UART.
Projet 6 — Communication UART
1. Objectif
Concevoir un émetteur, un récepteur, un générateur de baud et une boucle de retour entre la carte et un ordinateur.
2. Paramètres
Paramètre | Valeur de référence |
|---|---|
| Format | 8N1 |
| Baud | 115 200 bit/s |
| Ordre | LSB en premier |
| Repos TX/RX | 1 |
| Récepteur | Suréchantillonnage ×8 ou ×16 |
3. Architecture
| Chaîne | Architecture |
| clk -> générateur baud TX -> UART TX rx_async -> synchroniseur -> générateur tick x16 -> UART RX -> FIFO / registre -> boucle de retour vers UART TX |
4. Émetteur
| Trame 8N1 dans un registre | VHDL |
| -- Bit 0 : START, bits 1..8 : data, bit 9 : STOP. trame <= '1' & data_in & '0'; -- Envoi LSB en premier : tx <= trame(index_bit). |
5. Récepteur : validation du START
| Échantillonnage au centre | VHDL |
| if etat = IDLE and rx_sync = '0' then compteur_os <= 0; etat <= START; elsif etat = START and tick_x16 = '1' then if compteur_os = 7 then if rx_sync = '0' then index_bit <= 0; etat <= DATA; else etat <= IDLE; -- faux START end if; else compteur_os <= compteur_os + 1; end if; end if; |
6. Capture des données
| Octet reçu | VHDL |
| if tick_x16 = '1' then if compteur_os = 15 then compteur_os <= 0; registre_rx(index_bit) <= rx_sync; if index_bit = 7 then etat <= STOP; else index_bit <= index_bit + 1; end if; else compteur_os <= compteur_os + 1; end if; end if; |
7. Boucle de retour
| Echo UART | VHDL |
| if rising_edge(clk) then tx_start <= '0'; if rx_valid = '1' then octet_attente <= rx_data; octet_present <= '1'; end if; if octet_present = '1' and tx_busy = '0' then tx_data <= octet_attente; tx_start <= '1'; octet_present <= '0'; end if; end if; |
8. Erreurs
Erreur | Détection |
|---|---|
| Framing | STOP reçu à 0 |
| Overflow | Octet reçu avant consommation |
| Faux START | RX remonte avant le centre du START |
| Mauvais baud | Accumulation de décalage |
9. Testbench
| Procédure d’envoi UART | VHDL |
| procedure envoyer_octet( signal rx : out std_logic; constant data : std_logic_vector(7 downto 0); constant temps_bit : time ) is begin rx <= '0'; wait for temps_bit; for i in 0 to 7 loop rx <= data(i); wait for temps_bit; end loop; rx <= '1'; wait for temps_bit; end procedure; |
10. Validation PC
1. Utiliser un pont USB-UART compatible avec la tension logique.
2. Relier les masses.
3. Configurer le terminal en 8N1 au bon débit.
4. Envoyer des caractères.
5. Vérifier leur retour.
6. Tester des séquences longues et rapides.
11. Extensions
- parité ;
- FIFO RX/TX ;
- commandes ASCII ;
- protocole avec checksum ;
- transmission de mesures périodiques.
Projet 7 — Jeu numérique sur FPGA
1. Objectif
Réaliser un jeu de réflexe ou de séquence avec génération pseudo-aléatoire, score, temporisation et sorties lumineuses ou sonores.
2. Exemple de jeu
Après un délai pseudo-aléatoire, une LED s’allume. Le joueur doit appuyer sur le bouton correspondant avant le timeout.
3. Architecture
| Décomposition | Architecture |
| base_de_temps -> LFSR pseudo-aléatoire -> FSM du jeu -> sélection LED cible -> gestion boutons -> mesure temps de réaction -> score -> affichage -> buzzer / effets lumineux |
4. États
| FSM du jeu | VHDL |
| type etat_t is ( ATTENTE_DEMARRAGE, DELAI_ALEATOIRE, SIGNAL_ACTIF, ATTENTE_REPONSE, SUCCES, ECHEC, FIN_PARTIE ); |
5. Générateur pseudo-aléatoire LFSR
| LFSR 8 bits | VHDL |
| process(clk) begin if rising_edge(clk) then if reset = '1' then lfsr <= x"A5"; -- graine non nulle elsif avance_lfsr = '1' then lfsr <= lfsr(6 downto 0) & (lfsr(7) xor lfsr(5) xor lfsr(4) xor lfsr(3)); end if; end if; end process; |
6. Sélection d’une cible
| Index LED | VHDL |
| index_cible <= to_integer(unsigned(lfsr(1 downto 0))); leds_cible <= std_logic_vector( shift_left(to_unsigned(1, 4), index_cible) ); |
7. Délai pseudo-aléatoire
| Durée bornée | VHDL |
| duree_attente_ms <= 500 + to_integer(unsigned(lfsr)) * 10; -- Délai entre 500 ms et 3050 ms. |
8. Mesure de réaction
| Compteur | VHDL |
| if rising_edge(clk) then if reset_reaction = '1' then reaction_ms <= 0; elsif etat = ATTENTE_REPONSE and tick_1ms = '1' then reaction_ms <= reaction_ms + 1; end if; end if; |
9. Score
| Mise à jour | VHDL |
| if rising_edge(clk) then if reset_score = '1' then score <= 0; elsif succes = '1' then if reaction_ms < SEUIL_RAPIDE then score <= score + 3; else score <= score + 1; end if; elsif erreur = '1' and score > 0 then score <= score - 1; end if; end if; |
10. Anti-triche et erreurs
- appui avant le signal : pénalité ;
- mauvais bouton : échec ;
- absence de réponse : timeout ;
- boutons synchronisés et filtrés ;
- graine LFSR non nulle.
11. Plan de test
Scénario | Résultat |
|---|---|
| Start | Passage en délai aléatoire |
| Appui anticipé | Échec ou pénalité |
| Bonne réponse | Score augmenté |
| Mauvaise réponse | Score réduit |
| Timeout | Échec |
| Fin du nombre de manches | FIN_PARTIE |
| Reset | Score et état initial |
12. Effets sonores
| Buzzer carré | VHDL |
| buzzer <= phase_audio when son_actif = '1' else '0'; -- phase_audio est basculée par un tick correspondant -- à la fréquence sonore souhaitée. |
13. Extensions
- jeu Simon avec séquence mémorisée ;
- niveau de difficulté progressif ;
- meilleur score en RAM ;
- affichage du temps de réaction ;
- mode deux joueurs ;
- transmission UART des résultats.
Comparaison des sujets proposés
Projet | Difficulté | Blocs dominants | Extension naturelle |
|---|---|---|---|
| Chronomètre | Intermédiaire | Compteurs, affichage, boutons | Compte à rebours |
| Feu intelligent | Intermédiaire | FSM, temporisation | Capteurs adaptatifs |
| Serrure | Intermédiaire+ | Clavier, FSM, registres | Code programmable |
| Calculatrice | Intermédiaire+ | UAL, saisie, affichage | Virgule fixe |
| PWM | Intermédiaire | Compteurs, comparateur | Multi-canaux |
| UART | Avancé | FSM, suréchantillonnage | Protocole de commandes |
| Jeu | Avancé | FSM, LFSR, score | Deux joueurs |
Choisir le projet
Profil ou objectif | Projet conseillé |
|---|---|
| Débuter l’intégration | Chronomètre ou PWM |
| Approfondir les FSM | Feu ou serrure |
| Approfondir l’arithmétique | Calculatrice |
| Approfondir les communications | UART |
| Projet démonstratif et créatif | Jeu |
| Approfondir l’affichage | Chronomètre ou calculatrice |
Livrables obligatoires
1. Cahier des charges et matrice des exigences.
2. Diagramme d’architecture hiérarchique.
3. Sources VHDL commentées.
4. Paquetages et composants réutilisables.
5. Bancs de test unitaires et d’intégration.
6. Fichier de contraintes.
7. Rapports de synthèse et de timing.
8. Tableau de validation matérielle.
9. Rapport final.
10. Démonstration ou vidéo de secours.
Barème proposé sur 100 points
Critère | Points |
|---|---|
| Cahier des charges et exigences | 8 |
| Architecture hiérarchique | 12 |
| Qualité du VHDL et bonnes pratiques | 12 |
| Fonctionnement des blocs | 12 |
| Testbenches et assertions | 15 |
| Synthèse et analyse des ressources | 8 |
| Contraintes et timing | 8 |
| Validation matérielle | 12 |
| Rapport et traçabilité | 7 |
| Démonstration et soutenance | 6 |
| Total | 100 |
Niveaux d’évaluation
Niveau | Description |
|---|---|
| Insuffisant | Fonction non démontrée, tests absents ou architecture monolithique |
| Acceptable | Fonction principale opérationnelle et validation minimale |
| Bon | Architecture claire, tests automatiques et timing respecté |
| Très bon | Cas limites, diagnostic, réutilisation et documentation complète |
| Excellent | Extensions maîtrisées, preuves quantitatives et démonstration robuste |
Checklist de livraison
- Le dépôt se reconstruit à partir d’une copie propre.
- Le top-level correspond à la carte utilisée.
- Les contraintes ne contiennent aucun placeholder.
- Le testbench se termine automatiquement.
- Les assertions ne signalent aucune erreur.
- Le rapport ne contient aucun latch involontaire.
- Le timing est respecté.
- Le bon bitstream est archivé.
- La procédure de démonstration est documentée.
- Les limites et améliorations sont honnêtement décrites.
Synthèse du chapitre
Étape | Résultat attendu |
|---|---|
| Spécification | Exigences mesurables |
| Architecture | Blocs et interfaces définis |
| Codage | Composants lisibles et synthétisables |
| Vérification | Tests unitaires et système réussis |
| Synthèse | Ressources conformes à l’intention |
| Contraintes | Broches et horloges correctement décrites |
| Implantation | Timing respecté et bitstream généré |
| Validation | Scénarios matériels réussis |
| Documentation | Preuves, limites et perspectives |
Autoévaluation
1. Quel est le premier livrable ?
Réponse : Un cahier des charges vérifiable.
2. Pourquoi décomposer le système ?
Réponse : Pour tester, réutiliser et intégrer progressivement.
3. Que doit préciser une interface ?
Réponse : Types, largeur, polarité, timing et protocole.
4. Quand synthétiser ?
Réponse : Après réussite du testbench d’intégration.
5. Que vérifier dans le rapport ?
Réponse : Ressources, latches, warnings et timing.
6. Pourquoi accélérer la simulation ?
Réponse : Réduire les durées sans changer la logique.
7. Que prouve le bitstream ?
Réponse : Seulement que l’implémentation a été générée.
8. Pourquoi valider sur carte ?
Réponse : Les entrées, broches et délais physiques diffèrent.
9. Que devient un bug corrigé ?
Réponse : Un test de régression.
10. Quand le projet est-il terminé ?
Réponse : Quand fonction, timing, validation et documentation sont démontrés.
Modèle de fiche de projet
Rubrique | Contenu à renseigner |
|---|---|
| Titre | Nom clair du système |
| Objectif | Fonction principale et utilisateur |
| Entrées | Broches, protocoles, polarités |
| Sorties | Afficheurs, LED, communication, actionneur |
| Horloge/reset | Fréquence et stratégie |
| Architecture | Blocs, interfaces et hiérarchie |
| Exigences | Liste numérotée et mesurable |
| Tests | Scénarios nominaux, limites et erreurs |
| Contraintes | Broches, I/O et timing |
| Validation | Procédure sur carte |
| Extensions | Fonctions supplémentaires |
Conclusion — Aboutissement du cours Le projet final doit démontrer une démarche d’ingénierie complète : comprendre le besoin, concevoir une architecture, vérifier le comportement, maîtriser l’implantation et apporter des preuves de fonctionnement. |