\subsection{Cahier des charges} Voici les contraintes du bloc d'entrées / sorties : \begin{itemize} \item{Bloc de 8 entrées / sorties} \item{Chaque fil est configurable soit en entrée, soit en sortie} \item{Chaque fil est configurable pour générer une interruption sur front montant et / ou front descendant} \item{Un signal de RAZ} \end{itemize} % en gros c'est comment est vu le module côté userland. \subsection{Vue comportementale} Les blocs d'entrées / sorties ont plusieurs utilités. La première est de pouvoir brancher des capteurs renvoyant une entrée binaire, par exemple la sortie d'un comparateur. La deuxième est de permettre de commander, des sorties comme par exemple l'allumage de LEDs. Finalement la troisième fonction de ce bloc sera de simuler un bus parallèle. En effet, l'année dernière, nous utilisions un bus parallèle pour lequel nous avons développé un certain nombre de cartes. A partir de blocs d'entrées / sorties, on peut donc réutiliser les modules précédements développés. On pourra voir la figure \ref{entity_gpio} page \pageref{entity_gpio} pour avoir une vue globale du module. \begin{figure}[htbp] \caption{Entity du bloc d'entrées / sorties} \begin{center} \scalebox{0.6}{ \includegraphics {./gpio/images/entity.pdf} %\includegraphics[width=\textwidth]{./interrupt/images/entity.pdf} } \end{center} \label{entity_gpio} \end{figure} Du point de vue comportemental son fonctionnement est le suivant. Au début, le PC configure le bloc après avoir envoyé un signal de remise à zéro. Il commence par configurer les différentes pins du bloc soit en entrées, soit en sorties. Ensuite le PC configure quelles pins pourront générer une interruption. Une fois cela fait, il peut lire et écrire des données sur les entrées et sorties. La configuration du bloc gpio est réalisée en écrivant dans des registres. On remarque que ce module possède quatres signaux "chip select" : cs\_reg\_data, cs\_reg\_direction, cs\_reg\_it\_mask et cs\_read\_output. Le signal cs\_read\_output permet de lire les états des 8 broches d'entrées / sorties. Les autres signaux permettent d'accéder aux registres contenant respectivement, le masque des directions, le masque d'interruption et les données à mettre sur les lignes en sorties. Ces trois registres ont la particularité de pouvoir être écrit mais aussi lu. En effet, pour la phase de teste il nous semble utile que les registres puissent être relus. Ainsi on pourra s'assurer que la configuration est bien celle désirée. Voici comment se déroule les procédures d'écriture et de lecture dans les registres. La procédure d'écriture est la suivante. Tout d'abord, le module dirigeant le bloc écrit sur le bus de donnés l'octet lui permettant de configurer tel ou tel registre. Simultanément, il positionne le signal $R\bar{W}$ en mode écriture (Write). Finalement, il sélectionne à l'aide d'un des signal CS (Chip select) le registre dans lequel il veut écrire. La procédure de lecture s'effectue en positionnant le signal $R\bar{W}$ en lecture (Read), puis en sélectionnant le chip select du registre auquel on désire accéder. On notera que pour interfacer ce bloc et le bus ISA, il faut un module dont le rôle sera de convertir les signaux du bus ISA en les signaux $R\bar{W}$ et les signaux de "chip select" (CS). Pour résumer, voici quelques informations utiles : \begin{itemize} \item{La lecture (signal $R\bar{W}$) : active pour un état haut} \item{L'écriture (signal $R\bar{W}$) : active pour un état bas} \item{Le masque d'interruptions : interruption active pour un état haut, inactive pour un état bas} \item{Le masque de directions : en sortie pour un état haut, en entrée pour un état bas} \end{itemize} \subsection{Exemple d'utilisation du module} Voici un exemple pour illustrer les discours précédents. On pourra se reporter aux chronogrammes de la figure \ref{gpio_behav_simul} page \pageref{gpio_behav_simul}. Ce chronogramme représente la simulation comportementale du bloc d'entrées sorties. %% TODO : Se débrouiller pour inclure l'image % Commande sympas : convert -rotate -90 fichier.tiff fichier.pdf %\begin{figure}[htbp] %\begin{center} %\scalebox{0.6}{ %\includegraphics {./gpio/sim/gpio_behavior_simul.pdf} %} %\includegraphics[height=0.7\textwidth,angle=90]{./gpio/sim/gpio_behavior_simul.pdf} %\end{center} %\label{gpio_behav_simul} %\end{figure} Dans cet exemple, nous allons configurer puis utiliser le bloc d'entrée / sorties. La première action à effectuer est une remise-à-zéro du bloc à l'aide de son signal reset. C'est ce que l'on remarque lorsque le signal rst est à 1. Ce signal doit garder un état haut durant au moins une prériode d'horloge du bus ISA (clk\_i). On remarque que sur les entrées /sorties, on simule le fait d'avoir branché des capteurs sur les cinq lignes de poids fort. On voit donc apparaître sur la sortie les valeurs $00001ZZZ$. Cela signifie que l'on laisse les trois pins de poid faible dans un état de haute impédance. Une fois cela fait, on configure alors le bloc. Pour ce faire, l'ordinateur place tout d'abord sur le bus de données le masque de direction. Dans l'exemple, le masque est $00000111$, ce qui signifie que l'on désire positionner les 3 pins de poid faible en sorties. On peut alors constater que les trois pins du bloc qui sont en sortie, prennent la valeur $0$. Cela vient du fait que lors du reset, on a remis le bloc à zéro, et par défaut, les sorties sont à zéro d'ou les signaux obtenus. On remarquera aussi que la ligne $R\bar{W}$ est en écriture. Ainsi, dès que la ligne de validation du registre de configuration des directions (ligne chip select : cs\_reg\_direction ) est à un état haut et qu'il y a un front montant de l'horloge (clk\_i) du bus ISA, on configure le bloc avec les signaux sur le bus de données. De la même manière, on configure ensuite le masque d'interruption pour lequel on conserve la valeur $11111000$. On remarque que cet octet est le complémentaire du masque de direction. Dans cette configuration, on vient d'autoriser les interruptions sur les pins en entrée du bloc. Ainsi, dès qu'il y aura un changement d'état sur l'une des cinq pins de poid fort, une interruption sera générée. Ensuite, on transmet au bloc les signaux que l'on désire voir sur les lignes en sortie du bloc. Dans notre cas on transmet $00000001$. Comme seules les trois pins de poid faible sont en sortie, on recopie en sortie $ZZZZZ001$ sans tenir compte des bits de poid fort. Comme les "capteurs simulés" sur les cinq bits de poid fort génèrent les valeurs $00001ZZZ$, on retrouve sur la sortie un mélange de ces signaux, d'où la valeur de $00001001$. Dans la suite, on se propose de relire les valeurs affectées. C'est ce que l'on fait. On vérifie successivement le masque d'interruption, le registre de direction puis le registre de données. Finalement le PC veut lire les valeurs situées sur les entrées sorties, ce qui est réalisé grâce au signal cs\_read\_output. On remarquera aussi le signal d'interruption. Celui-ci passe à l'état haut lorsque l'état des "capteurs" change. Le bloc d'entrées /sorties attend alors que le PC demande à lire les entrées / sorties pour achever l'interruption. \subsection{Architecture physique} Nous allons dans cette partie étudier plus en détails le fonctionnement interne du module d'entrées /sorties. On pourra consulter l'architecture physique sur la figure \ref{archi_gpio} page \pageref{archi_gpio}. \begin{figure}[htbp] \caption{Architecture physique du bloc d'entrées / sorties} \begin{center} %\scalebox{0.7}{\includegraphics {./interrupt/images/archi_phy.pdf}} \includegraphics[width=\textwidth]{./gpio/images/archi_phy.pdf} \end{center} \label{archi_gpio} \end{figure} Comme on peut le constater, ce module est relativement simple. On peut le décomposer en deux parties : la configuration et la lecture / écriture des entrées et sorties. Nous commencerons par nous pencher sur la configuration du bloc. Nous avons vu précédement que pour la configuration d'un bloc d'entrées / sorties, il y avait deux registres de configuration, un registre contenant un masque déterminant la direction de chaque pin et un registre contenant un masque d'interruption. On retrouve bien ces deux registres sur le schéma directement connectés au bus de données. On trouve un troisième registre nommé registre de données. Celui-ci est chargé de mémoriser les valeurs à mettre sur les pins du bloc qui sont configurées en sortie. Pour revenir aux registres de configuration, ils sont alors connectés sur deux autres blocs. Le premier, est le gestionnaire de direction et a pour but de recopier les valeurs du registre de données uniquement sur les pins qui sont configurées en sorties. Le deuxième est le gestionnaire d'interruption qui est chargé de générer les interruptions. On voit que pour cela il s'aide du masque d'interruption. Finalement, pour la lecture des entrées / sorties on connecte directement sur les pins un bloc à trois états (état bas, état haut et haute impédance). Ce bloc dès qu'on le sélectionne à l'aide du signal cs\_read\_output recopie les entrées sorties sur le bus de données. On notera que ce module, de même que les trois registres, sont synchronisés sur l'horloge du bus ISA. \subsection{Décomposition RTL} Commençons par décrire le fonctionnement des registres nommés % Reg_rw % Module haute impédance Pour la lecture des valeurs sur les entrées / sorties, un composant nommé \textit{tristate} est utilisé. Ce composant est en fait un module synchrone composé de huits composants trois états. Son comportement est donc le suivant : \begin{itemize} \item{Si enable (représenté par cs\_read\_output sur le schéma) est à un état bas, les sorties sont dans un état haute impédance} \item{Si enable est à l'état bas on recopie les entrées / sorties sur le bus de données} \end{itemize} \subsection{Simulation du bloc}