LE LANGAGE VHDL POUR
L’ARITHMETIQUE
Lilian Bossuet – 2010
1. Introduction
Lorsqu’il s’agit de décrire en VHDL un circuit dans lequel des opérations arithmétiques doivent être réalisées il est nécessaire d’appliquer une description particulière.
Effectivement, les circuits électroniques disposent d’entrées sorties qui sont des fils, ou en VHDL des signaux de types std_logic (ou std_ulogic
1), ce sont donc des entités physiques qui n’ont pas directement de valeur arithmétique. Cependant ces signaux, en fonction de leur état, peuvent représenter, lorsqu’ils sont groupés, des valeurs numériques qu’un traitement arithmétique peut utiliser. Pour ce faire il est nécessaire de traduire, ou interpréter, les signaux (std_logic_vector) en nombres signés (signed) ou non signés (unsigned). Dans ce document on appellera les types signed et unsigned les types arithmétiques .
Les nombres signés sont des nombres positifs ou négatifs. Lors de la conversion d’un signal en nombre signé, le MSB du signal est interprété comme un bit de signe. Le MSB à l’état haut signifie que le nombre doit être interprété comme un nombre négatif, le MSB à l’état bas signifie que le nombre doit être interprété comme un nombre positif.
2. Les types utilisés pour décrire un circuit arithmétique
Pour les entrées sorties :
TYPE std_logic IS (‘U’, ‘X’, ‘0’, ‘1’, ‘Z’, ‘W’, ‘H’, ‘L’, ‘-‘) ;
Une variable ou un signal de ce type pourra donc prendre une des neuf valeurs spécifiées, celles- ci se rapprochent des valeurs possibles physiquement pour un signal électrique dans le cas limité de l’électronique numérique. La description des neuf valeurs est la suivante :
U : non initialisé X : inconnue fort 0 : état bas fort 1 : état haut fort Z : haute impédance W : inconnue faible
1
Std_logic est un sous type de std_ulogic, il dispose en plus de fonction de résolutions nécessaires lorsqu’il
s’agit de décrire des signaux sur des bus.
H : état haut faible L : état bas faible - : quelconque
Ces différentes valeurs permettent au simulateur de faire les calculs et de détecter les éventuelles erreurs de conception, comme par exemple l’absence d’initialisation des signaux par un RESET (signal de mise à l’état haut ou bas).
Pour utiliser le type std_logic (que l’on utilise systématiquement pour représenter des signaux électrique), il faut placer au début de la description VHDL la déclaration de librairie suivante :
LIBRARY IEEE
USE ieee.std_logic_1164.all;
Grace à cette librairie, le type std_logic et les principales opérations le concernant sont déjà décrites.
Pour les nombres internes non signés (appelés aussi SIGNAL en VHDL) ou les valeurs intermédiaires non signées (VARIABLE) :
TYPE UNSIGNED is ARRAY (NATURAL RANGE <>) OF std_logic;
Pour les nombres internes signés (appelés aussi SIGNAL en VHDL) ou les valeurs intermédiaires signées (VARIABLE) :
TYPE SIGNED is ARRAY (NATURAL RANGE <>) OF std_logic;
Remarque : Comme on le voit, physiquement un signal UNISGNED ou SIGNED c’est la même chose, c'est-à-dire un vecteur de N std_logic.
Dans le cas d’un UNSIGNED sur N bits la valeur du signal sera comprise dans l’intervalle suivant :
1 2 _
0 valeur nombre
N
Dans le cas d’un SIGNED sur N bits la valeur du signal sera comprise dans l’intervalle suivant : 1
2 _
2
1
1
Nvaleur nombre
NExemple : si N = 8
127 _
_ 128
255 _
_ 0
signed nombre
valeur
unsigned nombre
valeur
Pour utiliser les types unsigned et signed (que l’on utilise systématiquement pour représenter des nombres qui sont physiquement des fils), il faut placer au début de la description VHDL la déclaration de librairie suivante :
LIBRARY IEEE -- si elle n’y est pas déjà USE ieee.numeric_std.all;
Remarque : au niveau de l’architecture d’un circuit, il est tout à fait envisageable, pour la flexibilité d’un calcul, d’utiliser d’autres types comme les types INTEGER et NATURAL (sous-type d’INTEGER se limitant aux nombres positifs).
3. La librairie IEEE.NUMERIC_STD.ALL, conversion de type et opérations avec les types arithmétiques
La librairie IEEE.NUMERIC_STD.ALL définie les types UNSIGNED et SIGNED (c'est-à-dire comme des vecteurs de std_logic, elle utilise donc la librairie ieee.std_logic_1164.all).
Elle définie des fonctions de conversion de type pour ces deux types :
TO_INTEGER (UNSIGNED) -- conversion UNSIGNED => INTEGER TO_INTEGER (SIGNED) -- conversion SIGNED => INTEGER
TO_UNSIGNED (INTEGER, N) -- conversion INTEGER => UNSIGNED sur N bits TO_SIGNED (INTEGER, N) -- conversion INTEGER => SIGNED sur N bits
Il n’existe pas de fonctions de conversion des types UNSIGED et SIGNED avec le type STD_LOGIC_VECTOR, puisqu’il s’agit uniquement d’une interprétation. Pour affecter à un signal du type std_logic une valeur avec les types arithmétiques, ou le contraire il faut utiliser les conversions directes (interprétations) suivantes (attention dans tous les cas la taille des signaux en nombre de bits doit être la même) :
V_S <= SIGNED(A) -- interprétation d’un signal A std_logic_vector en un signal V_S SIGNED
V_US <= UNSIGNED(A) -- interprétation d’un signal A std_logic_vector en un signal V_US USIGNED
A <= STD_LOGIC_VECTOR(V_S) -- interprétation d’un signal V_S SIGNED en std_logic_vector A <= STD_LOGIC_VECTOR(V_US) -- interprétation d’un signal V_US UNSIGNED en std_logic_vector
Remarque : au passage on notera que pour effectuer une conversion de type de std_logic_vector en integer il est assez efficace de passer par le type SIGNED (UNSIGNED si il s’agit de Natural) sans être obligé de passer par la librairie ieee.std_logic_arith.all, de la façon suivante :
V_INTEGER <= TO_INTEGER(SIGNED(A)) -- conversion d’un signal A std_logic_vector en un signal V_INTEGER de type INTEGER
V_NATURAL <= TO_INTEGER(UNSIGNED(A)) -- conversion d’un signal A std_logic_vector en un signal V_NATURAL de type NATURAL
A <= STD_LOGIC_VECTOR(TO_SIGNED(V_INTEGER,N)) -- conversion d’un signal V_INTEGER en un signal A std_logic_vector sur N bits
A <= STD_LOGIC_VECTOR(TO_UNSIGNED(V_NATURAL,N)) -- conversion d’un signal V_NATURAL en un signal A std_logic_vector sur N bits
La librairie IEEE.NUMERIC_STD.ALL définie pour les types UNSIGNED et SIGNED les fonctions suivantes :
abs, +, –, *, /, rem, mod, >, <, <=, >=, =, /=, shift_left, sift_right, rotate_right, rotate_left, sll, srl, rol, ror, to_integer, to_signed, to_unsigned, not, and, or, nand, nor, xor, xnor.
Dans la partie 4, un extrait de cette librairie avec la définition de ces fonctions est donnée.
4. Extrait de la librairie IEEE.NUMERIC_STD.ALL
package NUMERIC_STD is
constant CopyRightNotice: STRING
:= "Copyright 1995 IEEE. All rights reserved.";
attribute builtin_subprogram: string;
--============================================================================
-- Numeric array type definitions
--============================================================================
type UNSIGNED is array (NATURAL range <>) of STD_LOGIC;
type SIGNED is array (NATURAL range <>) of STD_LOGIC;
--============================================================================
-- Arithmetic Operators:
--===========================================================================
function "abs" (ARG: SIGNED) return SIGNED;
function "-" (ARG: SIGNED) return SIGNED;
function "+" (L, R: UNSIGNED) return UNSIGNED;
function "+" (L, R: SIGNED) return SIGNED;
function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED;
function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED;
function "+" (L: INTEGER; R: SIGNED) return SIGNED;
function "+" (L: SIGNED; R: INTEGER) return SIGNED;
function "-" (L, R: UNSIGNED) return UNSIGNED;
function "-" (L, R: SIGNED) return SIGNED;
function "-" (L: UNSIGNED;R: NATURAL) return UNSIGNED;
function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED;
function "-" (L: SIGNED; R: INTEGER) return SIGNED;
function "-" (L: INTEGER; R: SIGNED) return SIGNED;
function "*" (L, R: UNSIGNED) return UNSIGNED;
function "*" (L, R: SIGNED) return SIGNED;
function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED;
function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED;
function "*" (L: SIGNED; R: INTEGER) return SIGNED;
function "*" (L: INTEGER; R: SIGNED) return SIGNED;
--============================================================================
-- Comparison Operators
--============================================================================
function ">" (L, R: UNSIGNED) return BOOLEAN;
function ">" (L, R: SIGNED) return BOOLEAN;
function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN;
function ">" (L: INTEGER; R: SIGNED) return BOOLEAN;
function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN;
function ">" (L: SIGNED; R: INTEGER) return BOOLEAN;
function "<" (L, R: UNSIGNED) return BOOLEAN;
function "<" (L, R: SIGNED) return BOOLEAN;
function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN;
function "<" (L: INTEGER; R: SIGNED) return BOOLEAN;
function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN;
function "<" (L: SIGNED; R: INTEGER) return BOOLEAN;
function "<=" (L, R: UNSIGNED) return BOOLEAN;
function "<=" (L, R: SIGNED) return BOOLEAN;
function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN;
function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN;
function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN;
function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN;
function ">=" (L, R: UNSIGNED) return BOOLEAN;
function ">=" (L, R: SIGNED) return BOOLEAN;
function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN;
function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN;
function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN;
function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN;
function "=" (L, R: UNSIGNED) return BOOLEAN;
function "=" (L, R: SIGNED) return BOOLEAN;
function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN;
function "=" (L: INTEGER; R: SIGNED) return BOOLEAN;
function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN;
function "=" (L: SIGNED; R: INTEGER) return BOOLEAN;
function "/=" (L, R: UNSIGNED) return BOOLEAN;
function "/=" (L, R: SIGNED) return BOOLEAN;
function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN;
function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN;
function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN;
function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN;
--============================================================================
-- Shift and Rotate Functions
--============================================================================
function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED;
function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED;
function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED;
function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED;
function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED;
function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED;
function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED;
function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED;
function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED;
function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED;
function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED;
function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED;
function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED;
function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED;
function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED;
function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED;
function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED;
function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED;
--============================================================================
-- Conversion Functions
--============================================================================
function TO_INTEGER (ARG: UNSIGNED) return NATURAL;
function TO_INTEGER (ARG: SIGNED) return INTEGER;
function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED;
function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED;
--============================================================================
-- Logical Operators
--============================================================================
function "not" (L: UNSIGNED) return UNSIGNED;
function "and" (L, R: UNSIGNED) return UNSIGNED;
function "or" (L, R: UNSIGNED) return UNSIGNED;
function "nand" (L, R: UNSIGNED) return UNSIGNED;
function "nor" (L, R: UNSIGNED) return UNSIGNED;
function "xor" (L, R: UNSIGNED) return UNSIGNED;
function "xnor" (L, R: UNSIGNED) return UNSIGNED;
function "not" (L: SIGNED) return SIGNED;
function "and" (L, R: SIGNED) return SIGNED;
function "or" (L, R: SIGNED) return SIGNED;
function "nand" (L, R: SIGNED) return SIGNED;
function "nor" (L, R: SIGNED) return SIGNED;
function "xor" (L, R: SIGNED) return SIGNED;