Filtre

Principe de fonctionnement

L’entité BiquadFilter réalise un filtre numérique à réponse impulsionnelle infinie (IIR pour Infinite Impulse Response). Il s’agit plus précisément d’un filtre biquadratique dont la sortie yy est calculée de la manière suivante :

y(n)=b0x(n)+b1x(n1)+b2x(n2)a1y(n1)a2y(n2)y(n) = b_0\cdot x(n) + b_1\cdot x(n-1) + b_2\cdot x(n-2) - a_1\cdot y(n-1) - a_2\cdot y(n-2)

Selon la valeur des coefficients (a1a_1, a2a_2, b0b_0, b1b_1, b2b_2), un tel filtre pourra avoir une réponse de type passe-bas, passe-haut, ou passe-bande.

Dans le cadre de ce projet, nous avons calculé pour vous les coefficients de tous les filtres. Vous les trouverez dans le paquetage Vocoder_pkg. Nous nous sommes inspirés des algorithmes fournis dans la page Biquad formulas sur le blog EarLevel Engineering.

Pour la réalisation en VHDL, nous choisissons d’exprimer l’équation du filtre dans la forme directe transposée de type 2 :

Filtre biquadratique, forme directe transposée de type 2

y(n)=b0x(n)+w(n1)w(n)=b1x(n)a1y(n)+v(n1)v(n)=b2x(n)a2y(n)\begin{aligned} y(n) &= b_0\cdot x(n) &+ w(n-1) \\ w(n) &= b_1\cdot x(n) - a_1\cdot y(n) &+ v(n-1) \\ v(n) &= b_2\cdot x(n) - a_2\cdot y(n) \end{aligned}

À titre d’exercice, vous pouvez vérifier que ces trois équations sont équivalentes à celle proposée au début de cette section.

L’entité BiquadFilter

Interface de l'entité BiquadFilter

Les paramètres génériques de cette entité permettent de configurer sa réponse en fréquence :

Paramètre Type Rôle
A1 Virgule fixe (vocoder_coef_t) Le coefficient a1a_1 du filtre
A2 Virgule fixe (vocoder_coef_t) Le coefficient a2a_2 du filtre
B0 Virgule fixe (vocoder_coef_t) Le coefficient b0b_0 du filtre
B1 Virgule fixe (vocoder_coef_t) Le coefficient b1b_1 du filtre
B2 Virgule fixe (vocoder_coef_t) Le coefficient b2b_2 du filtre

L’entité BiquadFilter traite un flux de données en utilisant le protocole ready/valid. Elle joue à la fois les rôles de consommateur et de producteur :

Port Direction Type Rôle
clk_i Entrée Logique Le signal d’horloge global du système
reset_i Entrée Logique La commande de réinitialisation du système
valid_i Entrée Logique Indique qu’un nouvel échantillon est disponible en entrée
ready_o Sortie Logique Indique que ce filtre est prêt à recevoir un nouvel échantillon d’entrée
data_i Entrée Virgule fixe (vocoder_data_t) La valeur d’un échantillon à traiter
valid_o Sortie Logique Indique qu’un nouvel échantillon est disponible en sortie
ready_i Entrée Logique Indique que le consommateur relié à ce filtre est prêt à recevoir un nouvel échantillon
data_o Sortie Virgule fixe (vocoder_data_t) La valeur d’un échantillon filtré

Réalisation du filtre

Nous fournissons une version complète du filtre qui fonctionne en simulation. La gestion du protocole ready/valid est assurée par une machine à trois états sur le modèle présenté dans la page Connecter producteurs et consommateurs.

Dans la version que nous fournissons, tous les calculs sont effectués en une période d’horloge dans l’état BUSY_STATE.

Choix d’implémentation

Les types de données et l’écriture des opérations ont été choisis pour tirer parti des cellules de traitement du signal DSP48E1 présentes dans les FPGA de Xilinx. Ces cellules sont spécialement conçues pour réaliser des opérations de multiplication rapides et des calculs associant multiplication et addition de la forme :

P=A×B+CP = A \times B + C

Cette combinaison d’opérations est appelée Multiplication-ACumulation (MAC) car dans les algorithmes de traitement du signal, elle est souvent utilisée pour calculer des sommes de produits. Dans l’exemple ci-dessous, la variable p « accumule » les produits des éléments de a et b :

pour i de 0 à N-1 répéter
    p ← p + a(i) * b(i)
fin répéter

La cellule DSP48E1 peut également calculer des expressions de la forme :

P=(A+D)×B+CP = (A + D) \times B + C

Les tailles des opérandes et du résultat sont les suivantes :

Opérande Taille max. (bits)
A 30
B 18
C 48
D 25
P 48

On peut mettre ces tailles en relation avec celles des types de données définis dans le paquetage Vocoder_pkg. Dans le filtre, ils sont destinés à être utilisés comme ceci :

Type Taille (bits) Rôle
vocoder_coef_t 18 B
biquad_data_t 25 C ou D

Pour plus de détails, vous pouvez consulter la documentation officielle de Xilinx.

Banc de test et simulation

Le fichier BiquadFilterTestbench.vhd contient un banc de test pour l’entité BiquadFilter.

Ce banc de test relie la sortie d’un oscillateur avec l’entrée d’un filtre passe-bande. Vous pouvez régler les caractéristiques de ces deux instances en modifiant des constantes dans le fichier BiquadFilterTestbench_pkg.vhd :

Au cours de la simulation, on s’attend à obtenir une autre sinusoïde en sortie du filtre. L’amplitude de la sortie sera maximale si la fréquence de l’oscillateur se situe au centre de la bande passante du filtre, c’est-à-dire pour OSC_STEP = FILTER_CHANNEL + 1.

Pour exécuter la simulation, nous fournissons un script qui automatise le démarrage du simulateur et l’exécution d’une séquence de commandes :

  1. Dans le menu Tools, choisissez Run Tcl Script.
  2. Allez dans le dossier src/BiquadFilter et sélectionnez le fichier BiquadFilterTestbench.tcl.
  3. Dans la fenêtre des chronogrammes, sélectionnez les signaux data_i et data_o.
  4. Cliquez avec le bouton droit sur l’un des deux signaux et choisissez Waveform StyleAnalog.
  5. Cliquez avec le bouton droit sur l’un des deux signaux et choisissez RadixSigned Decimal.

Application de démonstration

Dans le fichier BiquadFilterDemo.vhd, nous nous sommes inspirés de l’exemple I2SDemo en supprimant la mémoire RightRom et en insérant un filtre entre la sortie de LeftRom et l’entrée correspondant à la voie droite du transmetteur I2S.

Application de démonstration du filtre

Afficher la légende des schémas.

Ainsi, au cours du fonctionnement de ce circuit, vous devriez entendre l’extrait audio « week-end » original dans l’oreille gauche, et le même extrait filtré dans l’oreille droite.

Synthétiser et implémenter le circuit

Dans le panneau Tcl Console, indiquez que l’entité BiquadFilterDemo est l’entité principale du circuit :

set_property top BiquadFilterDemo [get_filesets sources_1]

Générez le fichier binaire à charger dans le FPGA : Flow NavigatorProgram and DebugGenerate Bitstream.

Vivado generate bitstream

Vivado va enchaîner toutes les étapes d’analyse des fichiers sources, de synthèse logique, de placement et routage, pour terminer par la génération d’un fichier binaire à charger dans le FPGA.

À la fin des opérations, la boîte de dialogue Bitstream Generation Completed s’affiche. Choisissez Open Hardware Manager.

Configurer le FPGA

Vérifiez que l’interrupteur d’alimentation de votre carte Basys3 est en position OFF. Le cavalier situé à côté de l’interrupteur doit être en position USB.

Branchez le module PmodI2S sur le connecteur JA (en haut sur le côté gauche de la carte) et branchez un casque stéréo ou des enceintes sur le connecteur jack.

Vous ne connaissez pas à l’avance le volume de la sortie audio. Ne mettez pas vos écouteurs sur les oreilles avant d’être sûr que le son n’est pas trop fort.

Reliez le connecteur micro-USB de la carte à un port USB de votre PC. Mettez la carte sous tension.

En haut du panneau Hardware Manager, pressez Open target et choisissez Auto Connect.

Vivado open target

Pressez ensuite Program Device.

Vivado program device

Observations et optimisation des ressources matérielles

Avant d’aller plus loin, nous allons nous intéresser aux ressources matérielles utilisées par ce circuit.

Affichage du schéma logique

Affichez le schéma RTL : Flow NavigatorRTL AnalysisOpen Elaborated DesignSchematic.

Dans le schéma, repérez l’instance filter_inst et ouvrez-la. Identifiez ensuite les opérations d’addition, de soustraction et de multiplication utilisées.

Ce schéma présente le circuit en termes d’opérations élémentaires : arithmétiques, logiques, de sélection, de mémorisation. En réalité, après synthèse et optimisation, certaines opérations pourront être fusionnées ou associées dans un même composant.

Affichage du schéma technologique

Affichez le schéma du circuit synthétisé : Flow NavigatorSynthesisOpen Synthesized DesignSchematic.

Dans ce nouveau schéma, repérez l’instance filter_inst, ouvrez-la et identifiez les composants DSP48E1.

Combien y en a-t-il ? Est-ce cohérent avec la description VHDL ?

Affichage des statistiques d’utilisation du FPGA

Dans la barre d’outils en haut de la fenêtre, pressez le bouton Project Summary, dont l’icône est une lettre Sigma (Σ).

Vivado project summary

La rubrique Utilization donne un aperçu du taux d’occupation du FPGA. Vous pouvez l’afficher sous forme de diagramme ou sous forme de tableau. Repérez le nombre de ressources DSP utilisées après implémentation.

Sachant que notre application vocodeur travaillera sur 12 voies, avec un filtre passe-bande et un filtre passe-bas par voie, y a-t-il assez de cellules DSP48E1 dans notre FPGA ?

Amélioration

Proposez une solution et modifiez l’architecture du filtre de manière à utiliser moins de cellules DSP48E1.

Simulez et synthétisez BiquadFilterDemo avec la nouvelle version du filtre.

Après synthèse, vous ne constaterez peut-être pas de diminution du nombre de cellules DSP48E1 utilisées. En effet, les algorithmes d’optimisation de Vivado prennent en compte de nombreux critères et, sur ce circuit précis, la réduction du nombre de cellules DSP n’apporte peut-être pas de gain significatif.