Aller au contenu

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

Leçons de niveau 15
Une page de Wikiversité, la communauté pédagogique libre.
Début de la boite de navigation du chapitre
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « Very High Speed Integrated Circuit Hardware Description Language : Interfaces RS232 et USB
Very High Speed Integrated Circuit Hardware Description Language/Interfaces RS232 et USB
 », n'a pu être restituée correctement ci-dessus.

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.


L'interface RS232

[modifier | modifier le wikicode]

Le circuit spécialisé qui gère la liaison série (ou RS232) s’appelle une UART.

Trame RS232

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

[modifier | modifier le wikicode]

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

[modifier | modifier le wikicode]

Dans les deux figures ci-dessous, on voit apparaître un signal "en_16_x_baud". Il nous faut maintenant en discuter.

Un exemple de programme réalisant cela sera inséré dans la partie exercice un peu plus tard.

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.

Comment transmettre des données avec des logicores Xilinx

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 ?

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.

Comment recevoir des données avec des logicores Xilinx

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

[modifier | modifier le wikicode]

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

[modifier | modifier le wikicode]

Voici le code source qui sera commenté plus tard.

Genérateur de bauds

[modifier | modifier le wikicode]

Voici le code source qui sera commenté plus tard.

Voici le code source qui sera commenté plus tard.

Voici le code source qui sera commenté plus tard.

Bibliographie supplémentaire

[modifier | modifier le wikicode]

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

[modifier | modifier le wikicode]

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.

Il est inévitable de commencer par quelques définitions.

L'énumération se fait en trois étapes :

  1. attribution d'une adresse au périphérique, comprise entre 1 et 127, par l'hôte (le PC)
  2. envoi des descripteurs par le périphérique à l'hôte
  3. 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...

Notion de terminaison ou endpoint

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.

Début de l'exemple
Fin de l'exemple

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

[modifier | modifier le wikicode]

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

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.

Les transfert de données sont divisés en transactions pour éviter de monopoliser l'hôte.

Début de l'exemple
Fin de l'exemple

Une transaction comporte trois phases distinctes :

  1. 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
  2. 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)
  3. 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
Sync PID ADDR ENDP CRC EOP
8 bits 7 bits 4 bits 5 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
Sync PID Data CRC EOP
8 bits 0-1 024 octets 2 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
Sync PID EOP
8 bits

C'est la valeur de ce PID qui définira si l'échange s'est correctement passé.


Il existe plusieurs sortes d'appels, nous allons commencer par décrire le transfert par appel.

Transfert par appel

[modifier | modifier le wikicode]

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
Sync PID ADDR ENDP CRC EOP Sync PID Data CRC EOP Sync PID EOP
IN 7 bits 4 bits 5 bits Data0 0-1 024 octets 2 octets ACK
Hôte vers périphérique Réponse périphérique vers hôte de 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
Sync PID ADDR ENDP CRC EOP Sync PID Data CRC EOP Sync PID EOP
OUT 7 bits 4 bits 5 bits Data0 0-1 024 octets 2 octets ACK
Hôte vers périphérique Hôte vers périphérique du périphérique

Les descripteurs

[modifier | modifier le wikicode]