# Partie 1 : Exercices

## Exercice 1 : Lancement des outils
Pour pouvoir avancer dans la suite des exercices il est nécessaire de savoir utiliser à minima les outils de développement et de simulation. Je vous propose donc de vous familiariser avec dans ce premier exercice.
### 1.1 Questa : outil de simulation
Dans cette première partie de l'exercice, nous allons découvrir comment utiliser le logiciel de simulation de circuit intégré compatible avec plusieurs language HDL. Nous l'utiliserons pour simuler le banc de test de la machine à état décrit dans le cours.

Pour lancer le logiciel Questa, ouvrez un terminal puis tapez la commande : 
```bash
$: vsim
```
 Vous devriez voir apparaître cette fenêtre :
![Fenêtre d'accueil Questa](images/questa_landing.png)

L'encart `Transcript` en bas de la fenêtre est un invité de commande qui permets de manipuler le logiciel d'un manière plus aisé qu'en passant par les menu graphiques. Nous allons donc l'utiliser pour réaliser nos différentes actions.

Lancez dans l'invité de commande les instructions suivantes :
```cmd
cd /home/electrolab/Workshop/workshop-fpga/part1/exercices/fsm
do simulate.do
``` 
La dernière commande va lancer le script qui automatise des opérations de configuration tel que l'importation des entités et des bancs de test, la configuration de l'analyseur logique et le lancement de la simulation.   
N'hésitez pas à aller lire ce script, les commandes sont assez simples à comprendre.

Vous obtiendrez alors ce résultat:   
![Fenêtre post-simulation](images/questa_simulate.png)   
On distingue alors quatre zones dans la fenêtre :
1. Un onglet `sim` listant les bancs de tests exécutés.
2. Un onglet `Object` listant les signaux (nom , valeur, type)
3. Un onglet `Processes` listant les processus exécutés pendant la simulation
4. Un onglet `wave` correspondant à l'analyseur logique associé à la simulation
   
La lecture de l'analyseur logique et / ou de l'onglet `transcript` nous permettra alors de valider le bon fonctionnement de l'entité.

### 1.2 Quartus : outil de synthétisation
Maintenant que nous savons que notre entité est fonctionnelle, nous allons pouvoir la synthétiser et la téléverser sur notre carte de développement _BeMicro MAX10_.

Pour commencer, lancez le logiciel Quartus sur votre ordinateur :
 - soit en cliquant sur l'icon dans la liste des programmes installés
 - soit en exécutant la commande `quartus` dans un terminal
  
Vous devriez alors voir apparaître la fenêtre suivante:   
![Fenêtre d'accueil Quartus](images/quartus_landing.png)   
Vous pouvez maintenant créer votre premier projet en cliquant sur le bouton `New Project Wizard`.   
Vous allez ensuite devoir configurer le projet comme suit :
- Répertoire du projet : `/home/electrolab/Workshop/workshop-fpga/part1/exercices/fsm/quartus`
- Nom du projet : `FSM`
- Type de projet : projet vide
- Ajouter des fichiers : laissez vide, nous le ferons dans les prochaines étapes
- Sélection du FPGA :
  - Choisir la famille `MAX 10` dans la liste déroulante
  - Dans le champ `Name filter`, collez la valeur `10M08DAF484C8GES`
- Outils :
  - Simulation : sélectionnez le format `VHDL` dans la liste déroulante

Votre projet est donc maintenant configuré. Vous devriez alors voir deux nouvelles entrées dans l'onglet `Project Navigator`.   
![Onglet de navigation](images/questa_project_navigator.png)

Faites un clic droit sur la ligne `FSM` puis `Settings`. Il devrait alors apparaître une fenêtre de configuration. Cela va nous permettre d'ajouter de nouvelles entités au projet ainsi que de définir l'entité principale (Top-Level).

Pour ajouter un fichier :   
1. Cliquez sur l'onglet `Files`.
2. Cliquez sur le bouton avec les `...` à côté du champ `File name` pour ouvrir l'explorateur de fichier.
3. Sélectionnez le fichier `fsm.vhd` dans le répertoire parent du projet.
4. Fermez la fenêtre en appuyant sur le bouton `OK`

Nos entités sont alors importées, nous pouvons donc lancer une première compilation du projet pour que Quartus puisse analyser les différentes entités. Cette compilation n'aboutira pas mais nous permettra de sélectionner l'entité `seq_design` dans les paramètres généraux.   

Pour ce faire, lancez la compilation en appuyant sur ce bouton  dans la barre des actions : ![Bouton de compilation](images/quartus_compile_btn.png).    
Une fois le processus de compilation terminé, vous pourrez sélectionner dans les paramètres la bonne entité principale.
![Entité principale](images/quartus_settings_top_level.png)
Nous pouvons alors relancer la compilation du projet qui, cette fois-ci, devrait aboutir.

La seconde étape nécessaire à la synthétisation de notre composant est l'assignation d'entrées et sorties physique à l'entité principale. Pour cela, nous allons utiliser l'outil d'assignation accessible depuis la barre des menus : `Assignments > Pin Planner`. Cette étape est la moins agréable car nécessitant d'aller fouiller dans diverses documentation pour trouver les correspondances entre les composants sur la carte de développement et les pins du FPGA.

Pour vous simplifier la vie, je vous ai fait la table de correspondance:

| Label carte  | PIN FPGA | Signal | Localisation (Pin planner) |
|--------------|----------|--------|----------------------------|
| D1 (led)     | M2       | x      | PIN_M2                     | 
| SW1 (bouton) | M1       | a      | PIN_M1                     |
| SW2 (bouton) | R1       | reset  | PIN_R1                     |
|              | N14      | clock  | PIN_N14                    |

Ce qui donne cette assignation de pin après renseignement des différents champs :   
![Assignation de pin](images/quartus_pin_assign.png)

Tout est maintenant près pour télécharger le bitstream sur la carte de développement.
Pour procéder, rien de plus simple :
1. Lancer à nouveau une compilation pour intégrer les assignations de pin
2. Ouvrez l'utilitaire de programmation : `Barre des menus > Tools Programmer`
3. Configurez la connexion au module de programmation de la carte via le bouton `Hardware Setup` et choisissez `USB-Blaster [X.X.x]` dans la liste déroulante.
4. Sélectionner le  mode `JTAG`
5. Appuyez sur `Start` et attendez que le programme se téléverse.
   
![Téléversement du bitstream](images/quartus_program.png)

**Et voilà, vous avez une carte de développement avec un FPGA programmé !**
## Exercice 2 :  
Dans cet exercice, nous allons nous intéresser à reproduire l'exemple de LED clignotante dans la première partie du cours. Les fichiers de travail sont disponibles dans le répertoire `exercices/led_blink`.
_Un corrigé est présent dans le répertoire, merci de ne pas le regarder directement :D_

Pour faire clignoter une LED, nous avons besoin de décrire les comportements suivants :
- une initialisation et inversion d'état pour un pin
- un diviseur de fréquence
- un moyen de réinitialiser le diviseur de fréquence

La conception du diviseur de fréquence pouvant être longue, je vous mets à disposition un diviseur accessible sur internet. Vous devez cependant l'intégrer dans votre entité afin de pouvoir l'utiliser.   
Le banc de test est lui aussi pré-écrit afin que vous puissiez vous concentrer sur la conception de la logique de votre entité.

Pour commencer, ouvre le fichier `led_blink.vhd`. Ce fichier contient la déclaration de notre futur circuit intégré (le block `entity`) ainsi que la structure de l'architecture temps réel de ce dernier.   
Vous y trouverez aussi quatres block de commentaire décrivant les emplacements des codes VHDL à produire.  
Nous sommes fin pret pour attaquer la description de l'architecture.

### Signaux
Ce circuit intégré est assez simple nous n'aurons besoin que de trois signaux : 
 - une entrée pour l'horloge du FPGA `CLK`
 - une entrée pour la réinitialisation de l'entité `RST_N`
 - une sortie pour l'alimentation de la LED

La déclaration d'un signal se fait de la façon suivante :
```vhdl
SIGNAL <NOM_SIGNAL> : <TYPE>;
```   
Pour cet exercice tous les signaux seront des états tout-ou-rien et donc du type `STD_LOGIC`.

### Réinitialisation de l'entité
Qui dit utilisation d'une horloge dit synchronisation des processus avec cette dernière. Quoi de mieux pour faire cela que de mettre en place un processus de réinitialisation de l'entité.

La déclaration d'un processus se fait de ma manière suivante :
```vhdl
    PROCESS (<SIGNAL_A_OBSERVER>,<SIGNAL_A_OBSERVER>)
      -- Definition des variables du processus
    BEGIN
      -- code qui fait des trucs
    END PROCESS;
```
Un process se comporte comme une sorte d'interruption : lorsque un changement d'état opère sur un des signaux observé, alors le processus est lancé avec les états courant de tous les signaux.

Comme nous souhaitons faire une réinitialisation synchrone, nous allons indiquer que nous ne souhaitons réaliser nos actions que lorsque le signal de l'horloge passe à l'état haut : 
```vhdl
    PROCESS (CLK)
    BEGIN
      IF rising_edge (CLK) THEN

      END IF;
    END PROCESS;
```

Ne reste plus qu'à ajouter les affectations d'états dans le `IF`. Cela se fait de la manière suivante :
```vhdl
  <SIGNAL_OU_PORT> <= '0'; -- dans le cas d'un STD_LOGIC
```

### Diviseur de fréquence
Le diviseur de fréquence est une entité qui, comme son nom l'indique, divise une fréquence d'entrée (ici l'horloge de 50Mhz) en plusieurs sous-fréquences :
 - Tick10us : 100kHz
 - Tick1ms  : 1kHz
 - Tick10ms : 100Hz

Nous avons donc besoin d'instancier l'entité `FDIV` pour pouvoir obtenir une fréquence de clignotement compatible avec l'oeil humain.
Elle se fait de la manière suivante :
```vhdl

<nom_instance> : ENTITY <NOM_BIBLIOTHEQUE>.<NOM_ENTITE>
        GENERIC MAP(
          <PARAMETRE> => <VALEUR>,
          <PARAMETRE> => <VALEUR>
        )
        PORT MAP(
            <PORT> => <SIGNAL_OU_PORT>,
            <PORT> => <SIGNAL_OU_PORT>);
```
Dans notre cas, nous utiliserons l'entité suivante : `WORK.FDIV`.     
Nous aurons aussi besoin de configurer la fréquence d'horloge à 50Mhz :  `GENERIC MAP(FCLOCK => 50E6)`

### Le processus principal
Vous avez normalement tous les éléments nécessaires pour pouvoir écrire ce dernier processus.

Quelques informations supplémentaires : 
 - Instanciation de variable dans un processus : `VARIABLE <NOM_VARIABLE> : <TYPE>;`
 - Affectation d'une variable : `<VARIABLE> := '0'; -- dans le cas d'un STD_LOGIC`
 - Opérateur de négation : `NOT`
 - Tick à utiliser : `Tick1ms`

A vous de jouer !