« Very High Speed Integrated Circuit Hardware Description Language/Réalisation d'un coprocesseur CORDIC » : différence entre les versions

Contenu supprimé Contenu ajouté
Wisdood (discussion | contributions)
m étidiants
m Robot : Remplacement de texte automatisé (-(<|</)source([ \t>]) +\1syntaxhighlight\2)
Ligne 83 :
 
Sans entrer dans les détails, nous vous proposons des sous-programmes réservés aux architectures de type PC :
<sourcesyntaxhighlight lang=c>
// Serge MOUTOU Avril 2013
// destiné à une architecture 32 bits et non aux AVRs ciblés
Ligne 154 :
}
 
</syntaxhighlight>
</source>
{{remarque|
*Le type "int" du c n’est pas défini de manière standard. Il peut être sur 16, 32 ou 64 bits. Il est de 16 bits sur AVR et de 32 bits sur un PC.
Ligne 162 :
 
Comme nous l'avons énoncé au tout début de cette section, une simple routine universelle pourrait donc être réalisée par :
<sourcesyntaxhighlight lang=c>
// Serge MOUTOU Juin 2018
// destiné à une architecture quelconque
Ligne 168 :
return (val * 1.0 / (0x2000)); // 0x2000 = 1 en Q3.13
}
</syntaxhighlight>
</source>
Attachons-nous maintenant à la transformation inverse.
 
==== Format flottant vers Q3.13 ====
La transformation du format flottant vers le Q3.13 se fait par :
<sourcesyntaxhighlight lang=c>
// Serge MOUTOU Avril 2013
// destiné à une architecture 32 bits et non aux AVRs ciblés
Ligne 265 :
}
}
</syntaxhighlight>
</source>
Cette première routine ne contient pas de vérification d'erreur tandis que la deuxième affiche une erreur mais retourne quand même un nombre. Le format "float" du c étant plus précis que notre format Q3.13, cette routine peut échouer. Elle reste cependant utile dans le cadre de CORDIC.
 
Ligne 272 :
 
{{Boîte déroulante|titre=Programme de vérification sous Arduino|contenu=
<sourcesyntaxhighlight lang=Arduino>
void setup() {
Serial.begin(9600);
Ligne 352 :
if (val < 0) return -(u.f_temp); else return u.f_temp;
}
</syntaxhighlight>
</source>
}}
 
Ligne 614 :
 
Pour pallier à cet inconvénient, nous le remettons ici :
<sourcesyntaxhighlight lang=C>
#include <stdio.h>
#include <stdlib.h>
Ligne 655 :
return 0;
}
</syntaxhighlight>
</source>
}}
Le fonctionnement de cet algorithme semble parfait. Pourtant, nous allons essayer de l'améliorer pour un fonctionnement dans une architecture bien plus petite qu'un PC. En effet, compilé tel quel avec le compilateur avr-gcc, il faut plus de 8 ko de mémoire, ce qui n’est pas toujours possible pour certains processeurs (ATMega8 et ATTiny861) que nous utilisons dans ce cours.
Ligne 695 :
Nous avons réalisé ce cœur sans utiliser les boucles du VHDL ce qui allonge un peu le code de ce coprocesseur CORDIC, c’est pourquoi nous le mettons dans une boite déroulante.
{{Boîte déroulante|titre=Notre coprocesseur CORDIC pipeline|contenu=
<sourcesyntaxhighlight lang=vhdl>
-- Serge Moutou avril 2013
-- CORDIC en format virgule fixe Q3.13 et 13 étages pipelinés
Ligne 982 :
sin <= y_array_13;
END rtl;
</syntaxhighlight>
</source>
}}
Ce code n'a pas été développé avec une boucle VHDL pour des raisons d'optimisation.
Ligne 994 :
==== Augmenter l'intervalle de calcul des angles ====
Gilles Millon a profité du passage du mode pipeline au mode séquentiel pour réaliser un coprocesseur CORDIC capable de traiter des angles de <math>-\pi</math> à <math>+\pi</math> au lieu de <math>-\pi \over 2</math> à <math>+\pi \over 2</math>. Ceci peut être fait avec le code [[w:VHDL|VHDL]] suivant :
<sourcesyntaxhighlight lang=vhdl>
-- pretraitement angle
process(angle) begin
Ligne 1 019 :
end if;
end process;
</syntaxhighlight>
</source>
où vous voyez une mémorisation dans coeffx et coeffy du quadrant concerné.
 
Ligne 1 036 :
{{Clr}}
{{Boîte déroulante|titre=Notre coprocesseur CORDIC séquentiel (sans le séquenceur)|contenu=
<sourcesyntaxhighlight lang=vhdl>
library ieee;
use ieee.std_logic_1164.all;
Ligne 1 346 :
end behavior;
</syntaxhighlight>
</source>
}}
 
Ligne 1 369 :
{{Boîte déroulante|titre=Notre coprocesseur CORDIC comme périphérique de l'ATMega|contenu=
Le code source ci-dessous suit exactement la figure ci-dessus.
<sourcesyntaxhighlight lang=vhdl>
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
Ligne 1 585 :
 
end Behavioral;
</syntaxhighlight>
</source>
}}
Une remarque pour terminer.
Ligne 1 604 :
Le coprocesseur CORDIC fournit un calcul à l'ATMega et c’est ce dernier qui est chargé de le donner à l'extérieur pour tester. Le meilleurs moyen de réaliser tout cela est d’utiliser la liaison série. On entre l'angle sur lequel on veut faire le calcul dans un hyperterminal, le calcul se fait et le résultat s'affiche sur l'écran de l'hyperterminal. Mais pour faire cela il faut transformer la chaîne fournie par l'hyperterminal en format Q3.13 et inversement, le résultat Q3.13 devra être converti en chaîne de caractères avant d’être envoyé. Pour faciliter ces conversions, nous proposons quelques utilitaires regroupés ci-dessous :
{{Boîte déroulante|titre=Des utilitaires pour AVR pour utiliser le coprocesseur CORDIC|contenu=
<sourcesyntaxhighlight lang=c>
//************************************************************************
// function HexQ3_13ToFloat_AVR()
Ligne 1 893 :
return UDR;
}
</syntaxhighlight>
</source>
}}
Si ces utilitaires ne fonctionnent pas cela peut être dû à un problème dans la vitesse de transmission. Toutes ces routines sont commentées pour 38400 bauds mais peuvent fonctionner à des vitesses doubles ou moitié selon votre horloge système !
Ligne 1 899 :
=== Un programme principal pour tester ===
On donne un exemple partiel de programme principal pour tester :
<sourcesyntaxhighlight lang=c>
do {
nbOK=0;
Ligne 1 942 :
_delay_ms(500);
} while(1);
</syntaxhighlight>
</source>
Nous allons proposer quelques exercices matériels pour ceux qui veulent aller plus loin.
== Quelques idées pour des exercices complémentaires ==
Ligne 1 982 :
{{solution|titre=Solution partielle|contenu=
D'abord la connexion du registre PORTD responsable du positionnement de "ena" (en poids faible) :
<sourcesyntaxhighlight lang=vhdl>
-- IO write process
--
Ligne 2 010 :
end if;
end process;
</sourcesyntaxhighlight >
Ensuite la lecture de l'état du calcul avec encore le PORTD :
<sourcesyntaxhighlight lang=vhdl>
iord: process(I_ADR_IO, U_RX_DATA, U_RX_READY, L_RX_INT_ENABLED,
U_TX_BUSY, L_TX_INT_ENABLED,sinMSB,sinLSB,cosMSB,cosLSB)
Ligne 2 056 :
end case;
end process;
</sourcesyntaxhighlight >
Ensuite le cœur CORDIC modifié
<sourcesyntaxhighlight lang=vhdl>
library ieee;
use ieee.std_logic_1164.all;
Ligne 2 370 :
sin <= y_array_13;
END rtl;
</sourcesyntaxhighlight >
Et enfin les extraits du programme C utilisant ce cour CORDIC modifié
<sourcesyntaxhighlight lang=C>
do {
nbOK=0;
Ligne 2 413 :
_delay_ms(500);
} while(1);
</syntaxhighlight>
</source>
Remarquez que le matériel nécessite le passage du bit de poids faible à 0 avant un nouveau départ. Cette façon de faire pourrait être améliorée en utilisant un seul bit pour le départ et pour le done mais sa gestion se complique un peu.
}}
Ligne 2 419 :
=== Réalisation matérielle de la conversion virgule fixe vers virgule flottante ===
Cette conversion était l'objectif de la fonction donnée et déjà utilisée dans un exercice précédent :
<sourcesyntaxhighlight lang=c>
float HexQ3_13ToFloat(int val)
</syntaxhighlight>
</source>
Un coup d'œil sur le code source de cette fonction montre des calculs de puissance de deux en flottant et notre objectif ici est de les éliminer en laissant le matériel les réaliser. Pour ce faire, il est possible d’utiliser un cœur de calcul flottant, il en existe chez Opencores.org. Mais on va être plus subtil car notre conversion se fait dans un cas suffisamment simple et nous allons tenter une réalisation sans multiplication.
 
Ligne 2 446 :
 
Voici comment les choses se font sous Linux/Windows ('''en format simple précision''') : on remarquera l'absence de multiplication et de calcul flottant :
<sourcesyntaxhighlight lang=c>
// Serge Moutou avril 2013 version 0.9
// ************ Mai 2014 version 1.0 : remplacement pointeur par union
Ligne 2 474 :
if (val < 0) return -(u.temp); else return u.temp;
}
</syntaxhighlight>
</source>
2°) On va réaliser la conversion ci-dessus dans le matériel (en VHDL donc). En clair, notre cœur CORDIC va continuer à travailler en virgule fixe, mais le résultat sera converti en flottant par le matériel puis retourné au processeur.