Blog VHDL33 de Patrice Nouel

Mon ancien collègue et compère Patrice Nouel m'a demandé de sauvegarder les billets de son blog vhdl33 qu'il ne maintient plus. Voici donc quelques billets intéressants reproduits ci-après :,

 

Test de la fonction modulo « MOD » 04/04/11

Lorsqu’elle s’applique à des nombres entiers positifs, la fonction « modulo » est simple à comprendre. Il s’agit du reste de la division d’un dividende par un diviseur, de telle sorte qu’on puisse écrire:

Modulo = dividende – partie entière de (dividende / diviseur), avec dans ce cas modulo <  diviseur

voir à ce sujet: modulo (informatique) wikipedia

En écriture VHDL, on dispose de cette fonction de multiples fois en surcharge dans les bibliothèques telles que ieee.numeric_std et la syntaxe est par exemple :

Modulo <= dividende MOD quotient;

Avec des types non signés ou natural, on va ainsi constater que : 200 Mod 200 retourne 0, mais que 210 MOD 200 retourne 10.

Le cas des nombres entiers signés est plus délicate et il est bon de faire un petit programme de test afin de se faire une idée de la façon dont est calculé le modulo.

Le fichie test_modulo.vhd permet de mieux cerner le fonctionnement du modulo.

On y constate, en particulier que le modulo VHDL  est toujours du même signe que le diviseur

ainsi :  2444 MOD 200 retourne 44 mais 2444 MOD -200 reourne -44.

La fonction MOD n’est pas reconnue synthétisable telle quelle sauf si le quotient est une puissance de 2 car cette opération revient à un décalage de bits. Ainsi dividende MOD 128 est synthétisable.  L’opération équivalente étant de ne garder que les 7 bits de poids faible de dividende. Ainsi 232 MOD 128 = 232 -128 = 104, opération qui ne coute rien en termes de ressource lors de la synthèse.

Une fonction Modulo synthétisable 08/04/11

Comme il a été expliqué dans l’article précédent, la fonction VHDL « MOD » correspondant au calcul du modulo n’est pas reconnue comme synthètisable dans les outils courants comme ISE. Il est donc nécessaire de créer une telle fonction à partir d’autres fonctions qui le sont. Nous avons choisi la multiplication qui est parfaitement réalisée par un bloc DSP.

On limite le problème à des nombres non signés. Le diviseur est en principe une constante de N2 bits, le dividende un nombre de N1 bits. On cherche le modulo par la relation:

dividende = quotient * diviseur + modulo

ou modulo = dividende – partie_entiere (dividende /diviseur)

On procède par dichotomie sur le quotient. On propose une succéssion de quotients jusqu’à ce que dividende – quotient * diviseur soit inférieur à diviseur. La différence est alors le modulo cherché.

Avec cette méthode, le temps de calcul en nombre de cycles est en général de N1 – N2 + 1 . Il tombe à 1 cycle si le dividende = 0, et est inférieur si le quotient est apparu plus tôt dans la séquence. Afin de réduire ce temps de cycle, on prendra bien soin d’ajuster N1 au minimum requis, pour N2 (le diviseur) on doit impérativement avoir un ’1′ en MSB afin de n’avoir que des bits « utiles.

Le fichier source et son fichier test apportent toutes les précisions nécessaires.

A titre d’exemple , voici un extrait du rapport de synthèse sur une cible Virtex.

Cell Usage :
     # BELS                                  : 325
     #      GND                              : 1
     #      INV                              : 4
     #      LUT2                             : 37
     #      LUT3                             : 27
     #      LUT4                             : 34
     #      LUT5                             : 55
     #      LUT6                             : 23
     #      MUXCY                            : 84
     #      VCC                              : 1
     #      XORCY                            : 59
     # FlipFlops/Latches                     : 59
     #      FD                               : 23
     #      FDR                              : 35
     #      FDRS                             : 1
     # Clock Buffers                         : 1
     #      BUFGP                            : 1
     # IO Buffers                            : 42
     #      IBUF                             : 33
     #      OBUF                             : 9
     # DSPs                                  : 1
     #      DSP48E                           : 1
     ============================================

Commentaire sur le VHDL

Pour le choix du diviseur rentrant dans le calcul du modulo, nous l’avons voulu constant et avons donc déclaré une constante générique:

GENERIC(  N1  : natural := 24;           — Nombres de bits  dividende

divisor  : unsigned(7 DOWNTO 0) :=x »C8″ );    — 200 et MSB = ’1′

On veut absolument  que le MSB soit 1 ce qui fait dépendre le nombre de bits de la valeur de la constante. On voit très bien que cette écriture n’est pas satisfaisante car la constante ne pourra être modifiée que dans la gamme 128 à 255 puisqu’au delà il faut changer le nombre de bits du diviseur et donc modifier la spécification d’entité.

Une solution alternative serait de définir une constante générique N2 , nombre de bits du diviseur et du modulo et de définir un port d’entree

divisor: unsigned(N2-1 DOWNTO 0), mais alors il faudra de l’extérieur assurer que la valeur d’entrée a bien un MSB = ’1′. On a juste repoussé le problème.