Bonjour Ă tous! Cet article se concentrera sur une partie importante du traitement numĂ©rique du signal - le filtrage du signal de fenĂȘtre, en particulier sur les FPGA. L'article montrera comment concevoir des fenĂȘtres classiques de longueur standard et des fenĂȘtres "longues" de 64K Ă 16M + Ă©chantillons. Le langage de dĂ©veloppement principal est le VHDL, la base de l'Ă©lĂ©ment est les derniers cristaux FPGA Xilinx des derniĂšres familles: ce sont Ultrascale, Ultrascale +, 7-series. L'article montrera l'implĂ©mentation de CORDIC - le noyau de base pour configurer les fonctions de fenĂȘtre de n'importe quelle durĂ©e, ainsi que les fonctions de fenĂȘtre de base. L'article dĂ©crit la mĂ©thode de conception utilisant des langages de haut niveau C / C ++ dans Vivado HLS. Comme d'habitude, Ă la fin de l'article, vous trouverez un lien vers les codes sources du projet.
KDPV: un schĂ©ma typique de transmission de signal via des nĆuds DSP pour des tĂąches d'analyse de spectre.

Présentation
Grùce au cours «Traitement numérique du signal», de nombreuses personnes savent que pour une forme d'onde sinusoïdale infinie dans le temps, son spectre est une fonction delta à la fréquence du signal. En pratique, le spectre d'un signal harmonique limité dans le temps réel est équivalent à la fonction
~ sin (x) / x , et la largeur du lobe principal dépend de la durée de l'intervalle d'analyse du signal
T. La limite de temps n'est rien d'autre que la multiplication du signal par une enveloppe rectangulaire. Il est connu du cours DSP que la multiplication des signaux dans le domaine temporel est une convolution de leurs spectres dans le domaine fréquentiel (et vice versa), par conséquent, le spectre de l'enveloppe rectangulaire limitée du signal harmonique est équivalent à ~ sinc (x). Cela est également dû au fait que nous ne pouvons pas intégrer le signal sur un intervalle de temps infini, et la transformée de Fourier sous forme discrÚte, exprimée par une somme finie, est limitée par le nombre d'échantillons. En rÚgle générale, la longueur de la FFT dans les appareils de traitement numérique FPGA modernes prend des valeurs
NFFT de 8 à plusieurs millions de points. En d'autres termes, le spectre du signal d'entrée est calculé sur l'intervalle
T , qui dans de nombreux cas est Ă©gal Ă
NFFT . En limitant le signal Ă l'intervalle
T , on impose ainsi une «fenĂȘtre» rectangulaire d'une durĂ©e de
T Ă©chantillons. Par consĂ©quent, le spectre rĂ©sultant est le spectre du signal harmonique multipliĂ© et de l'enveloppe rectangulaire. Dans les tĂąches DSP, des fenĂȘtres de formes diverses ont Ă©tĂ© inventĂ©es depuis longtemps, qui, superposĂ©es Ă un signal dans le domaine temporel, peuvent amĂ©liorer ses caractĂ©ristiques spectrales. Un grand nombre de fenĂȘtres diffĂ©rentes est principalement dĂ» Ă l'une des principales caractĂ©ristiques de toute superposition de fenĂȘtres. Cette caractĂ©ristique s'exprime dans la relation entre le niveau des lobes latĂ©raux et la largeur du lobe central. Un schĂ©ma bien connu: plus la suppression des lobes latĂ©raux est forte, plus le lobe principal est large et vice versa.
L'une des applications des fonctions de fenĂȘtre: dĂ©tection de signaux faibles sur fond de plus forts en supprimant le niveau des lobes latĂ©raux. Les principales fonctions de la fenĂȘtre dans les tĂąches DSP sont une fenĂȘtre triangulaire, sinusoĂŻdale, Lanczos, Hann, Hamming, Blackman, Harris, Blackman-Harris, une fenĂȘtre Ă toit plat, Natall, Gauss, une fenĂȘtre Kaiser et bien d'autres. La plupart d'entre eux sont exprimĂ©s Ă travers une sĂ©rie finie en additionnant des signaux harmoniques avec des poids spĂ©cifiques. Les fenĂȘtres de forme complexe sont calculĂ©es en prenant un exposant (fenĂȘtre gaussienne) ou une fonction de Bessel modifiĂ©e (fenĂȘtre de Kaiser), et ne seront pas prises en compte dans cet article. Vous pouvez en savoir plus sur les fonctions des fenĂȘtres dans la littĂ©rature, que je donnerai traditionnellement Ă la fin de l'article.
La figure suivante montre les fonctions de fenĂȘtre typiques et leurs caractĂ©ristiques spectrales construites Ă l'aide des outils de CAO Matlab.

Implémentation
Au dĂ©but de l'article, j'ai insĂ©rĂ© KDPV, qui montre en termes gĂ©nĂ©raux un diagramme structurel de la multiplication des donnĂ©es d'entrĂ©e par une fonction de fenĂȘtre. De toute Ă©vidence, la façon la plus simple d'implĂ©menter le stockage d'une fonction de fenĂȘtre dans le FPGA est de l'Ă©crire en mĂ©moire (bloc
RAMB ou distribué
distribuĂ© - cela n'a pas beaucoup d'importance), puis de rĂ©cupĂ©rer cycliquement les donnĂ©es lorsque les Ă©chantillons d'entrĂ©e du signal arrivent. En rĂšgle gĂ©nĂ©rale, dans les FPGA modernes, la quantitĂ© de mĂ©moire interne permet de stocker des fonctions de fenĂȘtre de tailles relativement petites, qui sont ensuite multipliĂ©es par les signaux d'entrĂ©e entrants. Par petite, je veux dire des fonctions de fenĂȘtre jusqu'Ă 64 Ko d'Ă©chantillons.
Mais que faire si la fonction de fenĂȘtre est trop longue? Par exemple, 1M de lectures. Il est facile de calculer que pour une telle fonction de fenĂȘtre prĂ©sentĂ©e dans une grille de bits 32 bits, NRAMB = 1024 * 1024 * 32/32768 = 1024 cellules de mĂ©moire de bloc des cristaux FPGA Xilinx de type RAMB36K sont nĂ©cessaires. Et pour 16 millions d'Ă©chantillons? 16 mille cellules mĂ©moire! Pas un seul FPGA moderne n'a autant de mĂ©moire. Pour de nombreux FPGA, c'est trop, et dans d'autres cas, c'est une utilisation inutile des ressources FPGA (et, bien sĂ»r, de l'argent du client).
Ă cet Ă©gard, vous devez trouver une mĂ©thode pour gĂ©nĂ©rer des Ă©chantillons de fonction de fenĂȘtre directement sur le FPGA Ă la volĂ©e, sans Ă©crire les coefficients du pĂ©riphĂ©rique distant dans la mĂ©moire de bloc. Heureusement, les choses de base ont longtemps Ă©tĂ© inventĂ©es pour nous. En utilisant un algorithme tel que
CORDIC (la méthode
numĂ©rique par numĂ©rique ), il est possible de concevoir de nombreuses fonctions de fenĂȘtre dont les formules sont exprimĂ©es en termes de signaux harmoniques (Blackman-Harris, Hann, Hamming, Nattal, etc.)
CORDIC
CORDIC est une méthode itérative simple et pratique pour calculer la rotation d'un systÚme de coordonnées, qui vous permet de calculer des fonctions complexes en effectuant des opérations d'addition et de décalage primitives. En utilisant l'algorithme CORDIC, on peut calculer les valeurs des signaux harmoniques sin (x), cos (x), trouver la phase - atan (x) et atan2 (x, y), les fonctions trigonométriques hyperboliques, faire pivoter le vecteur, extraire la racine du nombre, etc.
Au dĂ©but, je voulais prendre le noyau CORDIC fini et rĂ©duire la quantitĂ© de travail, mais j'ai une longue aversion pour les noyaux Xilinx. AprĂšs avoir Ă©tudiĂ© les rĂ©fĂ©rentiels sur le github, j'ai rĂ©alisĂ© que tous les cĆurs prĂ©sentĂ©s ne conviennent pas pour un certain nombre de raisons (mal documentĂ©s et illisibles, non universels, conçus pour une tĂąche spĂ©cifique ou une base d'Ă©lĂ©ments,
écrits en verilog , etc.). Ensuite, j'ai demandé au camarade
Lazifo de faire ce travail pour moi. Bien sĂ»r, il s'en est occupĂ©, car la mise en Ćuvre de CORDIC est l'une des tĂąches les plus simples dans le domaine des DSP. Mais comme je suis impatient, parallĂšlement Ă son travail, j'ai Ă©crit
mon vélo avec mon
propre noyau paramétré. Les principales caractéristiques sont la profondeur de bits configurable des signaux de sortie
DATA_WIDTH et la phase d'entrée normalisée
PHASE_WIDTH de -1 à 1, et la précision des calculs de
PRECISION . Le cĆur CORDIC est exĂ©cutĂ© selon le circuit parallĂšle du pipeline - Ă chaque cycle d'horloge, le cĆur est prĂȘt Ă effectuer des calculs et Ă recevoir des Ă©chantillons d'entrĂ©e. Le noyau passe N cycles pour calculer l'Ă©chantillon de sortie, dont le nombre dĂ©pend de la capacitĂ© des Ă©chantillons de sortie (plus la capacitĂ© est grande, plus il y a d'itĂ©rations pour calculer la valeur de sortie). Tous les calculs se font en parallĂšle. Ainsi, CORDIC est le noyau de base pour crĂ©er des fonctions de fenĂȘtre.
Fonctions de fenĂȘtre
Dans le cadre de cet article, je ne rĂ©alise que les fonctions de fenĂȘtre qui s'expriment Ă travers des signaux harmoniques (Hann, Hamming, Blackman-Harris de divers ordres, etc.). Que faut-il pour cela? En termes gĂ©nĂ©raux, la formule de construction d'une fenĂȘtre ressemble Ă une sĂ©rie de longueur finie.

Un certain ensemble de coefficients
a k et de membres de la sĂ©rie dĂ©termine le nom de la fenĂȘtre. La fenĂȘtre Blackman-Harris la plus populaire et la plus utilisĂ©e est d'ordre diffĂ©rent (de 3 Ă 11). Voici un tableau des coefficients pour les fenĂȘtres Blackman-Harris:

En principe, l'ensemble de fenĂȘtres Blackman-Harris est applicable Ă de nombreux problĂšmes d'analyse spectrale, et il n'est pas nĂ©cessaire d'essayer d'utiliser des fenĂȘtres complexes telles que Gauss ou Kaiser. Les fenĂȘtres nattales ou Ă toit plat ne sont qu'une variĂ©tĂ© de fenĂȘtres avec des poids diffĂ©rents, mais les mĂȘmes principes de base que Blackman-Harris. On sait que plus il y a de membres de la sĂ©rie, plus la suppression du niveau des lobes latĂ©raux est forte (sous rĂ©serve d'un choix raisonnable de la profondeur de bits de la fonction fenĂȘtre). En fonction de la tĂąche, le dĂ©veloppeur n'a qu'Ă choisir le type de fenĂȘtres utilisĂ©es.
Implémentation FPGA - approche traditionnelle
Tous les noyaux des fonctions de fenĂȘtre sont conçus en utilisant l'approche classique pour dĂ©crire les circuits numĂ©riques dans les FPGA et sont Ă©crits en langage VHDL. Voici une liste des composants fabriquĂ©s:
- bh_win_7term - Blackman-Harris 7 order, une fenĂȘtre avec suppression maximale des Ă©chafaudages latĂ©raux.
- bh_win_5term - Commande Blackman-Harris 5, comprend une fenĂȘtre avec un dessus plat.
- bh_win_4term - Blackman-Harris 4 commandes, comprend les fenĂȘtres Nattal et Blackman-Nattal.
- bh_win_3term - Blackman-Harris 3 commandes,
- hamming_win - FenĂȘtres Hamming et Hann.
Le code source du composant de fenĂȘtre Blackman-Harris est de 3 ordres de grandeur:
entity bh_win_3term is generic ( TD : time:=0.5ns;
Dans certains cas, j'ai utilisé la bibliothÚque
UNISIM pour incorporer les
nĆuds DSP48E1 et DSP48E2 dans le projet, ce qui
me permet finalement d'augmenter la vitesse des calculs en raison du pipelining à l'intérieur de ces blocs, mais comme l'a montré la pratique, il est plus rapide et plus facile de donner libre cours et d'écrire quelque chose comme
P = A * B + C et spécifiez les directives suivantes dans le code:
attribute USE_DSP of <signal_name>: signal is "YES";
Cela fonctionne bien et définit de maniÚre rigide le type d'élément sur lequel la fonction mathématique est implémentée pour le synthétiseur.
Vivado hls
De plus, j'ai implĂ©mentĂ© tous les cĆurs Ă l'aide des outils
Vivado HLS . Je vais énumérer les principaux
avantages de Vivado HLS: haute vitesse de conception (
time-to-market ) dans les langages de haut niveau C ou C ++, modĂ©lisation rapide des nĆuds dĂ©veloppĂ©s en raison de l'absence d'un concept de frĂ©quence d'horloge, configuration flexible des solutions (en termes de ressources et de performances) en introduisant pragmas et directives dans le projet, ainsi qu'un seuil d'entrĂ©e bas pour les dĂ©veloppeurs dans les langages de haut niveau. Le principal inconvĂ©nient est le coĂ»t sous-optimal des ressources FPGA par rapport Ă l'approche classique. De plus, il n'est pas possible d'atteindre les vitesses fournies par les anciennes mĂ©thodes RTL classiques (VHDL, Verilog, SV). Eh bien, le plus gros
inconvénient est de danser avec un tambourin, mais cela est caractéristique de tous les CAD de Xilinx. (Remarque: dans le débogueur Vivado HLS et dans le modÚle C ++ réel, des résultats souvent différents ont été obtenus, car Vivado HLS fonctionne de maniÚre tordue en utilisant les avantages de
la précision arbitraire ).
L'image suivante montre le journal du noyau CORDIC synthétisé dans Vivado HLS. Il est assez informatif et affiche de nombreuses informations utiles: la quantité de ressources utilisées, l'interface utilisateur du noyau, les boucles et leurs propriétés, le retard dans le calcul, l'intervalle de calcul de la valeur de sortie (important lors de la conception de circuits série et parallÚles):

Vous pouvez Ă©galement voir comment calculer les donnĂ©es dans divers composants (fonctions). On peut voir qu'Ă la phase zĂ©ro, les donnĂ©es de phase sont lues et aux Ă©tapes 7 et 8, le rĂ©sultat du nĆud CORDIC est affichĂ©.

Le résultat de Vivado HLS: un noyau RTL synthétisé créé à partir de code C. Le journal montre que dans l'analyse de temps, le noyau réussit toutes les restrictions:

Un autre gros avantage de Vivado HLS est que pour vĂ©rifier le rĂ©sultat, elle fait elle-mĂȘme un banc d'essai du code RTL synthĂ©tisĂ© basĂ© sur le modĂšle qui a Ă©tĂ© utilisĂ© pour vĂ©rifier le code C. Cela peut ĂȘtre un test primitif, mais je pense qu'il est trĂšs cool et assez pratique pour comparer le fonctionnement de l'algorithme en C et en HDL. Ci-dessous, une capture d'Ă©cran de Vivado montrant une simulation du modĂšle de fonction de noyau d'une fonction de fenĂȘtre obtenue par Vivado HLS:

Ainsi, pour toutes les fonctions de fenĂȘtre, des rĂ©sultats similaires ont Ă©tĂ© obtenus, quelle que soit la mĂ©thode de conception - en VHDL ou en C ++. Cependant, dans le premier cas, une plus grande frĂ©quence de fonctionnement et un plus petit nombre de ressources sont atteints, et dans le second cas, la vitesse de conception maximale est atteinte. Les deux approches ont droit Ă la vie.
J'ai calculé précisément combien de temps je consacrerais au développement en utilisant différentes méthodes. J'ai implémenté un projet C ++ dans Vivado HLS ~ 12 fois plus rapidement qu'en VHDL.
Comparaison des approches
Comparez le code source pour HDL et C ++ pour le noyau CORDIC. L'algorithme, comme cela a été dit précédemment, est basé sur les opérations d'addition, de soustraction et de décalage. Sur VHDL, cela ressemble à ceci: il y a trois vecteurs de données - l'un est responsable de la rotation de l'angle, et les deux autres déterminent la longueur du vecteur le long des axes X et Y, ce qui équivaut à sin et cos (voir l'image du wiki):

En calculant itérativement la valeur Z, les valeurs X et Y sont calculées en parallÚle. Le processus de recherche cyclique des valeurs de sortie sur HDL:
constant ROM_LUT : rom_array := ( x"400000000000", x"25C80A3B3BE6", x"13F670B6BDC7", x"0A2223A83BBB", x"05161A861CB1", x"028BAFC2B209", x"0145EC3CB850", x"00A2F8AA23A9", x"00517CA68DA2", x"0028BE5D7661", x"00145F300123", x"000A2F982950", x"000517CC19C0", x"00028BE60D83", x"000145F306D6", x"0000A2F9836D", x"0000517CC1B7", x"000028BE60DC", x"0000145F306E", x"00000A2F9837", x"00000517CC1B", x"0000028BE60E", x"00000145F307", x"000000A2F983", x"000000517CC2", x"00000028BE61", x"000000145F30", x"0000000A2F98", x"0000000517CC", x"000000028BE6", x"0000000145F3", x"00000000A2FA", x"00000000517D", x"0000000028BE", x"00000000145F", x"000000000A30", x"000000000518", x"00000000028C", x"000000000146", x"0000000000A3", x"000000000051", x"000000000029", x"000000000014", x"00000000000A", x"000000000005", x"000000000003", x"000000000001", x"000000000000" ); pr_crd: process(clk, reset) begin if (reset = '1') then
En C ++, dans Vivado HLS, le code est presque identique, mais l'enregistrement est plusieurs fois plus court:
Apparemment, le mĂȘme cycle avec dĂ©calage et ajouts est utilisĂ©. Cependant, par dĂ©faut, toutes les boucles dans Vivado HLS sont «rĂ©duites» et exĂ©cutĂ©es sĂ©quentiellement, comme prĂ©vu pour le langage C ++. L'introduction du
pragma HLS UNROLL ou
HLS PIPELINE convertit les calculs sĂ©rie en parallĂšle. Cela conduit Ă une augmentation des ressources FPGA, cependant, il vous permet de calculer et de soumettre de nouvelles valeurs au cĆur Ă chaque cycle d'horloge.
Les rĂ©sultats de la synthĂšse du projet en VHDL et C ++ sont prĂ©sentĂ©s dans la figure ci-dessous. Comme vous pouvez le voir, logiquement, la diffĂ©rence est deux fois en faveur de l'approche traditionnelle. Pour d'autres ressources FPGA, l'Ă©cart est insignifiant. Je n'ai pas approfondi l'optimisation du projet en C ++, mais sans ambiguĂŻtĂ© en dĂ©finissant diverses directives ou en modifiant partiellement le code, le nombre de ressources utilisĂ©es peut ĂȘtre rĂ©duit. Dans les deux cas, les synchronisations ont convergĂ© pour une frĂ©quence centrale donnĂ©e de ~ 350 MHz.

Caractéristiques d'implémentation
Ătant donnĂ© que les calculs sont effectuĂ©s dans un format Ă virgule fixe, les fonctions de fenĂȘtre ont un certain nombre de fonctionnalitĂ©s qui doivent ĂȘtre prises en compte lors de la conception de systĂšmes DSP sur FPGA. Par exemple, plus la profondeur de bits des donnĂ©es de fonction de fenĂȘtre est grande, meilleure est la prĂ©cision de la superposition de fenĂȘtre. D'un autre cĂŽtĂ©, avec une profondeur de bits insuffisante de la fonction de fenĂȘtre, des distorsions seront introduites dans la forme d'onde rĂ©sultante, ce qui affectera la qualitĂ© des caractĂ©ristiques spectrales. Par exemple, une fonction de fenĂȘtre doit avoir au moins 20 bits lorsqu'elle est multipliĂ©e par un signal d'une durĂ©e de 2 ^ 20 = 1M d'Ă©chantillons.
Conclusion
Cet article montre une façon de concevoir des fonctions de fenĂȘtre sans utiliser de mĂ©moire externe ou de mĂ©moire de bloc FPGA. La mĂ©thode d'utilisation exclusive des ressources logiques des FPGA (et dans certains cas des blocs DSP) est donnĂ©e. En utilisant l'algorithme CORDIC, il est possible d'obtenir des fonctions de fenĂȘtre de n'importe quelle profondeur de bit (dans des limites raisonnables), de n'importe quelle longueur et ordre, et donc d'avoir un ensemble de pratiquement toutes les caractĂ©ristiques spectrales de la fenĂȘtre.
Dans le cadre de l'une des Ă©tudes, j'ai rĂ©ussi Ă obtenir un noyau fonctionnant de maniĂšre stable de la fonction de fenĂȘtre Blackman-Harris de 5 et 7 ordres de grandeur sur des Ă©chantillons de 1 M Ă une frĂ©quence de ~ 375 MHz, et Ă©galement Ă crĂ©er un gĂ©nĂ©rateur de coefficients rotatifs pour une FFT basĂ©e sur CORDIC Ă une frĂ©quence de ~ 400 MHz. Cristal FPGA utilisĂ©: Kintex Ultrascale + (xcku11p-ffva1156-2-e).
Lien vers
le projet github ici . Le projet contient un modĂšle mathĂ©matique dans Matlab, des codes sources pour les fonctions de fenĂȘtre et CORDIC en VHDL, ainsi que des modĂšles des fonctions de fenĂȘtre rĂ©pertoriĂ©es en C ++ pour Vivado HLS.
Articles utiles
Je conseille également un livre trÚs populaire sur DSP -
Ayficher E., Jervis B. Digital signal processing. Approche pratiqueMerci de votre attention!