Vous êtes sur la page 1sur 18

2010

Calcul flottant en VHDL

THOMSON
Grass Valley France SA

BOUZID Bruno
Junior electronic numeric and RF design engineer
THOMSON Grass Valley 2010

Sommaire
I) Principes de codage sous forme IEEE-754 P3

II) Conversion : Entier => Flottant P6

III) Addition / Soustraction P8

IV) Multiplication P13

V) Division P15

VI) Conversion : Flottant => Entier P17

BOUZID Bruno Junior electronic numeric and RF design engineer 2


THOMSON Grass Valley 2010

I) Principes de codage sous forme IEEE-754

Dans le but d’alléger la structure du prochain SIRIUS, il a été suggéré de traiter les calculs
complexes par le FPGA et non plus par un processeur embarqué (µblase). Il s’agirait d’un
gain d’espace, car lorsqu’on utilise un microprocesseur embarqué nous sommes obligés de
lui rattacher deux boitiers (SDRAM et Mémoire Flash).Nous gagnerons aussi du temps de
calcul. Il faudra donc, pour réussir à totalement se passer du µp, réussir à utiliser ce code
pour réaliser les fonctions NLC et ALE (fonctions de corrélations et filtres adaptatifs…).

La base de ce code est la norme IEEE-754 :

Un nombre flottant est formé de trois éléments : la mantisse, l'exposant et le signe. Le


bit de poids fort est le bit de signe. Cela signifie que si ce bit est à 1, le nombre est négatif, et
s’il est à 0, le nombre est positif. Les e bits suivants représentent l'exposant décalé, et les m
bits suivants (m bits de poids faible) représentent la mantisse.

L'exposant est décalé de 2e-1 - 1 (e représente le nombre de bits de l'exposant). Ce


décalage est utile car l'exposant peut être positif ou négatif. Cependant, la représentation
habituelle des nombres signés (complément à 2) rendrait la comparaison entre les nombres
flottants difficile. Pour régler ce problème, l'exposant est décalé, afin de le stocker sous
forme d'un nombre non signé.

L'interprétation d'un nombre (autre qu'infini) est donc :

Valeur = signe × 1,mantisse × 2exposant − (2e−1−1), avec signe = ±1.

Le bit de poids fort de la mantisse est déterminé par la valeur de l'exposant. Si l'exposant
est différent de 0 et de 2e − 1, le bit de poids fort de la mantisse est 1, et le nombre est dit
"normalisé". Si l'exposant est nul, le bit de poids fort de la mantisse est nul, et le nombre est
'dé-normalisé'. Il y a trois cas particuliers :

 si l'exposant et la mantisse sont tous deux nuls, le nombre est ±0 (selon le bit de
signe)

BOUZID Bruno Junior electronic numeric and RF design engineer 3


THOMSON Grass Valley 2010

 si l'exposant est égal à 2e − 1, et si la mantisse est nulle, le nombre est ±infini (selon le
bit de signe)
 si l'exposant est égal à 2e − 1, mais que la mantisse n'est pas nulle, le nombre est NaN
(not a number : pas un nombre).

Nous pouvons le résumer ainsi :

Format simple précision (32 bits) :

Un nombre flottant simple précision est stocké dans un mot de 32 bit : 1 bit de signe,
8 bits pour l'exposant et 23 pour la mantisse.

L'exposant est décalé de 28 − 1 − 1 = 127 dans ce cas. L'exposant va donc de -126 à


+127. Un exposant de -127 serait décalé vers la valeur 0, mais celle-ci est réservée pour 0 et
les nombres dé-normalisés. Un exposant de 128 serait décalé vers 255, qui est réservé pour
coder les infinis, et les NaNs. (Voir le tableau précédent).

Pour les nombres normalisés (la plupart), Exp est l'exposant décalé et Fraction est la
partie fractionnelle de la partie significative. Le nombre a la valeur suivante :

v = s × 2e × m :

s = +1 (nombre positif) lorsque le bit de signe est nul.

s = −1 (nombre négatif) lorsque le bit de signe est à 1.

BOUZID Bruno Junior electronic numeric and RF design engineer 4


THOMSON Grass Valley 2010

e = Exposant − 127 (l'exposant est stocké avec 127 ajouté, autrement dit, "décalé de 127")

m = 1,fraction (en binaire). D'où 1 ≤ m < 2.

Remarques :

 Les nombres dénoralisés suivent le même principe, sauf que e = −126 et


m=0,fraction. (Attention: e n'est pas -127 mais -126, ceci afin de garantir la continuité
de cette représentation avec la représentation normalisée, puisque m=0,fraction et
non plus m=1,fraction.)
 −126 est la plus petite valeur possible pour l'exposant d'un nombre normalisé.
 Il y a deux 0 : +0 et −0 selon la valeur de S
 Il y a deux infinis : +∞ et −∞ selon la valeur de S
 Les NaNs peuvent avoir un signe et une partie significative, mais ils n'ont pas de sens,
sauf pour la correction d'erreurs.
 les NaNs et les infinis n'ont que des 1 dans le champ "exposant".
 Le plus petit nombre positif différent de zéro, et le plus grand nombre négatif
différent de zéro (représentés par une valeur dénormalisée avec tous les bits du
champ exposant à 0 et la valeur binaire 1 dans le champ Fraction) sont :

±2−149 ≈ ±1,4012985×10−45

 Le plus petit nombre positif normalisé différent de zéro, et le plus grand nombre
négatif normalisé différent de zéro (représentés par la valeur binaire 1 dans le champ
Exp, et 0 dans le champ Fraction) sont :

±2−126 ≈ ±1,175494351×10−38

 Le plus grand nombre positif fini, et le plus petit nombre négatif fini (représenté par
la valeur 254 dans le champ Exp et tous les bits à 1 dans le champ Fraction) sont :

±(224-1) × 2104 ≈ ±3,4028235×1038

Voici un tableau résumant la partie précédente, avec des exemples de nombres 32 bits
simple précision.

BOUZID Bruno Junior electronic numeric and RF design engineer 5


THOMSON Grass Valley 2010

II ) Conversion : Entier => Flottant

Mise en forme préliminaire:

Sachant qu’on traite des nombres aussi bien négatifs que positifs, le MSB du mot
entrant sera donc significatif de son signe :

- S’il est à "1", il est donc négatif, et nous devons le complémenter :

val_input <= x"9870"; en binaire "9870" = " 1001 1000 0111 0000".

Pour le coté pratique du programme nous garderons le MSB à sa valeur d’origine,


donc après avoir été complémenté, voici le résultat :

" 1001 1000 0111 0000" => " 1110 0111 1001 0000", tout en sachant que seuls les 15 LSB
expriment une valeur numérique, le 16ème est attribué au signe.

-S’il est à "0", on le garde tel qu’il est.

Manipulations:

Nous cherchons le premier "1" en partant du MSB (du 15ème au 1er), pour définir le
décalage à effectuer, lors du calcul de l’exposant. Voici un exemple :

"1111 1101 1101 1001" => Le MSB est le bit de signe, ce qui veut dire que ce nombre est
négatif, en complément à deux, en gardant le bit de signe, il vaut "1000 0010 0010 0111"
ensuite c’est le bit numéro 10 qui est le premier à "1", donc nous aurons un décalage de nb =
15 – 10 = 5.

Après obtention de la valeur de décalage nous pouvons calculer l’exposant. Comme


dit précédemment nous avons de base 127, ensuite nous ajoutons (14 – nb) .Sachant que 0 ≤
nb ≤ 14 et que nous avons établi un cas à part pour l’éventualité de tout à zéro, ici notre
exposant aura pour valeur : 127 + 14 – 5 = 136, codé sur 8 bits => "10001000".

BOUZID Bruno Junior electronic numeric and RF design engineer 6


THOMSON Grass Valley 2010

Maintenant il nous est possible d’établir la valeur de la mantisse, sachant que nous
avons fait des cas particuliers pour nb = 1 et nb = 0 ; nous avons procédé à ce calcul :

Mantisse = Valeur( (13 - nb ) downto 0) & zero( ( 8 +nb )downto 0);

Le nombre zéro est un mot ne contenant que des "0", nous permettant de combler le
manque d’information que nous pouvons donner à notre nombre. Pour une meilleure
compréhension nous continuons sur l’exemple précedent :

Mantisse = Valeur ( 8 downto 0) & zero (13 downto 0)

Mantisse = 1, 000 1001 1100 0000 0000 0000

Ce qui signifie que l’on prend les 9 premiers bits de Valeur et 14 "0" pour une mantisse de
23 bits. Le premier "1" ne figure pas dans la mantisse car il est virtuellement, on sait que
c’est lui le MSB, même si on ne le met pas dans le nombre sous forme IEEE-754. Donc nous
avons en sorti :

Temp_in étant la valeur de val_input après le complément à 2.

BOUZID Bruno Junior electronic numeric and RF design engineer 7


THOMSON Grass Valley 2010

III) Addition / Soustraction

Définition des différents cas:

Il existe 22 cas différents, les voici :

* Signe 1 négatif et signe 2 positif

- Cas n°1 : Exposant 1 > Exposant 2

- Cas n°2 : Exposant 1 < Exposant 2

- Cas n°3 : Exposant 1 = Exposant 2 Mantisse 1 > Mantisse 2

- Cas n°4 : Exposant 1 = Exposant 2 Mantisse 1 < Mantisse 2

- Cas n°5 : Exposant 1 = Exposant 2 Mantisse 1 = Mantisse 2

* Signe 1 positif et signe 2 négatif

- Cas n°6 : Exposant 1 > Exposant 2

- Cas n°7 : Exposant 1 < Exposant 2

- Cas n°8 : Exposant 1 = Exposant 2 Mantisse 1 > Mantisse 2

- Cas n°9 : Exposant 1 = Exposant 2 Mantisse 1 < Mantisse 2

- Cas n°10 : Exposant 1 = Exposant 2 Mantisse 1 = Mantisse 2

* Signe 1 et signe 2 négatif

- Cas n°11 : Exposant 1 > Exposant 2

- Cas n°12 : Exposant 1 < Exposant 2

- Cas n°13 : Exposant 1 = Exposant 2 Mantisse 1 > Mantisse 2

- Cas n°14 : Exposant 1 = Exposant 2 Mantisse 1 < Mantisse 2

- Cas n°15 : Exposant 1 = Exposant 2 Mantisse 1 = Mantisse 2

BOUZID Bruno Junior electronic numeric and RF design engineer 8


THOMSON Grass Valley 2010

* Signe 1 et signe 2 positif

- Cas n°16 : Exposant 1 > Exposant 2

- Cas n°17 : Exposant 1 < Exposant 2

- Cas n°18 : Exposant 1 = Exposant 2 Mantisse 1 > Mantisse 2

- Cas n°19 : Exposant 1 = Exposant 2 Mantisse 1 < Mantisse 2

- Cas n°20 : Exposant 1 = Exposant 2 Mantisse 1 = Mantisse 2

- Cas n°21 : Exposant 1 >> Exposant 2

- Cas n°22 : Exposant 1 << Exposant 2

Décalage et première opération de complément à 2:

On prendra simplement les cas de figures ou les exposants sont différents, pour
opérer un décalage. Il sert à obtenir deux exposants similaires, pour que le calcul soit
cohérent, par exemple :

Dans le cas n°16 :

49878 + 2398 (Nombre en décimal)

4742D600 + 4515E000 (format IEEE-754)

Signe : Positif Signe : Positif

Exposant : "1000 1110" => 142 (en décimal) Exposant : "1000 1010" => 138 (en décimal)

Mantisse : 1, "010 1101 0110 0000 0000 0000" Mantisse : 1, "001 0101 1110 0000 0000 0000"

BOUZID Bruno Junior electronic numeric and RF design engineer 9


THOMSON Grass Valley 2010

Il faudra donc décaler la mantisse du deuxième nombre de 142 – 138 = 4, alors nous
aurons :

Signe : Positif Signe : Positif

Exposant : "1000 1110" => 142 (en décimal) Exposant : "1000 1110" => 142 (en décimal)

Mantisse : 1, "010 1101 0110 0000 0000 0000" Mantisse : 0, "000 1001 0101 1110 0000 0000 "

Nous procéderons dans cette même étape à la transformation en complément à 2 de


la première valeur du cas n°1 et la deuxième valeur du cas n°7.

Addition ou soustraction selon les cas:

Au cours de cette étape nous effectuerons des additions pour :

- Les cas 1 et 7 car nous les avons complémentés une première fois et nous
complémenterons une deuxième fois, l’addition effectuée.

-Les cas 11 à 20 car les valeurs d’entrées sont de même signe.

Nous effectuerons une soustraction pour :

- Les cas 2 et 6 car nous avons mis les deux valeurs d’entrées sur le même exposant, donc
nous savons forcement lequel est le plus grand

- Les cas 3, 4, 5 et 8, 9, 10 car les exposants des valeurs d’entrées sont déjà les même, nous
savons par la même dès le départ qu’elle valeur a la plus grande mantisse.

C’est dans le souci de réaliser des calculs avec des nombres non-signés que nous
avons procédé à ce type de réflexion.

A la suite de cette étape nous complémenterons le résultat obtenu pour les cas 1 et 7

BOUZID Bruno Junior electronic numeric and RF design engineer 10


THOMSON Grass Valley 2010

Décalage et modification de l’exposant:

Nous procédons maintenant, à la dernière manipulation : Nous décalons les


mantisses pour faire en sorte quelles soient conformes à la norme IEEE-754, exemple :

Mantisse_int = "0 0,000 1110 1010 0110 1010 0000" ; il nous faut donc le décaler de 4 rangs
vers la gauche.

Mantisse_out = "1,110 1010 0110 1010 0000 0000", nous retrancherons 4 à l’exposant le
plus grand des deux valeurs entrées.

A la suite de cette étape il nous est facile de conclure en assemblant le signe,


l’exposant et la mantisse.

La soustraction:

Il nous suffit simplement de changer le signe de la deuxième valeur entrée. Et de


changer les cas tel que :

* Signe 1 et signe 2 négatif

- Cas n°1 : Exposant 1 > Exposant 2

- Cas n°2 : Exposant 1 < Exposant 2

- Cas n°3 : Exposant 1 = Exposant 2 Mantisse 1 > Mantisse 2

- Cas n°4 : Exposant 1 = Exposant 2 Mantisse 1 < Mantisse 2

- Cas n°5 : Exposant 1 = Exposant 2 Mantisse 1 = Mantisse 2

* Signe 1 et signe 2 positif

- Cas n°6 : Exposant 1 > Exposant 2

BOUZID Bruno Junior electronic numeric and RF design engineer 11


THOMSON Grass Valley 2010

- Cas n°7 : Exposant 1 < Exposant 2

- Cas n°8 : Exposant 1 = Exposant 2 Mantisse 1 > Mantisse 2

- Cas n°9 : Exposant 1 = Exposant 2 Mantisse 1 < Mantisse 2

- Cas n°10 : Exposant 1 = Exposant 2 Mantisse 1 = Mantisse 2

* Signe 1 négatif et signe 2 positif

- Cas n°11 : Exposant 1 > Exposant 2

- Cas n°12 : Exposant 1 < Exposant 2

- Cas n°13 : Exposant 1 = Exposant 2 Mantisse 1 > Mantisse 2

- Cas n°14 : Exposant 1 = Exposant 2 Mantisse 1 < Mantisse 2

- Cas n°15 : Exposant 1 = Exposant 2 Mantisse 1 = Mantisse 2

* Signe 1 positif et signe 2 négatif

- Cas n°16 : Exposant 1 > Exposant 2

- Cas n°17 : Exposant 1 < Exposant 2

- Cas n°18 : Exposant 1 = Exposant 2 Mantisse 1 > Mantisse 2

- Cas n°19 : Exposant 1 = Exposant 2 Mantisse 1 < Mantisse 2

- Cas n°20 : Exposant 1 = Exposant 2 Mantisse 1 = Mantisse 2

- Cas n°21 : Exposant 1 >> Exposant 2

- Cas n°22 : Exposant 1 << Exposant 2

BOUZID Bruno Junior electronic numeric and RF design engineer 12


THOMSON Grass Valley 2010

IV) Multiplication

Une petite introduction sur la multiplication binaire est nécessaire. La multiplication


binaire se réalise comme une multiplication décimale. C'est peut être un peu lointain pour
vous, mais quelle est donc la méthode que vous utilisez pour multiplier 2 nombres en base
10 ?
La méthode utilisée consiste à multiplier le premier terme par l'unité du second, et
d'inscrire le résultat de cette multiplication sous la première barre. Puis de décaler d'une
colonne vers la gauche et de faire à nouveau la multiplication mais cette fois ci en utilisant
les dizaines, et ainsi de suite jusqu'au terme le plus élevé du second membre. Une fois
toutes les multiplications réalisées, on additionne les résultats pour obtenir le produit de la
multiplication.
En binaire, on utilise la même méthode, mais cette fois ci, c'est encore plus simple
puisqu'on ne multiplie que des termes qui sont 1 ou 0. Or il est connu de tous que 1 est
l'élément neutre de la multiplication et zéro l'élément nul. De plus, la multiplication binaire
conserve les mêmes règles de commutativité, d'associativité et de distributivité que la
multiplication décimale. Exemple :

Donc pour une multiplication à N × N bits, notre résultat sera forcement sur 2N-1 bits
et le 2Nème bit sera considéré comme une retenue.

BOUZID Bruno Junior electronic numeric and RF design engineer 13


THOMSON Grass Valley 2010

Le signe:

Il existe 4 cas de figures différents pour déterminer le signe de sortie de la


multiplication :

*Signe de sortie positif :

-signe 1 et signe 2 positifs

-signe 1 et signe 2 négatifs

*Signe de sortie négatif :

-signe 1 négatif et signe 2 positif

-signe 1 positif et signe 2 négatif

La mantisse:

Pour ce calcul, nous avons créé un sous-programme, dans celui-ci est tout
simplement implémenté un DSP48 qui gère tout seul la multiplication. Comme nous savons
que le 47ème bit est à "1" nous prenons comme mantisse de sortie, du 46ème au 24ème bit :
(result_prod_mantisse(45 downto 23)

Si le 48ème bit(retenue) est à "1" alors nous prendrons comme mantisse de sortie, du 47ème au
ème
25 bit : (result_prod_mantisse(46 downto 24)

L’exposant:

Pour obtenir l’exposant de sortie, il nous suffit simplement d’additionner les deux
exposants des nombres d’entrées et d’y ajouter la probable retenue de la multiplication des
mantisses, tel que :

(exposant_1 + exposant_2 + ( result_prod_mantisse(47))) - 127)

On retranche 127 car les exposants le contienne tout les deux, hors il n’est à prendre
en compte qu’une seule fois.

BOUZID Bruno Junior electronic numeric and RF design engineer 14


THOMSON Grass Valley 2010

V) Division

Une petite introduction sur la multiplication binaire est nécessaire. La division binaire
est le reflet exact de la division décimale. On utilise une nouvelle fois les mêmes méthodes,
et les mêmes propriétés s'appliquent. Exemple :

C’est sur le modèle de la multiplication que la division s’effectue.

Le signe:

Il existe 4 cas de figures différents pour déterminer le signe de sortie de la


multiplication :

*Signe de sortie positif :

-signe 1 et signe 2 positifs

-signe 1 et signe 2 négatifs

*Signe de sortie négatif :

-signe 1 négatif et signe 2 positif

-signe 1 positif et signe 2 négatif

BOUZID Bruno Junior electronic numeric and RF design engineer 15


THOMSON Grass Valley 2010

La mantisse:

Pour ce calcul, nous avons utilisé pour les deux premiers décalages un morceau de
code et un autre pour traiter la fin. Le principe, hormis les différents compteurs qui facilitent
le fonctionnement, est de mettre un "1" si la valeur que l’on soustrait au nombre divisé est
supérieur ou égale à la valeur du diviseur, puis on décale, sinon, on décale en mettant "0" au
résultat, exactement comme dans l’exemple ci-dessus…

L’exposant:

De manière simple, il existe deux cas de figures :

- Mantisse 1 ≥ Mantisse 2, alors Exposant_out = 127 + (Exposant 1 – Exposant 2)

- Mantisse 1 < Mantisse 2, alors Exposant_out = 126 + (Exposant 1 – Exposant 2)

Sachant que pour nous, Mantisse 1 et Mantisse 2 sont pris en compte avec le "1"
devant la virgule, si le premier coups Mantisse 1 n’est pas assez grand, on est sûr qu’au
deuxième il le sera assez, alors on retire 1 à la valeur "127 + (Exposant 1 – Exposant 2) ".

Exemples :

Si Mantisse 1 < Mantisse 2

BOUZID Bruno Junior electronic numeric and RF design engineer 16


THOMSON Grass Valley 2010

VI) Conversion : Flottant => Entier

Le but de cette dernière, après tous les calculs effectués en flottant, est de convertir
le nombre actuel en entier, pour qu’il soit utilisable par les autres parties du système. Il nous
faut donc effectuer un arrondie, en perdant le moins d’information possible.

L’exposant et la mantisse:

Ici nous définissons le nombre de bits que nous prendrons de la mantisse, exemple :

45127C00 => 2343,7500 (en décimal)

45127C00 => signe "0" => positif, il n’y aura pas besoin de complémenter le résultat à la fin

Exposant "1000 1010" => 127 + 11 = 138, on prendra donc les 11 premiers bits.

Mantisse "1,001 0010 0111 1100 0000 0000"

Ici on prend donc les 11 premiers bits après la virgule plus le "1" virtuel devant la
virgule. Comme le 12ème bit est à "1", nous ajouterons "1" a la valeur transcrite en entier,
pour s’approcher le plus possible de la vrai valeur flottante :

Nombre final = 0000 1001 0010 0111 + 1 = 0000 1001 0010 1000 =>2344 (en décimal)

Le signe:

Si le bit de signe du nombre flottant est à "1", nous complémenterons le résultat final
tel que :

Si nous avions eu C5127C00 => -2343.7500 (en décimal)

BOUZID Bruno Junior electronic numeric and RF design engineer 17


THOMSON Grass Valley 2010

Le résultat final aurait été : le complément de "0000 1001 0010 1000" => " 1111 0110 1101 1000"

A la suite de la conception de ces différents modules, il nous a été possible de les


assembler pour créer des codes capables d’effectuer des opérations complexes en flottant.

Voici un petit rappel des techniques d’opérations en complexe :

Addition: (A + JB) + (C + JD) = (A + C) + [ J × (B + D)]

Soustraction: (A + JB) - (C + JD) = (A + C) - [ J × (B + D)]

Multiplication : (A + JB) × (C + JD) = [(A × C) – (B × D)] + J × [(A × D) + (B × C)]

Division : = =

En annexe voici le code complet.

BOUZID Bruno Junior electronic numeric and RF design engineer 18

Vous aimerez peut-être aussi