TP PIC

Il y a quelques années,  je voulais monter un TP de sensibilisation aux systèmes sur puce. Où trouver un modèle VHDL de processeur ? Quelle méthodologie employer pour le porter sur un FPGA ? Quel est le bilan comparativement à une solution totalement faite sur mesure ? Quel serait le gain d’une solution intégrée de processeur embarqué ?

Les étudiants auxquels je m’adressais ayant une connaissance  du composant PIC de Microchip et comme par ailleurs deux modèles VHDL (totalement « soft »)  étaient disponibles sur le site en open source opencores.org, mon choix se fit naturellement sur ce composant.

Contrairement à d’autres expériences tout à fait heureuses de modèles opencores.org, le modèle de PIC choisi s’est avéré comporter quelques défauts.  Ceci m’a fourni la trame d’un TP  PIC: Synthétiser une application avec le modèle d’origine; Constater le défaut; Effectuer une simulation pour en trouver l’origine; Corriger le défaut et réimplanter.

On peut ainsi se faire une idée des cotés positifs mais aussi des risques du « design reuse », l’avantage essentiel étant que le projet final est totalement maitrisé et portable puisqu’on possède toutes les sources VHDL.

On trouvera les détails de cet ancien TP remanié ici

Premier projet

Afin de servir de base d’apprentissage du langage, des outils et du savoir faire VHDL de synthèse, je vais définir un projet simple pour tous qui puisse être testé sur n’importe quelle carte de développement.

Un projet trop simple présente cependant l’inconvénient de ne pas avoir de contraintes sévères et donc de s’éloigner du monde « réel » . En compensation, on veillera à estimer les performances (fréquence maximale de fonctionnement et surface occupée) comme si elles étaient primordiales. On essaiera de noter chaque fois qu’il aura lieu les solutions alternatives. En particulier, une solution à base de processeur pourra être introduite.

Pour moi, le projet minimal doit comporter une machine d’état, un compteur, des entrées-sorties.

Après avoir posé le cahier des charges du projet, on effectuera uns structuration de l’ensemble ( découpage en blocs), puis l’écriture de chaque bloc, les différentes simulations, le placement-routage et la simulation post-routage, puis le test sur une carte.

Cette méthodologie peut paraitre lourde pour un petit projet ( vis à vis de la puissance du langage VHDL) mais entre un projet réel et un projet de débutant, la seule différence est l’éffort à apporter à la structuration de l’ensemble ( et cela, ce n’est pas le VHDL qui va le résoudre). Donc, ce qui est important c’est d’avoir une méthode rigoureuse.

Personnaliser Quartus Altera

En matière de saisie VHDL, nous avons avant tout deux revendications:

  • Pouvoir utiliser Emacs comme éditeur VHDL
  • Travailler prioritairement avec les bibliothèques std_logic_1164 et numeric_std, cette dernière étant la plus rigoureuse en matière de types numériques.

Quartus nous propose dans Tools>Options un certain nombre de possibilités.

  • En ce qui concerne Emacs, on sélectionne text editor et on indique le chemin complet de l’exécutable.Options quartus

Un bon point pour quartus, car à partir de ce moment, emacs sera appellé pour toute opération VHDL comme File > New> VHDL File

Par contre, il ne semble pas possible de fixer par défaut les bibliothèques VHDL que l’on préfère. On le fera très simplement dans emacs.

En conclusion:

  • Emacs est fixé comme éditeur préféré
  • Pour créer un nouveau source, on crée le fichier nouveau.vhd dans emacs par la commande File > New> VHDL File
  • On rajoute les bibliothèques ( VHDL>Template>package)
  • On décrit l’entité et l’architecture
  • On sauve

Personnaliser Xilinx ISE

En matière de saisie VHDL, nous avons avant tout deux revendications:

  • Pouvoir utiliser Emacs comme éditeur VHDL
  • Travailler prioritairement avec les bibliothèques std_logic_1164 et numeric_std, cette dernière étant la plus rigoureuse en matière de types numériques.

Xilinx ISE nous propose dans Edit>preferences un certain nombre de possibilités.

  • En ce qui concerne Emacs, on sélectionne text editor et on indique une ligne de commande pour Editor: custom runemacs.exe $1 $2

Ceci implique que l’on ait bien précisé dans son « Path » le chemin d’accès au logicile emacs. Exemple windows: Paramètres> panneau de configuration> Systeme>Avancè>Variables d’environnement puis Path> modifier on rajoutera sur la decription path ;c\logiciel\emacs-21_bin (si emacs a été installé de cette manière).

Fermer le navigateur ISE, relancer et tout fichier VHD sera ouvert dans emacs.

Preferences emacs

  • Si l’on sélectionne la ligne ISE Text Editor on voit par contre une option de bibliothèques( celles que préfère xilinx) non modifiables qui sont inclues chaque fois qu’on passe par le menu Project>new source) . Ayant changé d’éditeur et préférant une autre bibliothèque, on va préconiser d’ignorer ce menu.

En conclusion:

  • Emacs est fixé comme éditeur préféré
  • Pour créer un nouveau source, on crée le fichier nouveau.vhd dans emacs, on rajoute les bibliothèques ( VHDL>Template>package)
  • On décrit l’entité et l’architecture
  • Puis dans le navigateur on lie le fichier au projet par project>Add source

Morale: Contrairement aux synthétiseurs universels, les outils intégrés brident les possibilités du langageVHDL.

S’équiper en outils VHDL

Que l’on soit sur MAC OS , Linux, Unix ou Windows, on peut compiler et simuler du VHDL. Les outils existent et ils fonctionnent.

Pour en savoir plus, consultez les pages implantation physique et simulateurs.

Cours et Diaporama VHDL

La page Cours et diaporama VHDL a été mise à jour. Le cours disponible en format pdf est maintenant présenté en deux parties distinctes pour plus de clarté.

  • Le langage proprement dit dans une première partie
  • Le style optimisé pour la synthèse dans une deuxième partie

Le Diaporama illustre les exemples du cours

Tous les exemples proposés ont leur source disponibles.

Souris et clavier PS2

J’ai essayé de rassembler en une seule page tous les fichiers intéressant concernant l’interfaçage d’une souris ou d’un clavier PS2. Ces fichiers sont utilisés depuis pas mal de temps et donc tout à fait surs. Le modèle de l’interface clavier est plus complet que celui de souris car il y a plus d’inconvénient que d’avantage à compliquer le modèle de souris. On a donc pour cette dernière supprimé la partie commande ( on ne peut donc pas par exemple  changer la résolution, ce qui n’est pas primordial et couterait de la surface de silicium). Par contre, en ce qui concerne le clavier une telle simplification était impensable dans la mesure où il est impératif de pouvoir choisir le mode, allumer les leds etc..)

Les seules applications logicielles fournies concernent le processeur NIOS d’Altera.

Emacs VHDL, c’est génial

Que vous soyez débutant ou confirmé, essayer emacs avec son mode VHDL aura une conséquence certaine: vous ne pourrez plus vous en passer. Votre travail sera plus professionnel car vous aurez personnalisé votre style d’écriture. Finies les indentations approximatives ou la valse hésitation sur majuscule/minuscule. Les identificateurs que vous choisirez pourront être long puisque vous bénéficiez entre autre de la complétion.

Voir la nouvelle page de ce blog consacrée à emacs.

(pub gratuite)

Le choix des bibliothèques et des types

Cette question me semble d’une grande importance pour le débutant. Dans ce domaine, la facilité d’utilisation peut entraîner de grandes déconvenues.
Après consultation du site IEEE, je conseille les bibliothèques suivantes (voir cours VHDL pages 40 et suivantes):

    LIBRARY IEEE;
    USE IEEE.STD_LOGIC_1164.ALL;
    USE IEEE.NUMERIC_STD.ALL;

  • Au niveau des interfaces ENTITY, on n’utilise que des types std_ulogic , std_logic ou std_logic_vector. Ceci pour des raisons de compatibilité avec les différents aperçus du circuit.
  • Ces bibliothèques contrairement à d’autres ne permettent pas d’additionner, de soustraire ou de comparer des std_logic_vector entre eux. Ceci est heureux car il est souhaitable de savoir à priori si les nombres traités doivent être considérés comme signes ou non signès. En interne dans l’architecture on définira des signaux avec des types signed ou unsigned et toutes les opérations arithmétiques pourront alors se traiter correctement y compris avec des types différents ( signed et integer, unsigned et natural)
  • Le passage entre les signaux internes et les signaux visibles au niveau de l’entité se fera par un cast comme dans l’exemple suivant;

 SIGNAL   niveau_entity : std_logic_vector(31 DOWNTO 0);
     SIGNAL   niveau_architecture : signed(31 DOWNTO 0);

      BEGIN
             niveau_entity <= std_logic_vector( niveau_architecture – 212); –exemple de cast et d’opération mixte

  • Par défaut choisir std_ulogic plutôt que std_logic comme le font tous les outils. En effet std_logic est un std_ulogic avec fonction de résolution (donc qui permet de construire les bus). Les outils considèrent que « qui peut le plus peut le moins  » et proposent std_logic comme type par défaut. Cela ne fait pas l’affaire du débutant qui préférera être alerté suffisamment tôt lorsqu’il fera des bus sans le savoir.

EXEMPLE d’erreur souvent rencontrée:

un: Process
                WAIT until rising_edge(clk);
                IF condition1 THEN
                        s <=  une_certaine_equation; — premiere affectation de s
                END IF;
                END PROCESS;

deux: Process
                WAIT until rising_edge(clk);
                IF condition2 THEN
                        s <=  une_autre_equation; — deuxieme affectation de s
                END IF;
                END PROCESS;

observations:
Si le type de s est std_ulogic, une erreur va apparaître lors de la synthèse (compilation) du circuit. Si le type est std_logic, il n’y a pas d’erreur car on a décrit un bus (avec un seul fil)

  • Mais le concepteur a -t -il vraiment voulu réaliser un bus sur s ?  (connecter 2 sorties entre elles)
  • N’a t-il pas oublié qu’un mème signal doit être affecté dans un même PROCESS ?
  • Ne voulait-il pas écrire la chose suivante ? (ou quelque chose d’approchant)

correct: Process
                WAIT until rising_edge(clk);
                IF condition1 THEN
                        s <=  une_certaine_equation;
               ELSIF condition2 THEN
                        s <=  une_autre_equation;
                END IF;
                END PROCESS; 

    ==> Réserver le type std_logic exclusivement au bus, autrement utiliser std_ulogic

Séparer au maximum le combinatoire et le séquentiel

Si dans un processus, on constate un grand nombre d’imbrications de IF (plus de 3) il faut se poser la question de la simplification éventuelle de cette écriture.

WAIT UNTIL rising_edge (clk);
IF condition1 THEN …
IF condition 2 THEN …
IF condition 3 THEN …

On a ici associé à une fonction de mémorisation une fonction combinatoire de condition1, condition 2 etc…
Si cette fonction est combinatoire a t-on décrit toutes les combinaisons possibles ? Cette fonction si elle est trop complexe va créer des retards importants et faire chuter la fréquence maximale du circuit. Enfin, pour la lisibilité de la description, n’aurait-on pas eu intérêt à séparer cette partie combinatoire de la partie purement séquentielle.

Un circuit combinatoire

On privilégie toujours l’écriture en instruction concurrente. C’est plus économique en nombre de lignes et c’est surtout plus lisible. (voir cours VHDL pages 75 et suivantes)
S1 <= e1 OR (e2 AND NOT e3); — une équation

Un contre – exemple

faux_combi : Process ( e1) –ERREUR
BEGIN
IF (e1 OR (e2 AND NOT e3)) = ’1′ THEN
s1 <= ’1′;
ELSE
s1 <= ’0′;
END IF;
END PROCESS;

observations:

  • La liste de sensibilité est équivalente à WAIT ON. Si vous êtes débutant, préférer le WAIT ON explicite, vous vous apercevez tout de suite que le processus décrit est faussement combinatoire. En effet si e2 ou e3 change , la sortie n’est pas affectée. Elle ne le sera que lorsque e1 changera. On a ici affaire à un type de circuit inconnu en conception synchrone. Il y aurait ici un effet mémoire asynchrone.
  • On doit mettre en liste de sensibilité tous les signaux d’entrée si le circuit est combinatoire. L’écriture correcte est alors la suivante:

vrai_combi : Process
BEGIN
WAIT ON e1, e2, e3; — toutes les entrées puisque c’est combinatoire
IF (e1 OR (e2 AND NOT e3)) = ’1′ THEN
s1 <= ’1′;
ELSE
s1 <= ’0′;
END IF;
END PROCESS;