Le langage ABEL - HDL (Abel Hardware Description Language)

R. Grisel (IUP GEII Amiens - Richard.Grisel@sc.u-picardie.fr)

Introduction

H.D.L optimisé pour la conception des PLD (CPLD - SPLD)

Introduit par DATA I/O, se compose de parties déclaratives et de parties "exécutables", mais comparé par exemple au C++, le résultat de la compilation d'un "programme" HDL sera une solution "hardware" avec une cible "circuit" et non un programme exécutable.

ABEL permet la spécification d'équations, tables de vérité (truth tables), machines d'états (state diagrams), ou toute combinaison des trois. Il est possible de ne pas scpécifier le circuit ("device") final, voire de ne pas donner d'affectations pour les broches d'entrée/sortie. Le format de sortie des fichiers produits par le compilateur permet l'interfacage avec des produits de CAO électronique (dans notre cas il s'agira des outils Xilinx) ainsi que les standard JEDEC pour les programmateurs de PLD ainsi que les programmateurs de PROM. Dans son expression la plus simple, la description est de type RTL (Register Transfer language) i.e. que l'on définit une sortie par une variation de ses signaux d'entrée. ABEL permet d'écrire des structures indépendanters du choix technologique final, qui sera fait après simulation et optimisation (avec généralement une aide par les outils de CAO).

Structure de base d'un fichier ABEL HDL

Les rectrictions suivantes s'appliquent :

Identificateurs

Caractères ASCII valides:

a - z (alphabet minuscule)

A - Z (alphabet majuscule)

0 - 9 (chiffres)

<espace>

<tabulation>

! @ # $ ? + & * ( )- _ = +

[ { } ] ; : ` " ` ~ \ | , < > . / ^ %

Les règles sont les suivantes :

Mots clés réservés

DECLARATIONS             IF                   STATE_DIAGRAM              
DEVICE                   IN (obs)             TEST_VECTORS               
ELSE                     ISTYPE               THEN                       
ENABLE (obs)             LIBRARY              TITLE                      
END                      MACRO                TRACE                      
ENDCASE                  MODULE               TRUTH_TABLE                
ENDWITH                  NODE                 WHEN                       
FUSES                    OPTIONS              WITH                       
EQUATIONS                PIN                                             
FLAG (obs)               PROPERTY                                        

Constantes

Système de numération : ABEL supporte le binaire (2), l'octal (8), le decimal (10), l'hexadecimal. Le système par défaut est le décimal (10) et il peut être changé par la déclaration @RADIX. Examples :

56	decimal 56

^h56 hexadecimal 56 (valeur décimale 86)

^b1001 binaire 1001 (valeur décimale 9)

^o56 octal 56 (valeur décimale 46)

^h0E hexadecimal 0E (valeur décimale 14)

Valeurs logiques

Vrai (valeur logique 1) et faux (valeur logique 0) sont représentés comme des nombres entiers 32 bits, vrai = -1 (tous les bits à 1) et faux =0 (tous les bits à 0).

Constantes Spéciales

.C.	Entrée "clockée" (transition bas-haut-bas)

.K. Entrée "clockée"input (transition haut-bas-haut )

.U. Front montant (transition bas-haut )

.D. Front descendant

.F. Entrée ou sortie "flottante"

.P. Pré-charge de registre

.SVn. n = 2 .. 9. Force l'entrée à un "supervoltage" de 2 à 9V.

.X. Etat indifférent

.Z. Etat "tristate"

Chaînes de caractères

Suites de caractères ASCII , avec espaces, encadrés par apostrophes (` `). Les chaînes de caractères sont utilisées dans TITLE, MODULE et OPTIONS, et dans les instructions, broche, noeuds interne (node) et déclaration d'attributs.

`Hello this is a string!'

`Punctuation? is even allowed !!'

`It\'s easy to use ABEL' 
`He\\she can use backslashes in a string'

Operateurs

Constantes, noms de signaux sont utilisés dans les expressions. Les expressions combinent, comparent ou effectuent des opérations sur leurs opérandes pour produire un résultat. Les opérations sont indiquées par des opérateurs.

Il y a quatre types de base d'opérateurs pour ABEL-HDL : logique, arithmétique, relationnel, et affectation.

Opérateurs logiques (Logical Operators) :

! !A NOT: Complément à 1
& A & B AND
# A # B OR
$ A $ B XOR: exclusive OR
!$ A !& B XNOR exclusive NOR

Opérateurs Arithmétiques (Arithmetic Operators) :

 

-      -A      Complément à 2  (négation)          
 -     A - B    Soustraction                         
+     A + B    Addition                            

 

            *      A*B     Multiplication                       
   /      A/B     Division entière non signée  
%      A%B     Reste de la division      
                  <<     A<<B    Décalage de A gauche de B bits               
                 >>     A>>B    Décalage de A droite de B bits              

Opérateurs relationnels (Relational Operators) :

       ==  A == B     Egalité                     
   !=  A != B     Différent                
     <   A <  B     Inférieur                 
    <=  A <= B     Inférieur ou égal        
  >   A >  B     Supérieur              
 >=  A >= B     Supérieur ou égal     

Opérateurs d'affectation (Assignment Operators) :

Une équation affecte la valeur d'une expression à un signal de sortie. Il y a 4 opérateurs d'affectation, 2 pour le combinatoire et 2 pour les sorties à registre. Les affectations combinatoires arrivent sans délai après l'évaluation de l'expression, les affectations de type "registre" sont efectuées au prochain coup d'horloge actif associé au registre.

 =   ON(1)  Affectation combinatoire ou equation détaillée          
  ?=   DC(X)  Affectation combinatoire ou equation détaillée           
    :=   ON(1)  Affectation de sortie de registre                          
  ?:=  DC(X)  Affectationd de registre                                 

Priorité des opérateurs :

possibilité d'utilisation des parenthèses pour changer l'ordre d'évaluation, pour la même priorité l'évaluation se fait de gauche à droite dans l'ordre d'écriture..

  1. - (Négation), ! NOT
  2. & (AND), <<, >> (shift left, shift right), * (multiply), / (unsigned division),% (modulus)
  3. + (add) - (subtract), # (OR), $ (XOR), !$ (XNOR)
  4. ==, != (equal, not equal), < (less than), <= (less than or equal) > (greater than), >= (greater than or equal)

Les Ensembles (Sets)

Un ensemble est une collection de signaux et de constantes, et on peut les référencer avec un seul identificateur. Dans d'autres langages, les "sets" sont appelés des "bus". Les éléments d'un ensemble sont écrits entre crochets ([]) et séparés par des virgules, il speuvent aussi être séparés par l'indicateur d'ordre '..'.

bus_address =[A8, A7, A6, A5, A4, A3, A2, A1, A0]

ou

bus_address =[A8..A0]

Multiplication, division, reste, décalage ne sont pas autorisées sur les ensembles.

!bus_address= [!A8, !A7, ......., !A0]

-bus_adress=!bus_address + 1

bus_address.OE=[A8.OE,.....,A0.OE]

bus_address == BK si égalité de tous les bits

bus_address != BK si au moins un des bits est différent de l'autre

Blocs

Ce sont des sections de texte encadrés par des parenthèses. Ils sont utilisés dans les équations, machines d'états, macros et directives, le texte concerné peut tenir sur une ligne ou sur plusieurs et l'on peut imbriquer un bloc dans un autre bloc.

{ this is a block }

{this is also a block, and it

spans more than one line.}

{ A = B # C;

D = [0, 1] + [l, 0];

}

Commentaires

Un commentaire commence par " et se termine par ".

 "You can use comments to write observation in your program."

Paramètres et paramètres formels

Les paramètres formels n'ont de valeur que dans les macros. Dans les modules ou directives, ils pointent le paramètre sur lequel est appliqué l'opération. Dans le corps d'une macro, avant le paramètre formel, on écrit un point d'interrogation, et ils sont séparés par des espaces.

EXP MACRO (a, b, c, d)

{?a & ?b # ?c & ?d};

`This was the macro declaration'

`The call of the defined macro:'

F = EXP (x, y, z, w);

`The evaluation of the macro will be:'

F= x & y # z & w;

Directives

Les directives donnent des options qui contrôlent le contenu ou le traitement d'un fichier source.

@ALTERNATE (Alternate operator Set)

@ALTERNATE valide les opérateurs altenatifs :

Standard Alternate Description
! / NOT
& * AND
# + OR
$ :+: XOR
!$ :*: XNOR

@STANDARD (Standard operator Set):

@STANDARD repositionne les opérateurs standard ABEL.

@CONST (Constant Declaration) hors de la section de déclaration normale

Syntaxe:

@CONST identifier = expression;

Exemple:

@CONST OK = 1;

@DCSET (Don't Care Set)

@DCSET permet l'optimisation des fonctions partiellement définies (supprime les attributs `dc', `neg' et `pos').

@ONSET neutralise @DCSET.

@IF

@IF inclut ou exclut des sections de code source par rapport à la valeur d'une expression.

Syntaxe:

@IF expression {block}

Exemple:

@IF (A>B) {C = D # E}

@INCLUDE

@INCLUDE inclut un fichier ABEL

Syntaxe : @INCLUDE `file_name.abl`

Exemple:

@INCLUDE `macros.abl`

@INCLUDE `C:\\ABEL\\INCLUDE\\CONVERT.ABL`

@PAGE

@PAGE Saut de page

@RADIX (Default Base Numbering Directive)

@RADIX change la base par défaut.

Syntaxe:

@ RADIX expression

Example:

A = 10;	        `A is 10 (decimally)'

@RADIX 2;

A = 10; ` A vaut 2 (decimal)

@RADIX 10000; `base passe à 16''

A = 10; ` A vaut 16 (decimal)'

@RADIX 0A; `restaure à 10'

A = 10; `A vaut 10 (decimal) de nouveau

@REPEAT

@REPEAT répète un bloc du nombre de fois donné dans l'expression (peut être un entier).

Syntaxe :

@REPEAT expression { block };

ABEL a aussi une multitude d'autres directives listées ci-dessous.

@EXPR	 (Expression Directive)

@IFB (If Blank Directive)

@IFDEF (If Defined Directive)

@IFIDEN (If Identical Directive)

@IFNB (If Not Blank Directive)

@IFNDEF (If Not Defined Directive)

@IFNIDEN (If Not Identical Directive)

Description des éléments d'un fichier ABEL-HDL

Structure du fichier source ABEL HDL

La figure suivante donne un exemple de fichier ABEL.

La description fonctionnelle est définie dans le "module".

Un module comprend les sections suivantes :


Un en-tête (Header)

Une partie Declarations

Une partie Description logique (Equations)

Des vecteurs de test éventuels (Test_Vectors)

Une indication de fin pour le module (End)

Les règles suivantes s'appliquent à la structure du module :

En-tête (MODULE)

 

Déclarations

Généralement cela consiste en :





Description de la logique du circuit (EQUATIONS)

La description est fonctionnelle et/ou structurellle. Tous les éléments utilisés doivent avoir été précédemment déclarés.

Les différents éléments suivants permmettent de faire la description :

Test Vectors (Vecteurs de test)

Ne sont quasiment plus utilisés (On préfère la simulation)

End Statement

Termine le module et va de pair avec l'instruction MODULE.

Header (MODULE)

The MODULE statment defines the beginning of an HDL program and must be paired with END statment that defines the functional description end.

The Header Section can consist of the following elements:

MODULE name (The identifier is the beginning of module statement (required))

OPTIONS (Optional element that can influence the run of the program)

TITLE `string' (Optional element that it is written in the header of JEDEC file)

The order of the identifiers must be the order presented

Remarques

Chaque module doit avoir au moins une section de déclarations. Le "device" est déclaré de la manière suivante :

device_identifier DEVICE real_device; 

Cette déclaration est optionnelle, elle associe un module effectivement avec une cible matérielle (défini par real_device, du type P22V10, P16L8, etc...), Le "device_identifier" doit correspondre à un nom de fichier valide car ce sera celui du fichier JEDEC auquel on éjoutera l'extension .JED. Le ";" est obligatoire.

Exemples:

D1 device `P22V10' ;

module UART; "Xilinx™ XEPLD design"

UART device;

Déclarations des Signaux

Il y a plusieurs types de déclaration :

ATTRIBUTE
CONSTANT
LIBRARY
MACRO
NODE
PIN

PIN et NODE permettent de déclarer les signaux du module, et optionnellement d'associer les numéros de broche du circuit. Cette étape peut être faite en dernier lors du "mapping" final sur une architecture. Les attributs sont affectés au signaux (PIN/NODE) par l'intermédiaire de la déclaration ISTYPE. Les extensions (.NOM_EXTENSION) permettent de décrire plus précisément les signaux.

Declarations des "Pin" et "Node"

[!] pin_id [,[!] pin_id. . .] PIN (pin# [, pin#]] [ISTYPE `
attributes']

[!] node_id [[!] node_id. .] NODE [node# [, node#]] [ISTYPE `attributes']

avec pin# et node# numéros de broche du circuit, et
attributes une chaîne de caractères qui spécifie des attributs pour les circuits avec possibilité de programmation
(majoritairement pour les sorties).

Attributs pour les signaux :

signal_name, [signal_name] ISTYPE `attr'

Attributs génériques ou "indépendant de l'architecture" (Architecture Independent)

`com' , Signal combinatoire

`reg' , Elément mémoire, (bascule), peut être combiné avec 'invert' ou 'buffer' pour préciser le type de sortie.

`neg' , Le signal (entrée ou sortie) est inversé (logique négative pour optimisation), affectation à 1 pour logique non attribuée.

`pos' , Le signal (entrée ou sortie) n'est pas inversé (logique positive), affectation à 0 pour logique non attribuée.

Attributs "dépendants de l'architecture" (Architecture dependent)

`buffer' , Pas d'inverseur entre la fonction de sortie (éventuellement Flip-Flop) et la broche de sortie.

`invert' , Un inverseur entre la fonction de sortie (éventuellement Flip-Flop) et la broche de sortie.

`reg_D' , Une bascule D (D-type flip-flop). Implique une description détaillée (voir plus loin), si l'on spécifie 'invert' ou 'buffer', le compilateur transforme l'équation := (et .FB) en expressions avec .D et .Q.

`reg_T', Une bascule bi-stable (T-type flip-flop). Implique une description détaillée (voir plus loin).

`reg_SR' , Bascule SR (SR-type flip-flop). Implique une description détaillée (voir plus loin).

`reg_JK' , Bascule JK (JK-type flip-flop). Implique une description détaillée (voir plus loin).

`reg_G' , élément mémoire(D-type flip-flop avec validation de clock). Implique une description détaillée (voir plus loin).

`xor' , L'architecture cible contient une porte XOR.

ISTYPE permet de définir des attributs lorsque l'on ne spécifie pas de "device" ni de numéro de broche, cependant il est préférable de les spécifier même quand les numéros de broche pour un "device" sont donnés de manière à permettre une lecture claire du fichier.

Déclarations des constantes

Syntaxe :

identifier [, identifier]. .= expression [, expression]. . ;

Une constante correspond à un identificateur qui garde la même valeur dans le module. On fait l'affectation de gauche à droite.

Extensions (suffixe) .EXT :

Les extensions permettent de donner des préisions par rapport au comportement du circuit.

Syntaxe:

signal_name.EXT

Les extensions peuvent être indépendantes de l'architecture ou spécifiques à une architecture. On définit l'utilisation des extensions spécifiques comme correspondant à une syntaxe détaillée (detailed) et les extensions indépendantes comme correspondant à une syntaxe broche-à-broche (pin to pin).

Extensions indépendantes de l'Architecture (Architecture independent):

.CLK Entrée d'Horloge pour bascule

.OE "Output enable"

.PIN "Pin feedback", Retour vers le réseau de la broche (PIN)

.FB "Register feedback", Retour vers le réseau de la sortie du registre

Architecture specific dot extensions:

.D Dans la partie droite d'une équation, .D est le "feedback" combinatoire de l'entrée D de la bascule. Dans la partie gauche d'une équation, c'est l'entrée D de la bascule.

.J Entrée J d'une bascule JK.

.K Entrée K d'une bascule JK.

.R Entrée Rd'une bascule RS.

.S Entrée S d'une bascule RS.

.T Entrée T d'une bascule T.

.Q Sortie de la bascule

.PR Preset du Registre (synchrone ou asynchrone)

.RE Reset du registre (synchrone ou asynchrone)

.ACLR Reset Asynchrone du registre

.ASET Preset Asynchrone du registre

.CLR Reset synchrone du registre

.SET Preset synchrone du registre

.AR Reset Asynchrone du registre

.AP Preset Asynchrone du registre

.SR Reset Synchrone du registre

.SP Preset synchrone du registre

.LE Active bas, validation de latch

.LH Active haut, validation de Latch

.CE Entrée de validation d'horloge

.OE Validation de la sortie (Output Enable)

.COM "Feedback" combinatoire de l'entrée de la bascule, utilisé pour faire la distinction éventuelle entre la broche (.PIN) et le réseau logique interne (.COM).

 

Description en logique Combinatoire

La logique combinatoire peut être décrite avec des équations booléennes,des tables de vérité.
Les instructions suivantes peuvent être utilisées :

[WHEN condition THEN] equation;

[ELSE equation];

Exemple:

EQUATIONS

@ALTERNATE

A = B + C + /D;

ADDR = AB + 5;

WHEN X THEN A =B; ELSE A = C;

Syntaxe des tables de vérité :

TRUTH_TABLE ([input_signals] -> [output_signals])

[input_values] -> [output_values];

[input_values] -> [output_values];

...

Exemple: Décodeur BCD -> 7 segments

-------------------------------------------------------------

"HEX-to-seven-segment decoder
MODULE bcd7seg

Declarations
D3,D2,D1,D0,ENA pin;
A,B,C,D,E,F,G pin istype 'com';
BCD=[D3,D2,D1,D0];
LED=[A,B,C,D,E,F,G];
ON,OFF=0,1;
L,H,X,Z=0,1,.X.,.Z.;


EQUATIONS

LED.OE= !ENA;
truth_table ( BCD -> [G,F,E,D,C,B,A])
0 -> [OFF,ON,ON,ON,ON,ON,ON] ;
1 -> [OFF,OFF,OFF,OFF,ON,ON,OFF];
2 -> [ON,OFF,ON,ON,OFF,ON,ON];
3 -> [ON,OFF,OFF,ON,ON,ON,ON];
4 -> [ON,ON,OFF,OFF,ON,ON,OFF];
5 -> [ON,ON,OFF,ON,ON,OFF,ON];
6 -> [ON,ON,ON,ON,ON,OFF,ON];
7 -> [OFF,OFF,OFF,OFF,ON,ON,ON];
8 -> [ON,ON,ON,ON,ON,ON,ON];
9 -> [ON,ON,OFF,ON,ON,ON,ON];

end;

---------------------------------------------------------------------------------

Description de la Logique Séquentielle

Cette description peut se faire par équations logiques booléennes, diagrammes d'états et tables.

Equations Logiques Booléennes

La syntaxe est la même que pour la logique combinatoire, mais on utilise l'opérateur ":=" à la place de l'opérateur "=". L'expression est affectée après le coup d'horloge actif.

EQUATIONS

Q := (A + B) * /RST;

COUNT := COUNT + 1;

Tables de vérité

La syntaxe est la même, mais on utilise l'opérateur ":>" dans la table.

Syntaxe:

TRUTH_TABLE ([IN_SIGNALS] :> [REG_SIGNALS] -> [OUTPUTS]

[IN_VALUES] :> [REG_VALUES] -> [OUT_VALUES;]

[IN_VALUES] :> [REG_VALUES] -> [OUT_VALUES;]

[IN_VALUES] :> [REG_VALUES] -> [OUT_VALUES;]

[...];

 

Considérations de Conception

Comme nous l'avons dit précédemment, il y a deux types de description pour les éléments à mémoire : "pin to pin" ou "detailed".

Considérons l'équation suivante :

sortie := !sortie # Preset;

Le terme sortie à gauche avec ":=" implique un registre, le terme !sortie à droite correspond à quoi?
- la sortie du registre ?
- la sortie du combinatoire alimentant le registre ?
- la sortie de la broche de sortie (I/O) ?
Il n'y a d'autre part pas d'indication du type de registre. L'écriture suivante :

sortie.CLK = clock;
sortie := !sortie.FB # Preset;

est plus précise. C'est une description dite "PIN TO PIN".

L'écriture en version "detailed" revient à écrire :

sortie.CLK = clock;
sortie.D = !sortie.Q # Preset;
mais il n'y a pas d'information sur la sortie (I/O). On peut donc avoir un focntionnement différent selon que l'on ait un circuit avec sortie inversé (P16R4 par exemple) ou un circuit avec sortie normale. Il est donc préférable de mettre un attribut supplémentaire, l'attribut "buffer" (pas d'inversion entre la sortie de la bascule et la sortie associée) ou son complément "invert" est nécessaire , soit une déclaration :

sortie PIN ISTYPE 'buffer';

Il est intéressant de "visualiser" la "macrocellule" équivalente pour le mode "detrailed" :

Il faut noter sur la figure ci-dessus que l'identificateur BASC.Q n'est pas forcément le même que BASC (notamment si le fusible commande l'inversion en sortie).

Le "PIN to PIN" estv plus comportemental et correspond à la macro-cellule suivante (pas de Reset ou de Preset dans ce cas) :

Récapitulons donc l'écriture de notre module :

En "Pin to Pin" (Module 1):

module pin_to_pin
sortie PIN ISTYPE 'reg';
Clock, Preset PIN;
Equations;
Sortie.clk = Clock;
sortie := !sortie.FB # Preset;

En "detailed" (Module 2) :

module detail
sortie PIN ISTYPE 'reg_D, buffer';
Clock,Preset PIN
Equations;
Sortie.clk = Clock;
Sortie.D = !Sortie.Q # Preset

Le module 1 peut normalement s'implanter dans n'importe quel type de PLD. Le module D ne peut avoir pour cible que les circuits avec bascule D et sortie non-inverseuse. Pour l'implémenter dans un circuit avec sortie inversé, il faut écrire :

(Module 3)

module detail_inv
sortie PIN ISTYPE 'reg_D, invert';
Clock,Preset PIN
Equations;
Sortie.clk = Clock;
!Sortie.D = Sortie.Q # Preset; "(Changement de l'équation à cause du type de sortie)"

Ceci démontre que le mieux est de faire une description "Pin to Pin" pour ne pas avoir à modifier la decsription en fonction du type de cible, par contre on n'a pas de Preset et Reset (asynchrone), et si l'on en met un, on aura une restriction à certains types de circuits. Par exemple :

(Module 4)

module avec_preset
sortie PIN ISTYPE 'reg, buffer';
Clock,Preset PIN
Equations;
Sortie.clk = Clock;
Sortie.AP = Preset;
sortie := !Sortie.FB;

.AP pour le Preset est associé à la bascule interne, donc il ne faut pas que le circuit soit à sortie inverrsée entre la bascule et la broche, d'où la nécessité d'indisuer le "buffer" pour être sur que cela fonctionnera correctement.

Si l'on met un attribut "invert", il faudra que le Preset soit connecté sur le Resset Asynchrone pour avoir effectivement un Preset (voir Module 5) :

 

(Module 5)

module avec_preset_inv
sortie PIN ISTYPE 'reg, invert';
Clock,Preset PIN
Equations;
Sortie.clk = Clock;
Sortie.AR = Preset;
sortie := !Sortie.FB;

Terminons par l'exemple d'un compteur synchrone par 5 (Q2 Q1 Q0) = ( 000 001 010 011 100 ), pour lequel les équations sont :

D0 = /QO AND /Q2; D1 = (QO AND /Q1) OR (/Q0 AND Q1) = Q0 XOR Q1; D2 = Q0 AND Q1;

(Module 7 : Compteur synchrone en description PIN TO PIN)

module csync_pin_to_pin
csync device 'P16R4'
Clock, reset PIN 1,2 ;
Q0, Q1, Q2 PIN 15,16,17 ISTYPE 'reg';
QREG = [Q2,Q1,Q0];
Equations;
QREG.CLK = Clock;
Q0 := (!Q0.FB & !Q2.FB) & !reset;
Q1 := (Q0.FB $ Q1.FB) & !reset;
Q2 := (Q0.FB & Q1.FB) & !reset;
END;

 

(Module 8 : Compteur synchrone en description DETAILED)

module csync_detailed
csyncd device 'P16R4'
Clock, reset PIN 1,2 ;
Q0, Q1, Q2 PIN 15,16,17 ISTYPE 'reg_D,invert';
QREG = [Q2,Q1,Q0];
Equations;
QREG.CLK = Clock;
!Q0.D = (Q0.Q & Q2.Q) & !reset;
!Q1.D = (!Q0.Q $ !Q1.Q) & !reset;
!Q2.D = (!Q0.Q & !Q1.Q) & !reset;
END;