{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Logique combinatoire - PLD - CORRECTION" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Ressources** : \n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "**Sommaire**\n", "
    \n", "
  1. Présentation\n", "
      \n", "
    1. Historique
    2. \n", "
    3. La fonction \"décodage\"
    4. \n", "
    \n", "
  2. \n", "
  3. Enoncé
  4. \n", "
  5. Equations de la fonction \"Décodage\"
  6. \n", "
  7. Simulation\n", "
      \n", "
    1. Préparation des vecteurs de test
    2. \n", "
    3. Exemple d'utilisation des vecteurs de test
    4. \n", "
    5. Test des sorties RAM, ROM et OE de la fonction \"Décodage\"
    6. \n", "
    7. Génération automatique de la table des vecteurs de test
    8. \n", "
    \n", "
  8. \n", "
\n", "\n", "----" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Présentation\n", "Les circuits électroniques (microprocesseur, chipset, System on Chip) assurent le fonctionnement de nos outils numériques (ordinateur, tablette, smartphone, etc.). Ils sont constitués de fonctions logiques complexes (unité arithmétique et logique, multiplexeur, décodeur, etc.) issues de l'assemblage d'opérateurs logiques combinatoires (ET, OU, NON, etc.) et séquentiels (bascules). \n", "\n", "Dans ce TP, vous allez **simuler** les tests à effectuer sur une fonction logique avant son intégration dans un circuit logique programmable." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.A Historique\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", "

La figure ci-contre représente le boîtier DIP (Dual In Package) à 14 broches d’un circuit intégré de type SSI (Small Scale Integration) contenant quatre portes ET à deux entrées.
Apparus en 1964, les circuits logiques SSI sont encore utilisés. Ils contiennent de 1 à 12 portes. Dans les années 80, une fonction logique telle que celle représentée par le logigramme ci-dessous nécessitait l’utilisation de trois circuits intégrés de type SSI intégrant chacun quatre portes logiques.


Ces composants étaient soudés et interconnectés par des pistes de cuivre sur un circuit imprimé.\n", "
\n", " \n", "
\n", "\n", "![decodeur.jpg](img/decodeur.jpg)\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " On dispose aujourd’hui de circuits logiques programmables (Programmable Logic Devices) capables, selon leur complexité, de remplacer quelques dizaines à plusieurs centaines de milliers de circuits logiques \"classiques\". Le mot \"programmable\" ne signifie pas que le circuit exécute un programme, mais que les opérateurs logiques qu'il contient sont interconnectés à l'aide d'un programme ! Si la fonction réalisée ne correspond pas à celle attendue ou si on souhaite la faire évoluer, le composant pourra être \"effacé\" et reprogrammé.
Pour en savoir plus
.

\n", " Un circuit logique programmable renferme un grand nombre d’opérateurs logiques combinatoires (ET, OU, NON, etc.) et séquentiels (bascules). Ce type de composant est utilisé lors de la conception ou lors de la réorganisation d’un produit nécessitant la mise en œuvre d’un grand nombre d’opérateurs logiques, car il améliore la fiabilité du produit, diminue son coût de fabrication et lui confère une certaine évolutivité. Wikipédia.\n", "
\n", "\n", "\n", " \n", " \n", " \n", " \n", "
\n", " On assure l’interconnexion des opérateurs logiques avec un outil de programmation (ordinateur + logiciel).

\n", " Lorsque la fonction à intégrer dans le PLD est combinatoire et suffisamment simple, il suffit d'écrire les équations logiques booléennes de ses sorties avec le logiciel de programmation \n", "
\n", " \n", "
\n", "\n", "\n", " \n", " \n", " \n", " \n", "
La \"programmation\" d'un circuit logique programmable est réalisée avec un langage de description matériel ou un outil de saisie graphique. Après compilation de cette description, on obtient un fichier de configuration pour le circuit choisi.
VHDL et Verilog sont les deux langages de description les plus répandus. Il existe cependant un outil, migen, basé sur Python qui vise à automatiser davantage le processus de conception.
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.B La fonction \"Décodage\"\n", "La fonction logique \"**Décodage**\" est une fonction **combinatoire**. Elle reçoit n bits en entrée (2n combinaisons) et délivre M bits en sortie telle que M ≤ 2n. La fonction \"Décodage\" est courante en électronique numérique. Elle est notamment utilisée dans les microprocesseurs pour réaliser le **décodeur d'instructions**.\n", "\n", "## 2. Enoncé\n", "Dans le cadre de la modification d’une carte électronique, on souhaite intégrer une fonction **Décodage**, initialement réalisée avec trois composants logiques, dans un PLD. Le logigramme de cette fonction est donné ci-dessous." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Logigramme\n", "\n", "

Dessiné avec Scheme-it.

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Equations de la fonction \"Décodage\"\n", "On limite l'étude à trois des six sorties de la fonction. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> **Activité 1**\n", ">\n", "> Si l'activité n'a pas été préparée en cours, **écrivez** les équations de RAM, ROM et OE sur le **document réponse**. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Correction

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Simulation\n", "Après la phase de programmation d’un PLD, il est nécessaire d’en vérifier le fonctionnement. Dans le cas du test d’une fonction combinatoire, il suffit de placer sur ses entrées toutes les combinaisons logiques qu’elle est susceptible de recevoir et de comparer chaque état de sa sortie avec celui attendu. Ceci est fait automatiquement par l’outil de programmation. Seule l’écriture des **vecteurs de test** incombe au concepteur.\n", "\n", "Un vecteur de test se compose des **valeurs à placer sur les entrées** (E1, E2, .., En) de la fonction à tester et du **résultat attendu** sur sa sortie (S). Le vecteur de test i peut s'exprimer sous la forme : **Vi(E1, E2, .., En, S)**\n", "\n", "__Exemple__ : test d’une fonction f() implantée dans un PLD telle que **S = /E1.E2 + E1./E2** (/ <=> not)\n", "\n", "\n", "\n", "Dans l’exemple ci-dessus, les vecteurs V1(0,0,0), V2(0,1,1), V3(1,0,1) et V4(1,1,0) sont placés successivement sur les entrées du PLD reliées à la fonction f(). \n", "\n", "

Pour tester une sortie logique combinatoire, il est nécessaire d’écrire 2n vecteurs.
n représente le nombre d’entrées de la fonction.

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.A Préparation des vecteurs de test" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> **Activité 2**\n", ">\n", "> Si l'activité n'a pas été préparée en cours, **complétez** les tables de vérité du document réponse avec les **résultats attendus** sur les sorties **RAM**, **ROM** et **OE**." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Correction

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.B Exemple d'utilisation des vecteurs de test\n", " * **Ressources** : listes, tuples, tests, boucle for... et f-strings en Python.\n", "\n", "Le langage Python dispose des opérateurs logiques **and**, **or** et **not** pour écrire des équations logiques. Les états logiques peuvent être représentés par des 1 et des 0. **0** <=>False, **1** <=> True. \n", "\n", "L'exemple ci-dessous illustre le test d'un opérateur **Ou Exclusif** à 2 entrées." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Exemple introductif\n", "# Code de test d'une fonction XOR\n", "'''\n", "Test d'une porte OU Exclusif à 2 entrées\n", "E1, E2 : entrées\n", "S : sortie (on note Sa la sortie attendue et So est la sortie obtenue !)\n", "'''\n", "Vecteurs_XOR = [(0, 0, 0), (0, 1, 1), (1, 0, 1), (1, 1, 0)] # Une liste de tuples matérialise la table des vecteurs de test\n", "print(\"[E1,E2] -> S \")\n", "for E1, E2, Sa in Vecteurs_XOR:\n", " So = (not(E1) and E2 or E1 and not(E2)) # Equation de la porte OU Exclusif, parenthèses INDISPENSABLES !\n", " if Sa == So: # Remplacer and par or pour simuler des erreurs dans la table\n", " print(f\"[{E1},{E2}] -> {Sa}\") \n", " else:\n", " print(f\"[{E1},{E2}] -> Erreur\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ">**Activité 3. Simulons des erreurs de frappe !**
\n", ">\n", "> **Testez** les situations suivantes : \n", "> - le vecteur (0,1,1) a été remplacé par (0,1,0)
\n", "> - l'opérateur or a été remplacé par un and
\n", ">\n", "> a) Comment identifie-t-on une erreur dans la table ?
\n", "> b) Quelles sont les causes d'erreur lors du test d'un circuit logique programmable réel ? \n", ">\n", "> Répondez ci-dessous." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Correction

\n", "

a) Une erreur (So=/=Sa) est identifiée dans la table par le mot \"Erreur\"

\n", "

b) Lors du test d’un composant réel, les causes erreurs peuvent être :

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ">**Activité 4. Amélioration de l'affichage dans l'exemple introductif**
\n", "> En reprenant l'exemple introductif, **complétez** le code ci-dessous pour que le résultat du test affiche Sa, So et précise la position des erreurs.
\n", ">\n", "> Exemple de résultat attendu
\n", "> [E1,E2] -> Sa So
\n", "> [0,0] -> 0,0
\n", "> [0,1] -> 0,1->Erreur
\n", "> [1,0] -> 1,1
\n", "> [1,1] -> 0,0" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Exemple introductif modifié (à compléter)\n", "# Code de test d'une fonction XOR\n", "'''\n", "Test d'une porte OU Exclusif à 2 entrées\n", "E1, E2 : entrées\n", "S : sortie (on note Sa la sortie attendue et So est la sortie obtenue !)\n", "'''\n", "Vecteurs_XOR = [(0, 0, 0), (0, 1, 1), (1, 0, 1), (1, 1, 0)] # Une liste de tuples matérialise la table des vecteurs de test\n", "print(\"[E1,E2] -> Sa So \")\n", "for E1, E2, Sa in Vecteurs_XOR:\n", " So = (not(E1) and E2 or E1 and not(E2)) # Equation de la porte OU Exclusif, parenthèses INDISPENSABLES !\n", " # Remplacer and par or pour simuler des erreurs dans la table\n", " if Sa == So: \n", " print(f\"[{E1},{E2}] -> {Sa},{int(So)}\") \n", " else:\n", " print(f\"[{E1},{E2}] -> {Sa},{int(So)} -> Erreur\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.C Test des sorties RAM, ROM et OE de la fonction \"Décodage\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> **Activité 5**\n", ">\n", "> En vous inspirant de l'exemple introductif modifié et en utilisant les résultats des activités 1 et 2, écrivez le code de test de la sortie **RAM**. Simulez des erreurs de frappe." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Code de test de la sortie RAM\n", "Vecteurs_RAM = [ # Correction\n", " # A15,PSEN,RAMa \n", " (0, 0, 1), \n", " (0, 1, 0), \n", " (1, 0, 1), \n", " (1, 1, 1)] \n", "print(\"[A15,PSEN] -> RAMa RAMo\")\n", "# Correction\n", "for A15, PSEN, RAMa in Vecteurs_RAM:\n", " RAMo = (A15 or not(PSEN)) # Remplacer or par and pour simuler des erreurs dans la table\n", " if RAMa == RAMo:\n", " print(f\"[{A15},{PSEN}] -> {RAMa},{int(RAMo)}\")\n", " else:\n", " print(f\"[{A15},{PSEN}] -> {RAMa},{int(RAMo)} ->Erreur\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> **Activité 6**\n", ">\n", "> En vous inspirant de l'exemple introductif modifié et en utilisant les résultats des activités 1 et 2, écrivez le code de test de la sortie **ROM**. Simulez des erreurs de frappe." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Code de test de la sortie ROM\n", "Vecteurs_ROM = [ # Correction\n", " # A15,RD,PSEN,ROMa\n", " (0, 0, 0, 0),\n", " (0, 0, 1, 1),\n", " (0, 1, 0, 0),\n", " (0, 1, 1, 1),\n", " (1, 0, 0, 0),\n", " (1, 0, 1, 0),\n", " (1, 1, 0, 0),\n", " (1, 1, 1, 1)\n", "]\n", "print(\"[A15,RD,PSEN] -> ROMa ROMo\")\n", "# Correction\n", "for A15, RD, PSEN, ROMa in Vecteurs_ROM:\n", " ROMo = ((not(A15) and PSEN) or (RD and PSEN)) # Remplacer and par or pour simuler des erreurs dans la table\n", " if ROMa == ROMo:\n", " print(f\"[{A15},{RD},{PSEN}] -> {ROMa}, {int(ROMo)}\")\n", " else:\n", " print(f\"[{A15},{RD},{PSEN}] -> {ROMa}, {int(ROMo)} ->Erreur\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> **Activité 7**\n", ">\n", "> En vous inspirant de l'exemple introductif modifié et en utilisant les résultats des activités 1 et 2, écrivez le code de test de la sortie **OE**. Simulez des erreurs de frappe." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Code de test de la sortie OE\n", "Vecteurs_OE = [ # Correction\n", " # A15,A14,A13,A12,OEa\n", " (0, 0, 0, 0, 0),\n", " (0, 0, 0, 1, 0),\n", " (0, 0, 1, 0, 0),\n", " (0, 0, 1, 1, 0),\n", " (0, 1, 0, 0, 0),\n", " (0, 1, 0, 1, 0),\n", " (0, 1, 1, 0, 0),\n", " (0, 1, 1, 1, 0),\n", " (1, 0, 0, 0, 0),\n", " (1, 0, 0, 1, 0),\n", " (1, 0, 1, 0, 0),\n", " (1, 0, 1, 1, 0),\n", " (1, 1, 0, 0, 0),\n", " (1, 1, 0, 1, 0),\n", " (1, 1, 1, 0, 0),\n", " (1, 1, 1, 1, 1),\n", "]\n", "print(\"[A15,A14,A13,A12] -> OEa OEo\")\n", "# Correction\n", "for A15,A14,A13,A12,OEa in Vecteurs_OE:\n", " OEo = (A15 and A14 and A13 and A12) # Remplacer and par or pour simuler des erreurs dans la table\n", " if OEa == OEo:\n", " print(f\"[{A15},{A14},{A13},{A12}] -> {OEa}, {int(OEo)}\")\n", " else:\n", " print(f\"[{A15},{A14},{A13},{A12}] -> {OEa}, {int(OEo)} ->Erreur\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.D Génération automatique de la table des vecteurs de test" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " * **Ressources** : listes, tuples, tests, boucle for..., f-strings et sélection dans une chaîne (slicing) en Python.\n", " \n", "Lorsque le nombre d'entrées augmente, la table des vecteurs de test devient imposante. Pour **n=6**, il faut écrire **64 vecteurs**. L'écriture d'une telle table devient fastidieuse et le risque d'erreur augmente. Il devient alors nécessaire de disposer d'une fonction de génération automatique de la table des vecteurs de test. \n", "\n", "On propose l'algorithme ci-dessous." ] }, { "cell_type": "raw", "metadata": {}, "source": [ "Algorithme creerVecteursTest(n,vs)\n", "Entrées\n", "n : nombre d'entrées de la fonction à tester\n", "vs : liste des valeurs attendues pour la sortie S de la fonction, notée Sa\n", "\n", "Sortie\n", "vecteurs : table des vecteurs de test\n", "\n", "début\n", " pour i variant de 0 à (nombre_de_vecteur - 1) par pas de 1\n", " faire\n", " Construire le vecteur Vi(b_n-1, b_n-2,..., b0, Sa)\n", " Ajouter Vi à vecteurs\n", " fin faire\n", " Renvoyer vecteurs\n", "fin" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Remarque** : Python dispose de la fonction native bin. Cette fonction convertit un nombre entier en binaire dans une chaîne avec le préfixe 0b." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Exemple \n", "bin(8)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ">**Activité 8**\n", ">\n", "> **Complétez** la fonction *creerVecteursTest* ébauchée ci-dessous.
*Conseil : développer la fonction dans un éditeur (VSCode, etc.) avant de la tester dans le notebook.*\n", ">\n", ">*Résultat attendu* pour n=3
\n", ">vecteurs = [(0, 0, 0, 0), (0, 0, 1, 1), (0, 1, 0, 0), (0, 1, 1, 1), (1, 0, 0, 0), (1, 0, 1, 0), (1, 1, 0, 0), (1, 1, 1, 1)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def creerVecteursTest(n, vs):\n", " vecteurs = []\n", " # Correction\n", " vecteur_i = [] # Vecteur de la ligne i dans la table\n", " for i in range(2**n): # Pour n entrées, la table contient les lignes 0 <= i <= (2^n) - 1\n", " # Suppression de '0b' dans la représentation binaire de i\n", " binaire_i = bin(i)[2:] # pour i = 3 binaire_i='11'\n", " # conversion du nombre binaire_i en une liste de booléens\n", " for j in binaire_i:\n", " vecteur_i.append(int(j)) # pour i = 3 vecteur_i = [1,1]\n", " # si la taille du vecteur < n, il est complété par des 0\n", " for _ in range(n-len(vecteur_i)):\n", " vecteur_i.insert(0, 0) # pour i = 3 et n = 3 vecteur_i = [0,1,1]\n", " vecteur_i.append(vs[i]) # Ajout de la valeur attendue pour s \n", " # pour i = 3, n = 3 et vs[i] = 1 vecteur_i = [0,1,1,1]\n", " # Ajout du vecteur i à la table des vecteurs\n", " vecteurs.append(tuple(vecteur_i)) # sous la forme d'un tuple\n", " # pour i = 3, n = 3 et vs[i] = 1, on ajoute (0,1,1,1) à vecteurs\n", " vecteur_i = [] # on vide le vecteur i en cours pour le calcul du vecteur i+1\n", " return vecteurs\n", "\n", "# Test de la sortie Rom\n", "Roma = [0, 1, 0, 1, 0, 0, 0, 1]\n", "tableVecteurs = creerVecteursTest(3, Roma)\n", "print(tableVecteurs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> **Activité 9**. **Synthèse**\n", ">\n", "> **utilisez** la fonction *creerVecteurTest* pour tester la sortie **OE**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Code de test de OE avec la fonction creerVecteurTest\n", "# Exécuter creerVecteursTest avant !!!!!!!!!!!!!!!!!\n", "# --------------------------------------------------\n", "OEa = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1] # OE attendu\n", "Vecteurs_OE = creerVecteursTest(4, OEa)\n", "print(\"[A15,A14,A13,A12] -> OEa OEo\")\n", "# Correction\n", "for A15,A14,A13,A12,OEa in Vecteurs_OE:\n", " OEo = (A15 and A14 and A13 and A12) # Remplacer and par or pour simuler des erreurs dans la table\n", " if OEa == OEo:\n", " print(f\"[{A15},{A14},{A13},{A12}] -> {OEa}, {int(OEo)}\")\n", " else:\n", " print(f\"[{A15},{A14},{A13},{A12}] -> {OEa}, {int(OEo)} -> Erreur\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.5" } }, "nbformat": 4, "nbformat_minor": 4 }