Cette question concerne l'implémentation d'un filtre IIR dans un FPGA avec des tranches DSP, avec des critères très spécifiques.
Disons que vous faites un filtre sans taps avant et seulement 1 tap inversé, avec cette équation:
(voir image)
Prenez la tranche DSP48A1 de Xilinx comme exemple - la plupart des tranches DSP IP dures sont similaires.
Disons que vous avez des données analogiques entrant à 1 échantillon par horloge. Je voudrais concevoir un filtre IIR qui fonctionne de manière synchrone à l'horloge d'échantillonnage.
Le problème est que pour exécuter la tranche DSP au taux maximum, vous ne pouvez pas multiplier ET ajouter sur le même cycle. Vous devez avoir un registre de pipeline entre ces composants.
Donc, si vous avez 1 nouvel échantillon à chaque horloge, vous devrez produire 1 sortie par horloge. Cependant, vous avez besoin des horloges de sortie précédentes 2 avant de pouvoir en produire une nouvelle dans cette conception.
La solution évidente consiste soit à traiter les données à une fréquence d'horloge double, soit à désactiver le registre de pipeline afin de pouvoir multiplier et ajouter dans le même cycle.
Malheureusement, si vous échantillonnez à la fréquence d'horloge maximale de la tranche DSP entièrement pipelinée, aucune de ces solutions n'est possible. Y a-t-il un autre moyen de construire cela?
(Points bonus si vous pouvez concevoir un filtre IIR qui fonctionne à la moitié du taux d'échantillonnage, en utilisant n'importe quel nombre de tranches DSP)
L'objectif serait d'exécuter un filtre de compensation pour un ADC 1 GSPS dans un FPGA Xilinx Artix. Leurs tranches DSP peuvent fonctionner un peu plus de 500 MHz lorsqu'elles sont entièrement pipelinées. S'il existe une solution pour 1 échantillon par horloge, je voudrais essayer de mettre à l'échelle la solution pour 2 échantillons par horloge. Tout cela est très facile avec un filtre FIR.
Réponses:
Je n'ai pas encore travaillé avec les filtres IIR, mais si vous avez seulement besoin de calculer l'équation donnée
une fois par cycle CPU, vous pouvez utiliser le pipelining.
Dans un cycle, vous effectuez la multiplication et dans un cycle, vous devez faire la sommation pour chaque échantillon d'entrée. Cela signifie que votre FPGA doit être capable de faire la multiplication en un cycle lorsqu'il est cadencé à la fréquence d'échantillonnage donnée! Ensuite, vous aurez seulement besoin de faire la multiplication de l'échantillon actuel ET la somme du résultat de multiplication du dernier échantillon en parallèle. Cela entraînera un décalage de traitement constant de 2 cycles.
Ok, regardons la formule et concevons un pipeline:
Votre code de pipeline pourrait ressembler à ceci:
Notez que les trois commandes doivent être exécutées en parallèle et que la "sortie" sur la deuxième ligne utilise donc la sortie du dernier cycle d'horloge!
Je n'ai pas beaucoup travaillé avec Verilog, donc la syntaxe de ce code est très probablement erronée (par exemple, largeur de bit manquante des signaux d'entrée / sortie; syntaxe d'exécution pour la multiplication). Cependant, vous devriez avoir l'idée:
PS: Peut-être qu'un programmeur Verilog expérimenté pourrait modifier ce code et supprimer ce commentaire et le commentaire au-dessus du code par la suite. Merci!
PPS: dans le cas où votre facteur "b1" est une constante fixe, vous pourriez être en mesure d'optimiser la conception en implémentant un multiplicateur spécial qui ne prend qu'une seule entrée scalaire et calcule les "temps b1" uniquement.
Réponse à: "Malheureusement, cela équivaut en fait à y [n] = y [n-2] * b1 + x [n]. Cela est dû à l'étape supplémentaire du pipeline." comme commentaire à l'ancienne version de la réponse
Oui, c'était en fait correct pour l'ancienne version (INCORRECTE !!!) suivante:
J'espère avoir corrigé ce bug maintenant en retardant les valeurs d'entrée, également dans un deuxième registre:
Pour nous assurer que cela fonctionne correctement cette fois, regardons ce qui se passe lors des premiers cycles. Notez que les 2 premiers cycles produisent plus ou moins de déchets (définis), car aucune valeur de sortie précédente (par exemple y [-1] == ??) n'est disponible. Le registre y est initialisé à 0, ce qui revient à supposer que y [-1] == 0.
Premier cycle (n = 0):
Deuxième cycle (n = 1):
Troisième cycle (n = 2):
Quatrième cycle (n = 3):
Nous pouvons voir qu'à partir de cylce n = 2, nous obtenons la sortie suivante:
ce qui équivaut à
Comme mentionné ci-dessus, nous introduisons un décalage supplémentaire de l = 1 cycle. Cela signifie que votre sortie y [n] est retardée de retard l = 1. Cela signifie que les données de sortie sont équivalentes mais sont retardées d'un "index". Pour être plus clair: les données de sortie retardées sont de 2 cycles, car un cycle d'horloge (normal) est nécessaire et 1 cycle d'horloge supplémentaire (décalage l = 1) est ajouté pour l'étage intermédiaire.
Voici un croquis pour décrire graphiquement comment les données circulent:
PS: Merci d'avoir regardé de près mon code. J'ai donc aussi appris quelque chose! ;-) Faites-moi savoir si cette version est correcte ou si vous voyez d'autres problèmes.
la source
y[n+l] = y[n-1] * b + x[n]
une valeur fixe pour le décalagel
qui peut être réécrity[n] = y[n-1-l] * b + x[n-l]
et pour l = 1, c'est-à-direy[n] = y[n-2] * b + x[n-1]
.y[n+l] = x[n] * b0 + x[n-1] * b1 - y[n-1] * a1 - y[n-2] * a2
=>y[n] = x[n-l]*b0 + x[n-1-l] * b1 - y[n-1-l] * a1 - y[n-2-l]*a2
. En supposant que vous pouvez faire les trois multiplications en parallèle (1. étape / 1 cycle) et que vous devez faire pour ajouter les produits ensemble, vous avez besoin de 2 cycles (1 cycle: ajouter / sous deux premiers résultats de produit, 1 cycle: ajouter / sous le résultat de ces deux add / subs), vous aurez besoin de 2 cycles supplémentaires. Donc l = (3-1) = 2 vous donnanty[n]=x[n-2]*b0+x[n-1-2]*b1-y[n-1-2]*a1-y[n-2-2]*a2
=>y[n]=x[n-2]*b0+x[n-3]*b1-y[n-3]*a1-y[n-4]*a2
Oui, vous pouvez cadencer à la fréquence d'échantillonnage.
Une solution à ce problème consiste à manipuler l'expression d'origine afin que les registres de pipeline puissent être insérés, tout en conservant la séquence de sortie souhaitée.
Soit: y [n] = y [n-1] * b1 + x [n];
cela peut être manipulé en: y [n] = y [n-2] * b1 * b1 + x [n-1] * b1 + x [n].
Pour vérifier qu'il s'agit de la même séquence, considérez ce qui arrive aux premiers échantillons x [0], x [1], x [2] etc., où avant x [0] tous les échantillons x, y étaient nuls.
Pour l'expression originale, la séquence est:
Il est clair qu'il faut que b1 <1, sinon cela croîtra sans limite.
Considérons maintenant l'expression manipulée:
C'est la même séquence.
Une solution matérielle dans les primitives de bibliothèque Xilinx aurait besoin de deux DSP48E en cascade. Reportez-vous à la figure 1-1 dans UG193 v3.6 pour les noms de port et de registre ci-dessous. La première primitive multiplie par b1 et ajoute une horloge plus tard; la seconde multiplie par b1 * b1 et ajoute une horloge plus tard. Il existe une latence de pipeline de 4 horloges pour cette logique.
- DSP48E # 1
a_port1: = b1; - coefficient constant, régler AREG = 1
b_port1: = x; - définir l'attribut BREG = 1
c_port1: = x; - définir CREG = 1
- interne au DSP48E # 1
reg_a1 <= a_port1;
reg_b1 <= b_port1;
reg_c1 <= c_port1;
reg_m1 <= reg_a1 * reg_b1;
reg_p1 <= reg_m1 + reg_c1; - sortie du 1er DSP48E
- fin du DSP48E # 1
- DSP48E # 2
a_port2: = reg_p2; - définir l'attribut AREG = 0
b_port2: = b1 * b1; - constante, définissez BREG = 1
c_port2: = reg_p1; - définir CREG = 1
- interne au DSP48E # 2
reg_b2 <= b_port2;
reg_c2 <= c_port2;
reg_m2 <= a_port2 * reg_b2;
reg_p2 <= reg_m2 + reg_c2;
- fin du DSP48E # 2
La séquence à reg_p1:
x [0],
x [1] + x [0] * b1,
x [2] + x [1] * b1,
x [3] + x [2] * b1,
etc.
La séquence à reg_p2 est le résultat souhaité. En interne au 2ème DSP48E, le registre reg_m2 a une séquence:
x [0] * b1 * b1,
x [1] * b1 * b1 + x [0] * b1 * b1 * b1,
x [2] * b1 * b1 + x [1] * b1 * b1 * b1 + x [0] * b1 * b1 * b1 * b1
Il y a une belle élégance à ce résultat. De toute évidence, le DSP48E ne se multiplie pas et n'ajoute pas la même horloge, mais c'est ce que l'équation de différence nécessite. L'équation de différence manipulée nous permet de tolérer les registres M et P dans le DSP48E et l'horloge à pleine vitesse.
la source