J'ai besoin de calculer atan2(x,y)
sur un FPGA avec un flux continu de données d'entrée / sortie. J'ai réussi à l'implémenter à l'aide de noyaux CORDIC déroulés et pipelinés, mais pour obtenir la précision dont j'avais besoin, j'ai dû effectuer 32 itérations. Cela a conduit à consacrer une assez grande quantité de LUT à cette seule tâche. J'ai essayé de changer le flux pour utiliser des noyaux CORDIC partiellement déroulés, mais j'avais ensuite besoin d'une fréquence d'horloge multipliée pour exécuter des boucles répétées tout en maintenant un flux d'entrée / sortie continu. Avec cela, je ne pouvais pas respecter le calendrier.
Alors maintenant, je cherche des moyens de calcul alternatifs atan2(x,y)
.
J'ai pensé à utiliser des tables de recherche de bloc-RAM avec interpolation, mais comme il y a 2 variables, j'aurais besoin de 2 dimensions de tables de recherche, ce qui nécessite beaucoup de ressources en termes d'utilisation de bloc-RAM.
J'ai alors pensé à utiliser le fait atan2(x,y)
lié à l' atan(x/y)
ajustement quadrant. Le problème avec cela est qu'il a x/y
besoin d'une vraie division car ce y
n'est pas une constante, et les divisions sur les FPGA sont très gourmandes en ressources.
Existe-t-il d'autres façons nouvelles d'implémenter atan2(x,y)
sur un FPGA qui entraîneraient une utilisation moindre des LUT, mais fourniraient toujours une bonne précision?
la source
atan2
. Je ne sais pas si vous pouvez vous en tirer sans division, cependant.atan2
. Mais vous aurez toujours besoin d'une division.Réponses:
Vous pouvez utiliser des logarithmes pour vous débarrasser de la division. Pour(x,y) dans le premier quadrant:
Figure 1. Diagramme d'atan(2z)
Vous auriez besoin d'approximativement unatan(2z) dans la plage −30<z<30 pour obtenir la précision requise de 1E-9. Vous pouvez profiter de la symétrie atan(2−z)=π2−atan(2z) ou bien assurez-vous que(x,y) est dans un octant connu. Pour approximer lelog2(a) :
Figure 2. Diagramme dulog2(c)
Pour référence ultérieure, voici le script Python maladroit que j'ai utilisé pour calculer les erreurs d'approximation:
où est la dérivée seconde de et est à un maximum local de l'erreur absolue. Avec ce qui précède, nous obtenons les approximations:f′′(x) f(x) x
Étant donné que les fonctions sont concaves et que les échantillons correspondent à la fonction, l'erreur se produit toujours dans une direction. L'erreur absolue maximale locale pourrait être réduite de moitié si le signe de l'erreur était alterné d'avant en arrière une fois à chaque intervalle d'échantillonnage. Avec une interpolation linéaire, des résultats proches de l'optimisation peuvent être obtenus en préfiltrant chaque table en:
où et sont l'original et la table filtrée s'étendant sur et les poids sont . Le conditionnement final (première et dernière ligne de l'équation ci-dessus) réduit l'erreur aux extrémités du tableau par rapport à l'utilisation d'échantillons de la fonction en dehors du tableau, car le premier et le dernier échantillon n'ont pas besoin d'être ajustés pour réduire l'erreur d'interpolation entre elle et un échantillon juste à l'extérieur de la table. Les sous-tables avec différents intervalles d'échantillonnage doivent être préfiltrées séparément. Les valeurs des poids ont été trouvées en minimisant séquentiellement pour augmenter l'exposantx y 0≤k≤N c0=98,c1=−116,b0=1516,b1=18,b2=−116 c0,c1 N la valeur absolue maximale de l'erreur approximative:
pour les positions d'interpolation entre échantillons , avec une fonction concave ou convexe (par exemple ). Une fois ces poids résolus, les valeurs des poids de conditionnement d'extrémité ont été trouvées en minimisant de manière similaire la valeur absolue maximale de:0≤a<1 f(x) f(x)=ex b0,b1,b2
pour . L'utilisation du préfiltre réduit de moitié l'erreur d'approximation et est plus facile à faire que l'optimisation complète des tableaux.0≤a<1
Figure 4. Erreur d'approximation de partir de 11 échantillons, avec et sans préfiltre et avec et sans conditionnement d'extrémité. Sans conditionnement final, le préfiltre a accès aux valeurs de la fonction juste à l'extérieur du tableau.log2(a)
Cet article présente probablement un algorithme très similaire: R. Gutierrez, V. Torres et J. Valls, « FPGA-implementation of atan (Y / X) based on logarithmic transformation and LUT-based techniques », Journal of Systems Architecture , vol . 56, 2010. Le résumé indique que leur mise en œuvre bat les précédents algorithmes basés sur CORDIC en vitesse et les algorithmes basés sur LUT en taille d'encombrement.
la source