------------------------------- 1. Programmation par port JTAG. -------------------------------
La configuration par le port JTAG (boundary scan) est possible quelque soit le mode (M0/M1/M2).
Une application autonome sans processeur nécéssite l'emploi d'une PROM IsP (in system programmable.)
La PROM peut alors être programmée in situ en utilisant les 4 signaux JTAG qui suivent :
TCK : JTAG test clock.
TDI : JTAG serial data input (pull up à 1)
TDO : JTAG serial data output (pull up à 1)
TMS : JTAG mode select input (pull up à 1)
VCC : Alimentation positive.
GND : référence.
Les détails de ce mode de fonctionnement sont largement décrit dans les datasheet Xilinx.
Le logiciel fourni par Xilinx est iMPACT et permet la programmation ainsi que le test des circuits grâce aux vecteurs SFV.
Connection du xilinx et de la PROM.
Le lien qui suit présente un schéma permettant le dialogue entre un PC et le port JTAG.
Les buffers du convertisseur parrallèle vers JTAG sont alimentés par la carte cible (2.5V selon le Xilinx).
Cette tension est renvoyée sur l'entrée d'erreur du port // pour des raisons mystérieuses.
Schéma d'un convertisseur port parallèle PC vers JTAG.
JTAG. (site officiel)
JTAG. (aspect technique)
-------------------------------- 2. Programmation par bus 8 bits. --------------------------------
Le niveau logique des broche est de 3.3V (Le port parallèle fournit du TTL => transistor)
La broche PROGRAM\ doit être mise à '1' avant une nouvelle configuration.
La programmation par bus parallèle est la plus rapide, les données sont envoyées octet
par octet dans le FPGA qui génère un "BUSY flag" pour controller le flux de données.
Si la ligne BUSY est mise à '1' par le FPGA, la donnée doit être maintenue jusqu'à la
mise à zéro de BUSY.
Chaque front montant de CClk permet d'incrémenter le compteur d'adresse interne.(?vérif?)
Il est possible de lire le contenu du FPGA, dans ce cas WRITE\ est positionné à '0'.
Les données sont envoyées avec le MSB de chaque octet sur D0 et le lsb sur D7.
Il est possible de programmer plusieurs composants, CS\ valide celui qui sera la cible.
Quand le circuit est programmé, la broche DONE passe à '1'.
Mécanisme d'écriture (algorithmie):
/*----------------------------------------------------------------*/
WRITE\ = 0 Autorise l'écriture de la mémoire de configuration
CS\ = 0 Valide le circuit
Tant que le fichier n'est pas vide :
| D[7:0] = Data; octet à envoyer sur le port parallèle
| CCLK = 0 génère un front montant
| WAIT attente : c'est une pseudo horloge
| CCLK = 1 pour la prise en compte de la donnée
|
| if (BUSY==0) la donnée est accépté
| octet++ continuer le traitement
| sinon la donnée sera accepté au premier front montant
| wait de CCLK après passage à 0 de BUSY
| fin si
Fin tant que
si (DONE=1) programmation correcte
WRITE\ = 1 Fin d'écriture possible
CS\ = 1 Le circuit n'est plus valide
/*----------------------------------------------------------------*/
En fait, si l'horloge CCLK est suffisemment lente, BUSY n'influencera pas la séquence de programation, les problèmes se poseront quand il faudra optimiser la vitesse de programmation. (mais comme t'as le temps, gamin, tu t'fais pas) Donc la boucle d'attente "si BUSY==0" est supperflue ; les données seront programmées à chaque front montant de CCLK.
Chronnogrammes :
__ __ __ __ __ __ __ CCLK |__| |__| |__| |__| |__| |__| |__ ___ ___ CS\ |_________________________________| __ __ WRITE\ |___________________________________| ____ ________________ ________________ ___ D[0:7] ____X________________X________________X___ _____ BUSY ______________________| |_______________ D0 à D7 : Setup de 5 ns(1) Hold de 1.7 ns(2) CS\ : Setup de 7 ns(3) Hold de 1.7 ns(4) WRITE\ : Setup de 7 ns(5) Hold de 1.7 ns(6) BUSY : 12ns(7) CCLK : 50MHz au maximum
Employons le port parallèle du PC pour programmer le composant.
Prérequis : Le port parallèle :
HOW TO
Adresse de base du port parallèle : 378H-37BH = 11 0111 10XX
Le port LPT1 est situé à l'adresse 378, le port LPT2 à l'adresse 278.
Soit 888 thru 891 decimal, avec 891 non utilisé.
Le port BASE (port de donnée) permet l'envoie d'un octet.
Le port BASE+1 (port d'état) est en lecture seule et retourne l'état des signaux d'entrée suivants :
Bits 0 et 1 sont réservés.
Bit 2 état d'IRQ
Bit 3 ERROR (1 = état haut)
Bit 4 SLCT (1 = état haut)
Bit 5 PE (1 = état haut)
Bit 6 ACK (1 = état haut)
Bit 7 -BUSY (0 = état haut)
Le port BASE+2 (port de contrôle) est en écriture seule :
Bit 0 -STROBE (0 = état haut)
Bit 1 -AUTO_FD_XT (0 = état haut)
Bit 2 INIT (1 = état haut)
Bit 3 -SLCT_IN (0 = état haut)
Bit 4 active la requête d'interruption (IRQ) du port parallèle
Bit 5 contrôle la direction du mode étendu (0 = écriture, 1 = lecture)
Bits 6 et 7 sont réservés.
Brochage DB25 (SPP signal):
<= in DB25 Name of Reg => out pin Signal Bit Function Notes ------ ---- -------- --- ----------------------------- => (e/s) 1 -Strobe C0- Set Low pulse >0.5 us to send => (e/s) 2 Data 0 D0 Set to least significant data => (e/s) 3 Data 1 D1 ... => (e/s) 4 Data 2 D2 ... => (e/s) 5 Data 3 D3 ... => (e/s) 6 Data 4 D4 ... => (e/s) 7 Data 5 D5 ... => (e/s) 8 Data 6 D6 ... => (e/s) 9 Data 7 D7 Set to most significant data <= (e) 10 -Ack S6+ IRQ Low Pulse ~ 5 uS, after accept <= (e) 11 +Busy S7- High for Busy/Offline/Error <= (e) 12 +PaperEnd S5+ High for out of paper <= (e) 13 +SelectIn S4+ High for printer selected => (s) 14 -AutoFd C1- Set Low to autofeed one line <= (e) 15 -Error S3+ Low for Error/Offline/PaperEnd => (s) 16 -Init C2+ Set Low pulse > 50uS to init => (s) 17 -Select C3- Set Low to select printer == 18-25 GroundRoutine en c pour écrire sur le port parallèle :
/* * exemple.c : un exemple très simple d'accès aux ports d'E/S * * Ce programme ne fait rien d'utile, juste une écriture sur le port, * une pause, puis une lecture sur le même port. * À compiler avec « gcc -O2 -o exemple exemple.c »et à * exécuter en tant que root avec « ./exemple ». */ #include#include #include #define BASEPORT 0x378 /* lp1 */ int main() { /* Obtention de l'accès aux ports */ if (ioperm(BASEPORT, 3, 1)) {perror("ioperm"); exit(1);} /* Initialisation de tous les signaux de données (D0-D7) à l'état bas (0) */ outb(0, BASEPORT); /* Dormons pendant un moment (100 ms) */ usleep(100000); /* Lecture sur le port d'état (BASE+1) et affichage du résultat */ printf("status : %d\n", inb(BASEPORT + 1)); /* Nous n'avons plus besoin de l'accès aux ports */ if (ioperm(BASEPORT, 3, 0)) {perror("ioperm"); exit(1);} exit(0); } /* fin d'exemple.c */