Articles

Créer un module IP avec Vivado

Introduction

Les deux premiers projets ont permis de se familiariser à Vivado en privilégiant deux aspects :

  • La création de fonctionnalités matérielles avec une description en langage VHDL.
  • La création d'un système complet reposant sur des modules de propriétés intellectuelles existants.

Il s'agit maintenant de marier ces deux mondes en créant un module IP maison décrit en VHDL. Ce module pourra ensuite être intégré à un projet de système complet intégrant un coeur de processeur comme dans l'exercice précédent.

Création d'un nouveau périphérique AXI4

Créer un projet de type RTL (comme dans l'exemple précédent) et le nommer Projet_IP_PWM.

Note : le projet créé est totalement vierge et doit être configuré pour cibler une carte Zybo comme dans le projet VHDL vu précédemment.

Il s'agit de créer un module IP capable de s'interconnecter au Processing System via un bus AXI. Ce type de module est connu sous l'appellation de périphérique AXI4.

Lancer le processus de création par le menu Tools -> Create and Package New IP.

Passer la première boite de dialogue d'information en cliquant sur Next.

La boite de dialogue suivante apparaît :

Création d'un module IP

Choisir Create a new AXI4 peripheral puis cliquer sur Next.

Compléter le dialogue qui apparaît comme suit (champs Name et Description) :

Nom et description du module IP

Noter que le dossier d'accueil de l'IP créé est noté ip_repo et ne se trouve pas par défaut dans le dossier du projet en cours.

On sélectionne ensuite les caractéristiques du module IP en conservant les propositions faites par défauts :

Caractéristiques du module IP

Valider par Next.

Le processus préliminaire de création se termine par la boite ci-dessous dans laquelle on sélectionne Edit IP avant de cliquer sur le bouton Finish.

Vers l'édition du module IP

Génération du signal PWM 16 bits

On se propose de réaliser en VHDL un module PWM 16 bits à l'image de celui disponible dans les microcontrôleurs.

Principe de fonctionnement

Il s'agit de générer un signal carré de période $T$ fixée et au rapport cyclique commandable sur 16 bits. Le résultat prend la forme suivante où $pwm\_out$ est le signal généré :

Signal PWM

L'intérêt : obtenir un signal continu dont la valeur moyenne $‹pwm_{out}›=\alpha.V_{CCio}$ soit réglable.

La figure ci-dessus fait apparaître les éléments nécessaires à la génération d'un tel signal. On met d'abord en place un compteur, intitulé ici $pwm\_counter$, comptant de 0 à 65535 donc sur 16 bits non signés. La période de comptage à retenir est donc de $T_{comptage}=\frac{T}{2^{16}}$, ce qui conduit à une fréquence de comptage de $F_{clk}=\frac{2^{16}}{T}$.

Cahier des charges

Le bloc hiérarchique du module PWM à réaliser est le suivant :

Générateur PWM

Y figurent les signaux suivants :

  • Le signal d'horloge d'entrée est noté $clk$.
  • $prescaler$, codé sur 3 bits, permet d'accéder à différents rapports de prédivision à appliquer à $clk$ avant d'attaquer le compteur du générateur PWM.
  • $pwm\_in$ est un vecteur sur 16 bits fournissant l'image du rapport cyclique de 0 à 65535.
  • $pwm\_out$ désigne le signal de sortie.

Le calcul du rapport de prédivision $N$ se fait aisément avec la relation suivante : $N=2^{prescaler}$

Tâches à réaliser

  1. Créer un nouveau fichier source VHDL nommé pwm16bits_core et le caractériser avec les entrées et sorties répondant au cahier des charges.
  2. Décrire le module en VHDL (sans gérer le prescaler pour commencer).
  3. Ajouter un fichier de test VHDL nommé pwm16bits_core_tb; écrire les process permettant de générer des signaux pertinants pour valider et simuler le comportement du code écrit à la question précédente.
  4. Reprendre les deux dernières étapes en ajoutant le prescaler.

Aides : la mise en place du prescaler se fait aisément en lui associant un compteur décomptant de $N-1$ à $0$ et en autorisant le comptage sur $pwm\_counter$ au moment des passages à 0 du compteur associé au prescaler.

Conseils supplémentaires :

  • Associer un signal interne de comptage au prescaler, par exemple un signal appelé prescalerCounter de type unsigned(7 downto 0) (pour prescaler = "111", le rapport de division est de $2^7=128$).
  • Adapter la valeur initiale de ce compteur en fonction de la valeur de prescaler au moment de sa réinitilisation.

Intégration du code dans l'IP

L'étape Création d'un nouveau périphérique AXI4 a abouti à la création de la structure de base du module IP. A cette occasion, deux fichiers VHDL ont été produits :

2 sources VHDL pour un IP

Les deux fichiers créés sont hiérarchiquement dépendants.

ip_pwm16bits_v1_0.vhd est le sommet de la hiérarchie de notre IP. C'est à partir de ce fichier que le bloc fonctionnel apparaissant dans le diagramme sera élaboré.

ip_pwm16bits_v1_0_S00_AXI.vhd est instancié par le fichier précédent. Ce fichier met en oeuvre l'interface AXI pour assurer les échanges avec le Processing System (PS). Rappelons que ce fichier VHDL sera implémenté dans le Programmable Logic (PL).

En dehors des signaux du bus AXI tous déjà définis par le processus précédent, il nous faut maintenant ajouter les signaux que nous allons créer. Dans un premier temps, on se contente d'ajouter une sortie PWM de type STD_LOGIC.

Cette sortie est d'abord ajoutée au niveau du sommet hiérarchique de notre IP donc dans la liste des ports du fichier ip_pwm16bits_v1_0.vhd comme suit :

Ajout des ports

A noter que cet ajout s'effectue dans la zone identifiée à cet effet par le générateur d'IP par le commentaire -- Users to add ports here.

Comme ce signal PWM sera également présent dans le fichier de description du coeur de notre IP (ip_pwm16bits_v1_0_S00_AXI.vhd), on met à jour la description du composant qui en est faite dans ip_pwm16bits_v1_0.vhd comme suit :

Ajout des ports au composant qui sera instancié

Finalement on ajoute l'information de routage entre le fichier d'instanciation et le fichier instancié dans ip_pwm16bits_v1_0.vhd, fichier dont les modifications sont maintenant terminées.

Routage de l'instance

On s'attaque maintenant à la description de la fonction réalisée par l'IP à proprement parler dans le fichier ip_pwm16bits_v1_0_S00_AXI.vhd.

Logiquement, on commence par ajouter le port pour la sortie pwm :

Ajout du port pwm ...

On va maintenant déclarer le composant pwm16bits_core dans le fichier ip_pwm16bits_v1_0_S00_AXI.vhd dans la zone réservée pour les signaux "utilisateur" (on peut aussi y déclarer des composants).

Déclaration du core pwm

Composant qu'il faut instancier pour terminer à la toute fin du fichier ip_pwm16bits_v1_0_S00_AXI.vhd :

Instanciation du core pwm

Noter qu'on utilise ici deux signaux particuliers de l'interface AXI :

  1. S_AXI_ACLK qui correspond au signal d'horloge qui ryhtme le bus AXI.
  2. slv_reg0, registre présent à l'adresse de base dans le Processing System (PS) du module IP que nous venons de créer et qui fournira la valeur du prescaler.
  3. slv_reg1, registre présent à l'adresse de base + 1 dans le Processing System (PS) du module IP que nous venons de créer et qui fournira la valeur de pwm_in.

Sauvegarder les fichiers VHDL édités durant cette partie pour finir.

Encapsulation de l'IP

Pour lancer le processus d'encapsulation, cliquer sur Package IP dans la section PROJECT MANAGER du Flow Navigator.

Les informations suivantes apparaissent dans le PROJECT MANAGER :

Résultat de l'encapsulation

Mettre à jour l'IP en sélectionnant les paramètres qui ne sont pas à jour et ne sont pas pointés par une coche verte et en cliquant sur le message en haut de l'image précédente intitulé Merge changes from Customization Parameters Wizard.

Tout passe alors au vert :

Mise à jour des paramètres de l'IP

Noter que ces dernières opérations ont permis de prendre en compte les ajouts effectués dans les fichiers VHDL de l'IP, ce que l'on peut constater en listant la liste des ports intégrant dorénavant le signal pwm16bits :

Mise à jour des ports de l'IP

Terminer en configurant les paramètres d'édition de l'encapsultation en sélectionnant l'étape Review and Package :

Paramètres d'encapsulation de l'IP

et en réencapsulant l'IP par un clic sur le bouton Re-Package IP.

L'IP pwm 16 bits peut maintenant être utilisée dans un projet.

Utilisation de l'IP créée

Création de la structure matérielle

Ouvrir le projet nommé Projet_IP_PWM et créer un diagramme semblable à celui du TP Projet SoC avec Xilinx Vivado en reprenant toutes les étapes vues dans ce précédent TP. La seule nuance consistera à connecter les boutons poussoirs sur l'IP GPIO plutôt que les LEDs comme c'était le cas dans le TP précédent.

Ajouter une instance de l'IP pwm en prenant soin d'utiliser les commandes d'automatisation pour en assurer la connexion au reste de la structure de sorte d'aboutir au schéma suivant :

Ajouter également un port de sortie au diagramme et le relier à la sortie pwm16bits de l'IP pwm.

Le diagramme obtenu devra ressembler à cela :

Schéma du projet avec l'IP PWM

Implémenter le module, générer le bitstream de configuration et l'exporter pour l'utiliser sous le SDK.

Développement de l'application

Lancer le SDK.

Céer une nouvelle application nommée test_pwm sur la base du fichier source du projet précédent.

Ecrire une fonction assurant le test du module PWM par un simple balayage répété du rapport cyclique de 0 à 10000.

Aide : consulter le fichier include créé pour l'IP PWM 16 bits afin de savoir comment envoyer les données nécessaires à la configuration de l'IP pour un rapport cyclique donné.

Include de l'IP PWM 16 bits