# Very High Speed Integrated Circuit Hardware Description Language/Interfaces RS232 et USB

Ce chapitre risque de rester en construction un certain temps. En effet, à ce jour nous n'avons pas beaucoup d'expérience dans ces domaines. Nous avons un projet avec des étudiants sur l'USB avec un ATMEL ATMEGA8 qui, nous l'espèrons, va nous faire progresser dans le domaine de l'USB. À terme, puisque ce cours comprendra un processeur softcore compatible ATMEGA8, nous espèrons porter ce projet dans un FPGA. Le lecteur impatient peut se retrousser les manches et compléter ce chapitre à sa guise.
Comme d'habitude le préfixe "(en)" devant un hyperlien sera une référence wikipédia en anglais.

## L'interface RS232

Le circuit spécialisé qui gère la liaison série (ou RS232) s’appelle une UART.
On rappelle que ce type de liaison série permet d'envoyer des informations sans horloge de référence. Elle est à un logique au repos. Une trame est composée des 8 bits à transmettre, précédé d'un bit de start ("0" logique), et suivi par au moins un bit de stop ("1" logique). Le bit de stop peut être doublé et éventuellement précédé par un bit de parité. Pour une parité paire, le bit de parité est mis à "0" quand le nombre de "1" est pair tandis qu'une parité impaire met à "0" pour un nombre impair de "1".
La vue de l'image ci-contre semble indiquer le contraire de ce que je suis en train d'expliquer. Mais n'oubliez pas que du point de vue électrique, un niveau logique "0" est représenté par une tension de +3 V à +25 V et un niveau logique "1" par une tension de −3 V à −25 V (codage NRZ). Ordinairement, des niveaux de +12 V et −12 V sont utilisés.

### Utiliser les logicores Xilinx

Dans sa documentation Xilinx n'appelle pas ces programmes VHDL fournis des logicores (cœurs gratuits) mais des macros. La notion de logicore existe cependant chez Xilinx. Par abus de langage j'appellerai ces programmes dans la suite de ce chapitre des logicores !
Si l’on utilise des FPGA Xilinx, il est possible d’utiliser des cœurs fournis par ce fabricant. C'est pratique, mais si vous utilisez un FPGA Altera ou Actel, cela ne fonctionne plus !
Ces logicores sont disponibles chez Xilinx : faites une recherche du fichier KCPSM3.zip qui contient le PicoBlaze et les logicores en question.

#### Generateur de Baud

Dans les deux figures ci-dessous, on voit apparaître un signal "en_16_x_baud". Il nous faut maintenant en discuter.
Tout utilisateur des logicores devra fournir un signal de 16 fois la vitesse de transmission et synchronisé avec l'horloge générale.
Un exemple de programme réalisant cela sera inséré dans la partie exercice un peu plus tard.

#### Transmettre

Nous allons nous intéresser à la transmission de données vers l'extérieur. Pour cela, il faut utiliser le composant décrit par bbfifo_16x8.vhd avec le composant décrit par kcuart_tx.vhd et les assembler pour faire le composant décrit par uart_tx.vhd. Nous ne donnons pas le code de ces composants car ce code est illisible. Un schéma de principe sera bien plus utile.
Prenez le temps de repérer les composants décrits dans le texte.
La version moderne utilise des composants pour lesquels on a rajouté un 9 (par rapport aux anciennes versions) : bbfifo9, kcuart9_tx, kcuart9_rx, uart9_tx et uart9_rx. Ces composants permettent de recevoir et d'émettre un bit de parité.
Un exemple de programme utilisant ces logicores peut être trouvé dans le livre VHDL et conception, particulièrement à partir de la section En aura-t-on fini un jour avec ce compteur de passages ?

#### Recevoir

Nous allons nous intéresser à la réception de données provenant de l'extérieur. Pour cela, il faut utiliser le composant décrit par bbfifo_16x9.vhd avec le composant décrit par kcuart9_rx.vhd et les assembler pour faire le composant décrit par uart9_rx.vhd. Ces fichiers se trouvent dans le répertoire VHDL du fichier KCPSM3.zip qui est téléchargeable chez Xilinx. Ne sachant pas si j’ai le droit d’en donner le contenu ici, je ne préfère pas les publier.
Encore une fois, un schéma de principe sera bien plus utile.
Un exemple de programme utilisant ces logicores peut être trouvé dans le livre VHDL et conception, particulièrement à partir de la section Et un petit dernier séquenceur pour la route...

### Utiliser un cœur indépendant du fondeur

Il n’est pas très difficile de trouver sur Internet (chez Opencores) des cœurs RS232 libres. Il y en a même dans certains projets. Nous donnons par exemple ici ceux que l’on trouve dans le projet ATMega8 présenté dans le chapitre Embarquer un Atmel ATMega8.

#### Composant global

Voici le code source qui sera commenté plus tard.

#### Genérateur de bauds

Voici le code source qui sera commenté plus tard.

#### Reception

Voici le code source qui sera commenté plus tard.

#### Émission

Voici le code source qui sera commenté plus tard.

#### Bibliographie supplémentaire

Pour l'instant nous nous contenterons de dire que vous pouvez trouver de la documentation en anglais dans des livres. Personnellement nous adorons "FPGA Prototyping By VHDL Examples" de Pong P. Chu et nous aimons un peu moins "Design Recipes for FPGA" de Peter Wilson.

## L'interface USB

L'interface USB est simple électriquement (quatre fils seulement) mais complexe du point de vue protocole : on y trouve des concepts réseaux qui ne sont pas forcément maîtrisés par tous les électroniciens. Il faudrait probablement un ouvrage entier pour décrire l'USB : pour rester concis nous allons essentiellement nous intéresser à la classe (en) HID.

### Introduction

Il est inévitable de commencer par quelques définitions.
* On parle d'attachement lorsqu'un périphérique est connecté à un bus USB d'ordinateur. L'ordinateur s'appellera hôte dans ce cas.
* Le protocole qui suit l'attachement s’appelle l'énumération.
* La norme USB définit des types de périphériques appelés classes.
L'énumération se fait en trois étapes :
* attribution d'une adresse au périphérique, comprise entre 1 et 127, par l'hôte (le PC)
* envoi des descripteurs par le périphérique à l'hôte
* configuration du périphérique par l'hôte
Un périphérique quelconque a obligation de s'enregistrer comme appartenant à une certaine classe. Autrement dit, avant de concevoir votre périphérique il vous faut décider à quelle classe il appartient : mémoire de masse, caméra, clavier, souris...
Une classe spécifie, entre autres :
* le taux maximal de transfert
* des commandes spécifiques appelées requêtes de classe
* le nombre de terminaisons (Endpoints en anglais) et pour chacune des terminaisons son nombre de divisions en sections IN et OUT.
Ce qui peut surprendre à ce stade, c’est la notion de terminaison. Elle est liée au fait qu'une adresse de périphérique est insuffisante pour résoudre tous les problèmes de dialogues, et donc on ajoute une division supplémentaire.
Donnons un exemple pour se fixer les idées sur les classes.
La classe HID (Human Interface Device) est la classe des périphériques type claviers et souris. Elle est caractérisée par le fait que l'hôte doit savoir utiliser un tel périphérique sans système d'exploitation. Cette classe impose, entre autres :
* un taux de transfert maximal seulement 6 fois plus rapide que la liaison RS232
* un endpoint portant le numéro 1 en IN
* un transfert de données par appel pour l'endpoint 1 (interrupt transfer)
* le périphérique doit présenter ses données sous forme de rapport (rapport HID input)
Il y a tellement de données dans cette sections qu’il est possible qu'un débutant s'y perde un peu. Prenez éventuellement le temps de lire et relire, mais de toute façon, il est normal qu’à ce point, vous ne compreniez pas tout.

### Les transferts

Les transfert de données représentent les échanges de données sur le bus USB.

#### Les trames

Toutes les millisecondes un paquet nommé SOF (Start of Frame) est envoyé par l'hôte sur le bus. Cette division en entités élémentaires de 1 ms est appelée trame.
Une trame permet l'échange de plusieurs transactions.

#### Transactions

Les transfert de données sont divisés en transactions pour éviter de monopoliser l'hôte.
Si une clé USB est en transfert avec l'hôte, vous vous attendez à ce qu'un mouvement de votre souris USB produise un effet même si le transfert avec l'hôte n’est pas terminé.
Une transaction comporte trois phases distinctes :
* la phase TOKEN qui est toujours initiée par l'hôte. Cette phase spécifie l'adresse du périphérique de destination, le numéro de la terminaison (endpoint) et enfin le sens de l'échange IN ou OUT
* la phase DATA qui correspond à l'envoi de données dont l'expéditeur est soit l'hôte (section OUT), soit le périphérique (section IN)
* la phase HANDSHAKE informe de la réussite ou non de l'échange
Une transaction correspond physiquement à un groupe d'octets que l’on appelle paquet. Tous les paquets ont toujours la même architecture que nous présentons maintenant sans entrer dans les détails.

##### paquet TOKEN

    SyncPIDADDRENDPCRCEOP 8 bits7 bits4 bits5 bits
Parmi les champs de ce paquet, vous voyez le champ PID. On aura l’occasion de donner des valeurs à ce champ lorsqu'on s'intéressera aux transferts (un peu plus loin).

##### paquet DATA

    SyncPIDDataCRCEOP 8 bits0-1 024 octets2 octets
Vous voyez dans ce paquet que la taille des données est limitée. Elle est très largement suffisante pour les périphériques HID classiques : claviers et souris.

##### paquet HANDSHAKE

    SyncPIDEOP 8 bits
C'est la valeur de ce PID qui définira si l'échange s'est correctement passé.
Si les choses se passent mal, une transaction peut être interrompue mais seulement par le périphérique.
Il existe plusieurs sortes d'appels, nous allons commencer par décrire le transfert par appel.

#### Transfert par appel

On appelle transfert par appel (en anglais interrupt transfer), un transfert qui se fait régulièrement à l'initiative de l'hôte.
Chaque appel est une transaction IN qui informe le périphérique que s'il a des données à transmettre, c’est le moment.

##### Exemple de transfert IN par appel

    SyncPIDADDRENDPCRCEOPSyncPIDDataCRCEOPSyncPIDEOP IN7 bits4 bits5 bits→Data00-1 024 octets2 octets→ACK Hôte vers périphériqueRéponse périphérique vers hôtede l'hôte
Je dois avouer que cette façon de représenter les transactions (tableau pour représenter les paquets) n’est pas très conventionnelle. Les flèches dénotent un envoi de trames et le temps s'écoule de la gauche vers la droite. Vous avez donc trois paquets échangés dans l'exemple ci-dessus. Le PID du premier pacquet est IN, celui de la réponse est data0 et et pour terminer l'hôte envoie un ACK au périphérique. Examinons un autre type de transfert par appel :

##### Exemple de transfert OUT par appel

    SyncPIDADDRENDPCRCEOPSyncPIDDataCRCEOPSyncPIDEOP OUT7 bits4 bits5 bits→Data00-1 024 octets2 octets→ACK Hôte vers périphériqueHôte vers périphériquedu périphérique
La classe HID déjà mentionnée attribue à l'endpoint 1 un transfert par appel. Cela veut dire qu'un périphérique HID doit attendre la demande de l'hôte pour envoyer ses données.