Vous êtes sur la page 1sur 18

E cole Polytechnique de Tunisie

E cole Polytechnique de Tunisie Mini pro jet à base de microprocesseu rs Trai tement d’images

Mini pro jet à base de microprocesseu rs

Trai tement d’images sur FPGA

Rapport élaboré par :

23 juin 2008

BOUSSETTA Hichem

FEHRI Bilel Elèves 2 ème année (Option SISY)

Année universitaire 2007/2008

Introduction

Le but de ce projet est d’exploiter le FPGA Spartan 3 de Xilinx pour faire des applications basiques d’entrée sortie (module UART) pour passer par la suite à des architectures relativement complexes rassemblant plusieurs composants qu’il faut synchroniser et gérer l’accès à la mémoire.

I.

Architectures

Dans cette partie, nous allons présenter et décrire les architectures des unités que nous avons conçues et expliquer les démarches que nous avons adoptées pour y parvenir.

1. Module UART (Universal Asynchronous Receiver Transmitter)

Ce module a pour fonction de recevoir et de transmettre des données à travers un port série. Il est constitué de deux unités : une unité de réception qui détecte l’arrivée des données sur un support de transmission en série et les transforme en données parallèles, et une unité d’émission qui sérialise les données parallèles.

Avant d’expliquer l’architecture de chacune de ces deux unités, il est nécessaire de décrire le protocole série. En fait, il existe plusieurs normes pour la transmission série, chacune ayant ses spécificités. Dans notre projet, on se restreindra au cas le plus simple, où l’on transmet 8 bits avec un bit de stop (égal à 1) et sans contrôle de parité dénommé 8N1. La figure ci-dessous représente une transmission série en mode 8N1. La ligne est toujours à l’état 1. Pour signaler l’arrivée d’un nouvel octet, on transmet d’abord un bit de start égal à 0 pour servir de repère. Par la suite, la lecture des autres bits se fait à une certaine cadence fixée à l’avance par le récepteur et l’émetteur. L’inverse de la période qui sépare deux bits consécutifs est appelé Baud Rate. C’est la fréquence à laquelle les bits sont transmis.

1

Trame série Bit de start 8 bits Bit de stop
Trame série
Bit de start
8 bits
Bit de stop

Fig1 : Schéma d’une trame série en mode 8N1

Donc, la réalisation d’un module UART consiste à traquer une trame série et à en dégager les bits de données tout en respectant la vitesse de transmission.

1.1- Unité d’émission série

Cette unité reçoit des données parallèles (en provenance d’une mémoire par exemple), et elle est chargée de les transmettre en série un à un selon un débit fixé de 9600 bauds soit 9600 bits/s. Cette entité aura, donc, besoin d’un registre de décalage pour extraire successivement les bits d’un mot. Ce registre doit être cadencé par une horloge de fréquence égale au baud rate. Il devient, ainsi,

de fréquence égale au baud rate. Il devient, ainsi, nécessaire d’introduire des compteurs pour chronométrer

nécessaire d’introduire des compteurs pour chronométrer les moments des décalages, c'est-à-dire ceux de l’émissions des données sur la liaison série. Le tout doit être géré par une entité de contrôle qui selon l’état de l’unité d’émission commande les différents organes. L’unité d’émission peut être, donc, décrite par le schéma-bloc suivant :

Fig2 : Schéma-bloc de l’unité de réception

Cette unité est cadencée par une horloge (clk). Elle décale les données parallèles en entrée et émet les bits à une fréquence égale au débit de transmission. Le signal « Go » donne le signal de départ à l’unité pour l’envoi des données. L’unité de contrôle control_sm détient les informations sur l’état de l’unité et décide des traitements qu’elle va effectuer. L’entité compteurs rassemble les compteurs dont on a besoin pour chronométrer le fonctionnement de l’unité. Certains sont utilisés pour faire le décompte le nombre de cycles d’horloge qu’il faut pour conditionner l’envoi des données à une période bien déterminée et compter le nombre de bits à transmettre.

1.2- Unité de réception

Le rôle de cette unité est de déceler l’arrivée d’une trame transmise sur un support série et d’y extraire les 8 bits recherchés. Cette unité ressemble à l’unité d’émission et comporte elle, aussi, une entité de contrôle qui détecte le bit de start pour déclencher le processus de mise en parallèle des données. L’entité de contrôle synchronise le fonctionnement des autres composants à savoir le registre de décalage et les compteurs. L’octet obtenu est stocké dans un buffer jusqu’à ce qu’il soit lu par d’autres composants.

Le schéma-bloc décrivant cette unité est donné dans la figure ci-contre.

schéma-bloc décrivant cette unité est donné dans la figure ci-contre. Fig3 : Schéma-bloc de l’unité de

Fig3 : Schéma-bloc de l’unité de réception

On note l’utilisation de signaux de notification pour rendre compte de la disponibilité des données.

2. Module affichage sur un écran VGA

Il existe plusieurs modes pour la norme VGA, et nous allons utiliser celle dont la définition de l’image est de 640×480 fonctionnant à 60 Hz et dont les canaux de rouge, vert et bleu sont codés chacun sur un bit, ce qui définit 8 couleurs possibles. Le protocole VGA consiste à utiliser deux signaux de synchronisation horizontale HS et verticale VS et 3 signaux pour définir la couleur d’un pixel. Pour une fréquence de rafraîchissement de l’écran de 60 Hz, l’information de la couleur doit parvenir à tous les pixels de l’écran à une fréquence de 25 MHz (soit à une période de 40 ns). Le module d’affichage VGA lit une image à partir d’une mémoire et l’affiche sur un écran. Les contraintes à prendre en compte sont les contraintes de temps d’accès aux données des pixels et leur transmission sur un câble VGA dans les délais requis. D’autres difficultés se présentent aussi, surtout lorsque l’image en question stockée dans la mémoire est lue à partir d’un PC à travers un câble série. Dans ce cas, il faut gérer et organiser l’accès en lecture et en écriture à la mémoire par les différentes unités. Le module d’affichage VGA comporte les composants suivants :

Une unité de réception série (décrite dans les paragraphes précédents).

Un contrôleur d’écriture dans la mémoire : cette entité est chargée de la sauvegarde en mémoire des données reçues en série. Elle comprend, donc, un compteur pour effectuer un accès séquentiel à la mémoire. Une unité de contrôle qui gère le fonctionnement interne de l’unité et les signaux de contrôle de la mémoire. Cette unité est aussi pourvue d’une entité de calcul d’adresse qui peut servir pour des applications plus étendues comme par exemple segmenter la mémoire en plusieurs blocs pour y stocker plusieurs images, et afficher une animation en fonction de ces images. La segmentation de la mémoire simplifie, dans ce cas, l’accès à cette dernière sur une base et un index.

Une unité d’affichage VGA qui comme décrite précédemment émet les signaux de synchronisation et des couleurs sur la sortie VGA.

Un contrôleur de lecture à partir de la mémoire qui gère l’accès de l’unité d’affichage à la mémoire en lui faisant parvenir les informations sur la couleur d’un pixel.

Des multiplexeurs pour les fils d’adresse et de données correspondant aux unités de réception et d’affichage VGA. Ces multiplexeurs garantissent l’unicité de l’entité accédant à la mémoire.

Fig4 : Schéma-bloc du module d’affichage VGA La figure qui suit montre en détail la

Fig4 : Schéma-bloc du module d’affichage VGA

La figure qui suit montre en détail la constitution du contrôleur d’écriture en mémoire.

la constitution du contrôleur d’écriture en mémoire. Fig5 : Schéma-bloc du contrôleur d’écriture en mémoire

Fig5 : Schéma-bloc du contrôleur d’écriture en mémoire

II.

Implantation

Cette partie est consacrée à la description des techniques utilisées pour la réalisation des unités évoquées précédemment et explicitera leur fonctionnement à l’aide de machines d’états et quelques exemples de code VHDL.

Avant de donner l’implantation des unités, il est nécessaire d’avoir un aperçu sur les caractéristiques de la carte FPGA utilisée.

Caractéristiques

Un FPGA (Spartan 3 de Xilinx)

Une horloge de fréquence 50 MHz (temps de cycle = 20 ns)

Un port série RS232

Une sortie VGA

8 interrupteurs et 4 boutons poussoirs

4 afficheurs 7 segment et 8 LEDs

Une entrée PS/2 pour clavier et souris

2 mémoires RAM statiques

3 connecteurs d’extension pour des applications avancées

1. Module d’émission-réception série

1.1- Module d’émission (TX)

Le module TX permet de transmettre une donnée sur 8 bits sur la liaison série suivant un protocole imposé. La vitesse de transmission est de 9600 bauds (bits par secondes) pour une horloge du FPGA de 50 Mhz. Chaque bit prend, donc, 104 μs pour être transmis. La période de l’horloge étant de 20 ns, il faut 5200 tops d’horloge pour transmettre un bit. On utilisera pour cela deux compteurs : un compteur modulo 16 et un compteur modulo 325. On obtient ainsi un compteur global de 16*325 = 5200. Une machine d’état contrôle le transfert en gérant les différents modules, dont le module de décalage qui permet de transformer l’information parallèle en information série. Le schéma décrivant cette architecture est représenté dans la figure 2.

1.1.1- Les compteurs

On a utilisé 3 compteurs :

- un compteur modulo 16

- un compteur modulo 325

- un compteur modulo 10 (pour compter les bits constituant la trame à transmettre)

L’intérêt derrière l’utilisation de compteurs en cascade est d’éviter d’essayer de minimiser la taille du compteur (de point de vue nombre de pins) et s’approcher toujours des modèles standards.

Compteur modulo 325 Le schéma RTL de ce compteur est donné par la figure suivante :

RTL de ce compteur est donné par la figure suivante : Fig6 : compteur modulo 325

Fig6 : compteur modulo 325 Le code VHDL décrivant ce compteur est le suivant :

-- Diviseur d'horloge (/325) process(h,raz) is variable reg_div : natural range 0 to 324; begin if raz = '1' then reg_div := 0; elsif rising_edge(h) then if reg_div = 324 then reg_div := 0; top_325 <= '1'; else reg_div := reg_div + 1; top_325 <= '0'; end if; end if; end process;

Compteur modulo 16 Très semblable au compteur précédent, ce compteur s’incrémente lorsque le signal top_325 est à 1. Arrivé à 15, le processus envoie le signal fin_bit_tmp au compteur modulo 10 ainsi qu’à la machine d’état du système.

modulo 10 ainsi qu’à la machine d’état du système. Fig7 : compteur modulo 16 Le code

Fig7 : compteur modulo 16 Le code associé à cette entité est le suivant :

-- Diviseur de diviseur d'horloge (/16) process(h,raz) is variable reg_div_16 : natural range 0 to 15; begin if raz = '1' then reg_div_16 := 0; elsif rising_edge(h) then if top_325 = '1' then if reg_div_16 = 15 then reg_div_16 := 0;

fin_bit_tmp <= '1'; else reg_div_16 := reg_div_16 + 1; fin_bit_tmp <= '0'; end if; else reg_div_16 := reg_div_16; fin_bit_tmp <= '0'; end if; end if; end process; fin_bit<=fin_bit_tmp;

Le signal fin_bit est utilisé pour notifié la machine de contrôle de la fin du décompte des 5200 tops d’horloge.

Le compteur de bits (modulo 10) Contrairement aux compteurs précédents, ce compteur possède une remise à zéro synchrone contrôlée par la machine d’état du système via le signal rst_cpt_bit. Lorsque rst_cpt_bit est à l’état bas, le compteur s’incrémente lorsque fin_bit_tmp est égal à ‘1’.

s’incrémente lorsque fin_bit_tmp est égal à ‘1’. Fig8 : compteur modulo 10 Le code décrivant le

Fig8 : compteur modulo 10 Le code décrivant le fonctionnement de ce compteur est donné ci-contre.

-- Compte le nombre de bit's process(h,raz) is variable cpt_bit : natural range 0 to 10; begin if raz = '1' then cpt_bit := 0; elsif rising_edge(h) then if rst_cpt_bit = '1' then cpt_bit := 0; elsif fin_bit_tmp = '1' then if cpt_bit = 9 then cpt_bit := 0; fin_transmit <= '1'; else cpt_bit := cpt_bit + 1; fin_transmit <= '0'; end if; else cpt_bit := cpt_bit; fin_transmit <= '0'; end if; end if; end process;

1.1.2- Module de décalage

Ce module est une réalisation d’un registre de décalage. Il permet d’effectuer 4 actions sur la donnée en fonction du signal de commande cmd envoyée par la partie contrôle du système.

Cmd

Action

00

Décalage du registre de sortie

01

Mémorisation de la valeur sur la sortie

10

Chargement de la donnée entrante

11

Remise à 1 du registre

Tableau 1 : Actions de l’entité de décalage

La donnée parallèle a envoyer se trouve sur le bus din composé de 8 bits. Pour pouvoir émettre une première valeur, il faut en premier lieu charger la valeur de din en rajoutant les bits de Start et de Stop propres à la liaison série dans un registre que nous appellerons reg. La valeur de sortie sera le bit 0 du registre. Comme la valeur doit rester sur le fil pendant un temps dépendant de la vitesse de communication, une mémorisation est effectuée lorsque la commande cmd est à ‘‘01’’.

effectuée lorsque la commande cmd est à ‘‘01’’. Fig9 : module de décalage Le corps de

Fig9 : module de décalage Le corps de cette entité écrit en VHDL est le suivant :

--Decalage process (h,raz) is begin

if raz = '1' then reg <= (others => '1'); elsif rising_edge(h) then case cmd is

when "00" => reg <= '1'& reg(9 downto 1); -- Decalage when "10" => reg <= '1'& din & '0'; -- Formatage -> Bits --de Start et de Stop when "01" => sout <= reg(0) ; reg <= reg;

-- Ne fait

rien. -> Continu la transmission

when "11" => reg <= (others => '1'); when others => reg <= (others => '1'); end case;

end if;

end process;

1.1.3- Partie contrôle

La machine de contrôle est le noyau de l’unité d’émission. C’est une représentation logique des états de fonctionnement de cette unité, définit les transitions entre ces états et assure une synergie entre les divers constituants de l’unité en les commandant. La machine de contrôle peut être représentée à l’aide de la machine d’états suivante :

Fig10 : machine d’états du module TX Cette machine est constituée par 5 états :

Fig10 : machine d’états du module TX Cette machine est constituée par 5 états :

- Attente : Durant cet état, la sortie sout est à l’état haut. Le module attend le signal go pour passer à l’état suivant.

- Attd_bit : Cet état effectue un reset du compteur de bit modulo 10. Le module attend ensuite que le compteur modulo 16 soit revenu à zéro (indiqué par le signal fin_bit) pour passer à l’état suivant et pour libérer le compteur.

- Chargement : Une fois le système prêt, l’entité décalage charge la valeur de la donnée parallèle din dans le registre reg grâce à la commande cmd ‘‘10’’. Une fois la valeur chargée, la machine d’état rentre dans une boucle jusqu'à ce que les 10 bits de l’information soient transmis.

- Mémorisation : L’état attend que la valeur mise sur sout soit finie de transmettre. Ceci est indiqué par le signal fin_bit.

- Décalage : Le décalage de la donnée parallèle est effectué grâce à la commande ‘‘00’’. Si tous les bits sont transmis, la machine d’état retourne dans l’état Attente sinon, elle recommence la boucle Mémorisation/Décalage.

A la fin de l’exécution, la machine d’état fait un dernier décalage avant de retourner dans l’état attente. Cependant, ce décalage ne génère aucune erreur sur le signal de sortie car à ce niveau tous les bits de reg sont à 1. On observe sur le chronogramme de simulation suivant le passage de l’état décalage à l’état attente.

1.2-

Module de réception (RX)

Ce module est chargé de la récupération de convertir les données transitant en série en des données série. L’entité réception ressemble beaucoup à celle de l’émission de point de vue architecture, la seule différence réside dans le fonctionnement de l’entité de contrôle et des états internes. Elle comprend, donc, des compteurs, un module de décalage et une entité de contrôle. Le schéma-bloc de cette unité est représenté sur la figure 3. La machine d’états décrivant le fonctionnement de cette entité est la suivante :

le fonctionnement de cette entité est la suivante : Fig11 : machine d’états du module RX

Fig11 : machine d’états du module RX Ayant remarqué l’importance des compteurs et leur utilisation massive, on a eu recours à l’utilisation d’un compteur générique. Son utilité réside dans le fait qu’au moment de l’instanciation, on fixe la valeur sa valeur de décompte. Le code de ce compteur est donné ci-contre :

entity compteur_N is generic ( N : integer := 4) ; Port ( clk : in std_logic; raz : in std_logic; enable : in std_logic; rst_cpt_bit : in std_logic; fin_N_cycles : out std_logic); end compteur_N; architecture Behavioral of compteur_N is begin -- Compte le nombre de bit's process(clk,raz) is

variable cpt_bit : natural range 0 to N-1;

begin

if raz = '1' then cpt_bit := 0; elsif rising_edge(clk) then if rst_cpt_bit = '1' then cpt_bit := 0; elsif enable = '1' then if cpt_bit = N-1 then cpt_bit := 0; fin_N_cycles <= '1'; else cpt_bit := cpt_bit + 1; fin_N_cycles <= '0'; end if; else cpt_bit := cpt_bit; fin_N_cycles <= '0'; end if; end if; end process; end Behavioral;

De cette manière, on réduit remarquablement la taille du code et le nombre de fichiers à utiliser.

2. Module d’affichage VGA d’une image stockée en mémoire

Ce module rassemble les unités suivantes :

- Une unité de réception (RX) pour recevoir une image (640×480) sur le port série

- Une unité d’affichage VGA d’une image sur un écran VGA (donnée par Xilinx)

- Un contrôleur d’écriture en mémoire associé à l’unité RX

- Un contrôleur de lecture de la mémoire associé à l’unité d’affichage

- Des multiplexeurs pour la séparation physique des deux circuits (réception et affichage) Le schéma-bloc décrivant ce module est représenté dans la figure 4.

Les principales difficultés rencontrées lors de l’élaboration du module d’affichage sont dues aux contraintes de temps liées à la recherche des informations sur les pixels de la mémoire pour les transmettre sur la sortie VGA. Il s’est avéré difficile et fastidieux de faire un chronogramme qui décrit les étapes à suivre et d’essayer de le décrire par une machine d’états. De plus, la simulation de tout le design est difficile, vu qu’il faut simuler la transmission série et qu’on n’a pas eu le temps de trouver une solution pour simuler le fonctionnement de la mémoire. La solution serait de simuler chaque composant à part, ce qui prend beaucoup de temps.

2.1. Contrôleur d’écriture en mémoire

Ce composant gère l’accès de l’unité de réception à la mémoire. Il détermine à l’aide d’un compteur l’adresse à laquelle l’octet reçu sera placé et active tous les signaux nécessaires pour commander la mémoire. Le schéma-bloc de cette unité est représenté sur la figure 5. La machine d’états décrivant le fonctionnement de ce compteur est donnée ci-contre :

Fig12 : machine d’états du contrôleur d’écriture en mémoire 2.2. Gestion des adresses mémoires La

Fig12 : machine d’états du contrôleur d’écriture en mémoire

2.2. Gestion des adresses mémoires

La mémoire présente sur la carte FPGA est une RAM statique de capacité 256k × 16 bits. Elle est, donc, adressée par 18 bits avec la possibilité de sélectionner l’octet de poids faible ou de poids fort. Les pixels de l’image envoyée à partir d’un PC sont codés sur 3 bits. On utilise, donc, un octet pour y stocker 2 pixels à la fois. Pour accéder seulement à l’un des deux blocs d’un mot mémoire, on a adressé la mémoire sur 19 bits comme si elle était filiforme et que chaque case était d’une taille d’un octet. Ainsi, le bit 0 de l’adresse mémoire sert à sélectionner l’octet de poids faible ou de poids fort, et le reste sert à sélectionner la ligne de la mémoire. A l’intérieur de du contrôleur d’écriture, nous avons mis un additionneur pour calculer l’adresse physique de la mémoire à partir d’une adresse logique. L’adresse logique servira, donc, pour index et sa valeur sera ajoutée à une base. Nous avons, pensé à cela au début quand nous voulions réaliser une animation sur un écran VGA.

III.

Simulation

La simulation est une étape importante pour un design en VHDL car elle établit des chronogrammes permettant de suivre les signaux à chaque coup d’horloge et de vérifier le bon fonctionnement du design.

Pour simuler une entité en VHDL, on réalise une entité fictive appelée TestBench qui est une sorte de plateforme de test permettant de stimuler les entrées de l’entité à tester.

Le code suivant (TestBench de l’unité d’émission) donne un aperçu sur la façon de réaliser un TestBench.

ENTITY conv_parallel_serie_tb IS END conv_parallel_serie_tb; ARCHITECTURE behavior OF conv_parallel_serie_tb IS COMPONENT conv_parallel_serie PORT(

clk : IN std_logic; raz : IN std_logic; go : IN std_logic; din : IN std_logic_vector(7 downto 0); sout : OUT std_logic ); END COMPONENT; SIGNAL clk : std_logic; SIGNAL raz : std_logic; SIGNAL go : std_logic; SIGNAL din : std_logic_vector(7 downto 0); SIGNAL sout : std_logic; constant demi_periode : time := 10 ns; BEGIN uut: conv_parallel_serie PORT MAP( clk => clk, raz => raz, go => go, din => din, sout => sout

);

clock:process

begin

clk <= '1'; wait for demi_periode; clk <= '0'; wait for demi_periode; end process; raz <= '1', '0' after 2*demi_periode; go <= '0', '1' after 4*demi_periode, '0' after 6*demi_periode; din <= "01110110"; END;

Après une simulation sur une durée suffisante, on obtient les résultats suivants :

Fig13 : Simulation de l’unité d’émission

Fig13 : Simulation de l’unité d’émission

Fig14 : Simulation de l’unité de réception

Fig14 : Simulation de l’unité de réception Fig15 : Simulation d’un contrôleur de mémoire

Fig15 : Simulation d’un contrôleur de mémoire

Fig14 : Simulation de l’unité de réception Fig15 : Simulation d’un contrôleur de mémoire

Cette figure met en évidence l’importance de la simulation car on voit clairement l’arrivée des octets de données sur le signal data_in et on vérifie que les signaux de contrôle de la mémoire ont les valeurs qu’il faut pour y écrire la donnée (bien qu’on ait commis l’erreur de laisser le chip select de la première SRAM toujours à 1). On remarque, aussi, que l’adresse s’incrémente après la lecture de deux octets.

Conclusion

Au cours de ce projet, nous avons fait l’implantation en VHDL de circuits basiques, à savoir le module UART d’émission et de réception série. Nous avions pu également réaliser un circuit d’écriture dans la mémoire, tel que les octets sont affichés sur 8 LEDs. Cependant, nous n’avions pas pu valider l’architecture de l’affichage sur écran VGA pour des raisons qui sont probablement dues à la difficulté de synchronisation entre les diverses entités qui coexistent ainsi que les difficultés pour tester le design en entier.