J'essaie de commencer avec DSP dans ma carte Spartan-3. J'ai fait une carte AC97 avec une puce d'une ancienne carte mère, et jusqu'à présent, je l'ai fait pour faire de l'ADC, multiplier les échantillons pour un nombre <1 (diminuer le volume) puis DAC.
Maintenant, j'aimerais faire quelques trucs DSP de base, comme un filtre passe-bas, passe-haut, etc. Mais je suis vraiment confus à propos de la représentation numérique (entiers? Point fixe? Q0.15? Débordement ou saturation?).
Je veux juste un exemple de code d'un filtre simple réel pour me lancer. Pas de haute efficacité, rapide ou quelque chose comme ça. Juste le filtre théorique implémenté en VHDL.
J'ai cherché mais je trouve juste des formules théoriques - je comprends, ce que je ne comprends pas, c'est comment traiter les échantillons audio 16 bits, 48 kHz signés que je reçois de l'ADC. J'utilise ces bibliothèques: http://www.vhdl.org/fphdl/ . Si je multiplie mes échantillons par 0,5, 0,25, etc., je peux entendre la différence. Mais un filtre plus grand ne me donne que du bruit.
Merci.
Réponses:
Il semble que vous devez d'abord comprendre les aspects DSP, puis effectuer une implémentation dans FPGA.
Concernant les types de données, vous pouvez très bien utiliser des entiers.
voici un exemple de code pour vous aider à démarrer. Notez qu'il manque beaucoup de problèmes réels (par exemple, réinitialisation, gestion des débordements) - mais j'espère que c'est instructif:
la source
Le filtre FIR passe-bas le plus simple que vous pouvez essayer est y (n) = x (n) + x (n-1). Vous pouvez l'implémenter assez facilement en VHDL. Vous trouverez ci-dessous un schéma fonctionnel très simple du matériel que vous souhaitez implémenter.
Selon la formule, vous avez besoin des échantillons ADC actuels et précédents afin d'obtenir la sortie appropriée. Ce que vous devez faire est de verrouiller les échantillons ADC entrants sur le front descendant de l'horloge et d'effectuer les calculs appropriés sur le front montant afin d'obtenir la sortie appropriée. Étant donné que vous ajoutez deux valeurs 16 bits ensemble, il est possible que vous vous retrouviez avec une réponse 17 bits. Vous devez stocker l'entrée dans des registres 17 bits et utiliser un additionneur 17 bits. Votre sortie, cependant, sera les 16 bits inférieurs de la réponse. Le code pourrait ressembler à ceci mais je ne peux pas garantir qu'il fonctionnera complètement puisque je ne l'ai pas testé, et encore moins synthétisé.
Comme vous pouvez le voir, vous pouvez utiliser cette idée générale pour ajouter des formules plus compliquées, telles que celles avec des coefficients. Des formules plus compliquées, comme les filtres IIR, peuvent nécessiter l'utilisation de variables pour obtenir une logique d'algorithme correcte. Enfin, un moyen facile de contourner les filtres qui ont des nombres réels comme coefficients est de trouver un facteur d'échelle afin que tous les nombres finissent par être aussi proches que possible des nombres entiers. Votre résultat final devra être revu à la baisse par le même facteur pour obtenir le résultat correct.
J'espère que cela peut vous être utile et vous aider à faire bouger les choses.
* Ceci a été modifié afin que le verrouillage des données et le verrouillage de sortie soient dans des processus distincts. Utilisation également de types signés au lieu de std_logic_vector. Je suppose que votre entrée ADC va être un signal std_logic_vector.
la source
Un autre extrait de code simple (juste les tripes). Remarque Je n'ai pas écrit le VHDL directement, j'ai utilisé MyHDL pour générer le VHDL.
Il s'agit d'une mise en œuvre directe. Il faudra des multiplicateurs. La synthèse de ce circuit, ciblée pour un Altera Cyclone III, n'a pas utilisé de multiplicateurs explicites mais a nécessité 350 éléments logiques.
Ceci est un petit filtre FIR et aura la réponse suivante (pas si grande) mais devrait être utile comme exemple.
De plus, j'ai quelques exemples, ici et ici , qui pourraient être utiles.
En outre, votre question semble demander: "quelle est la représentation appropriée en virgule fixe?" Souvent, lors de la mise en œuvre des fonctions DSP, la représentation en virgule fixe est utilisée, car elle simplifie l'analyse des filtres. Comme mentionné, le point fixe est juste un arthimétique entier. L'implémentation réelle fonctionne simplement avec des entiers, mais notre représentation reçue est fractionnée.
Des problèmes surviennent généralement lors de la conversion de l'implémentation de l'implémentation (virgule fixe) en / en conception flottante.
Je ne sais pas dans quelle mesure les types VHDL à virgule fixe et à virgule flottante sont pris en charge. Ils fonctionneront bien en simulation mais je ne sais pas s'ils vont synthétiser avec la plupart des outils de synthèse. J'ai créé une question distincte pour cela.
la source
OpenCores a un certain nombre d'exemples DSP, IIR et FIR, y compris BiQuad. Vous devrez vous inscrire pour télécharger les fichiers.
edit
Je comprends le commentaire de Kortuk sur les liens morts, et en effet, si le lien vers OpenCores meurt, la réponse deviendra inutile. Je suis convaincu que cela ne se produira pas; mon lien est générique, et il ne mourra que si le domaine OpenCores complet disparaît.
J'ai essayé de chercher des exemples que je pourrais utiliser pour cette réponse, mais ils sont tous trop longs pour être représentés ici. Je vais donc m'en tenir à mes conseils pour vous inscrire au site vous-même (j'ai dû déménager à New York, parce que ma ville natale n'était pas acceptée) et jeter un œil au code qui y est présenté.
la source
J'ai essayé d'implémenter des scripts pour l'implémentation authomatique des filtres IIR, où vous pouvez définir si la conception doit être aussi rapide que possible (pour que chaque multiplication soit effectuée avec un multiplicateur dédié) ou aussi petite que possible (pour que chaque multiplicateur soit réutilisé).
Les sources ont été publiées sur alt.sources comme "Implémentation comportementale mais synthétisable des filtres IIR en VHDL" (vous pouvez également la trouver dans les archives google: https://groups.google.com/group/alt.sources/msg/c8cf038b9b8ceeec ? dmode = source )
Les publications sur alt.sources sont au format "shar", vous devez donc enregistrer le message sous forme de texte et le dés-partager (avec l'utilitaire "unshar") pour obtenir les sources.
la source
Que dis-tu de ça? https://github.com/MauererM/VIIRF
Il implémente un filtre IIR basé sur biquad (SOS, sections de second ordre) qui prend en charge l'implémentation en virgule fixe. Il comprend également des scripts Python pour la conception et la vérification du filtre. Il n'utilise pas de constructions FPGA spécifiques au fournisseur et vous pouvez choisir le compromis entre une utilisation rapide et faible.
la source