Construire son propre microcontrôleur

Cet article est axé sur l’apprentissage de la conception d’un cœur de microcontrôleur et est destiné à un usage éducatif uniquement. Veuillez visiter www.zilog.com et vérifiez la gamme de produits du fabricant pour sélectionner un microcontrôleur qui correspond aux besoins de votre projet (à partir de huit bits Z8! et eZ80 acclame le ZNEO32 basé sur ARM Cortex-M3 32 bits! qui comprend des capacités de contrôle moteur avancées).

Mon histoire d’amour avec les microcontrôleurs et les microprocesseurs a commencé en 1988 lorsque je travaillais pour obtenir un diplôme technique au CEFET-PR (une école secondaire / technique et une université brésilienne de quatre ans située à Curitiba). J’ai commencé par apprendre les bases en explorant le classique Zilog Z-80 (Figure 1a).

FIGURE 1A. Le Zilog Z-80A (avec l’aimable autorisation de Wikimedia Commons).

Avance rapide à travers une carrière de programmation qui comprenait la rédaction de livres sur la programmation de microcontrôleurs (voir Ressources), le démarrage d’une petite maison de design (ScTec) et la fin d’un programme post-diplôme au CEFET-SC (une autre université brésilienne située à Florianopolis). C’était en 2008, lorsque j’ai eu plus de contact avec la logique programmable et le VHDL et ma curiosité a atteint un sommet. Des années plus tard, en 2016, j’ai trouvé un kit FPGA (Field-Programmable Gate Array) très abordable et j’ai décidé de lui donner une chance, et j’ai commencé à en apprendre davantage sur la technologie FPGA.

Quoi de mieux que de concevoir un softcore pour en savoir plus sur le VHDL (langage de description du matériel VHSIC), les FPGA et les cœurs de microprocesseur eux-mêmes? J’ai fini par choisir un parent Z-80 moderne: le Zilog Z8 Encore! (alias eZ8; Figure 1b).

FIGURE 1B. Zilog eZ8.

C’est un cœur de microcontrôleur à huit bits avec un jeu d’instructions simple mais puissant et un très bon débogueur sur puce. Avec son lightweight léger (environnement de développement intégré) et son compilateur ANSI C gratuit, c’est un excellent projet pour apprendre (et aussi enseigner) sur les systèmes embarqués.

Avant de plonger dans les profondeurs du cœur de fonctionnement, du VHDL et des FPGA, jetons un coup d’œil sur le Zilog Z8 Encore ! caractéristique.

FIGURE 1C. FPz8 sur un FPGA.

Zilog Z8 Encore!

L’eZ8 est une famille de microcontrôleurs à huit bits basée sur la famille Z8 à succès de Zilog et sur le grand héritage Z-80. Il dispose d’une machine Harvard CISC avec jusqu’à 4 096 octets de RAM (registre de fichiers et zone de registres de fonctions spéciales), jusqu’à 64 Ko de mémoire de programme (généralement de la mémoire Flash) et jusqu’à 64 Ko de mémoire de données (RAM). Le cœur eZ8 comprend également un contrôleur d’interruption vectorisé à priorité programmable et un débogueur sur puce qui communique avec l’ordinateur hôte en utilisant une communication série asynchrone. Ces microcontrôleurs sont dotés d’un très bel ensemble de périphériques, allant des minuteries 16 bits polyvalentes aux minuteries de commande de moteur, de plusieurs UARTs (prêts pour IrDA) aux périphériques USB, et bien plus encore (visite www.zilog.com pour vérifier la gamme complète de produits).

Une caractéristique majeure du modèle de programmation eZ8 est l’absence d’accumulateur fixe. Au lieu de cela, n’importe laquelle des 4 096 adresses RAM possibles peut fonctionner comme accumulateurs. La CPU traite sa RAM principale (le fichier et la zone de registres de fonctions spéciales SFRs) comme un grand ensemble de registres CPU. Pour ce faire, la RAM est divisée en groupes de registres (il y a 256 groupes de 16 registres de travail chacun). Une instruction fonctionne généralement dans un seul groupe de registres de travail, qui est sélectionné par un SFR nommé RP (register pointer). Notez que tous les SFR sont situés à la dernière page de la RAM (adresses commençant de 0xF00 à 0xFFF).

En ce qui concerne le jeu d’instructions, il y a 83 instructions différentes divisées en deux pages d’opcode. Il comprend des instructions habituelles pour les opérations de base telles que l’addition, la soustraction, les opérations logiques, les instructions de manipulation de données, les instructions de décalage, les instructions de changement de flux, certaines instructions 16 bits, les tests et manipulations de bits, la multiplication 8×8, etc.

La zone mémoire du programme est organisée de sorte que les premières adresses soient dédiées à des fins spéciales. Les adresses 0x0000 et 0x0001 sont dédiées aux options de configuration ; les adresses 0x0002 et 0x0003 stockent le vecteur de réinitialisation ; et ainsi de suite. Le tableau 1 montre l’organisation de la mémoire du programme.

0x0000 Option bytes
0x0002 Reset vector
0x0004 WDT vector
0x0006 Illegal instruction vector
0x0008 to 0x0037 Interrupt vectors
0x0038 to 0xFFFF User program memory area

TABLE 1. Simplified program memory organization.

Certains appareils incluent également un deuxième espace de données (jusqu’à 65 536 adresses) accessible uniquement en utilisant les instructions LDE/LDEI. Cette zone peut être utilisée pour stocker des données moins utilisées (car la lecture / écriture y est plus lente que la zone RAM / SFR).

FPz8

La première implémentation de FPz8 utilise une approche de conception très conservatrice et câblée avec deux bus principaux : un pour la mémoire de programme et un autre pour la mémoire de registre. Comme j’ai choisi de ne pas inclure de zone de mémoire de données, les instructions LDE / LDEI ne sont pas implémentées.

Les bus de mémoire de programme comprennent un bus d’adresses d’instructions de 16 bits (IAB), un bus de données d’instructions de huit bits (IDB pour lire des données de la mémoire de programme), un bus de données d’écriture d’instructions de huit bits (IWDB pour écrire des données dans la mémoire de programme), et un signal PGM_WR qui commande l’écriture dans la mémoire de programme. FPz8 comprend 16 384 octets de mémoire de programme implémentés à l’aide de la RAM de bloc synchrone (ce qui signifie que le contenu de la mémoire de programme est perdu lorsque l’appareil est hors tension).

Les cinq bus de zone de registre comprennent trois pour la zone de registre de fichiers (RAM utilisateur), et deux autres dédiés aux registres de fonctions spéciales. Il existe un bus principal d’adresse de registre de fichiers à 12 bits (FRAB), un bus de données d’entrée de registre de fichiers à huit bits (FRIDB), un bus de données de sortie de registre de fichiers à huit bits (FRODB), un bus de données d’entrée de registre à huit bits (RIDB) et enfin un bus de données de sortie de registre à huit bits (RODB) pour l’écriture dans SFRs. Le FPz8 comprend 2 048 octets de mémoire RAM utilisateur implémentée à l’aide de RAM de bloc synchrone.

La figure 2 montre un schéma fonctionnel du FPz8; vous pouvez voir le processeur, deux unités de mémoire (une pour le stockage du programme et l’autre pour le stockage des données), ainsi qu’un module de minuterie externe.

FIGURE 2. Schéma bloc FPz8.

Notez que je n’utilise pas de bus bidirectionnels pour les interconnexions dans ce projet. Les bus unidirectionnels sont plus simples à utiliser, bien qu’ils soient moins économes en espace.

La description VHDL du FPz8 est grande et un peu complexe, donc je vais diviser son fonctionnement en quelques modules pour faciliter la compréhension:

  1. Moteur de mise en file d’attente d’instructions
  2. Décodage d’instructions
  3. Traitement d’interruption
  4. Débogueur

Moteur de mise en file d’attente d’instructions

La récupération d’instructions est une tâche principale pour tout processeur. L’architecture Harvard du FPz8 permet la récupération simultanée et l’accès aux données (grâce à des bus séparés pour les instructions et les données). Cela signifie que le processeur peut récupérer une nouvelle instruction pendant qu’une autre lit ou écrit dans la mémoire de données.

L’eZ8 a un mot d’instruction de longueur variable (la longueur de l’instruction varie d’un octet à cinq octets); certaines instructions sont longues mais plus rapides que d’autres. De cette façon, une instruction BRK a une longueur d’un octet et s’exécute en deux cycles, tandis qu’une instruction LDX IM, ER1 a une longueur de quatre octets et s’exécute en deux cycles d’horloge.

Alors, comment pouvons-nous décoder avec succès toutes ces instructions? Avec une file d’attente d’instructions; c’est-à-dire un mécanisme qui continue de récupérer des octets de la mémoire du programme et de les stocker dans un tableau de huit octets:

if(CAN_FETCH= ‘1’) puis
if(IQUEUE.FETCH_STATE=F_ADDR) puis
FETCH_ADDR: = PC;
IAB< = PC;
IQUEUE.WRPOS: = 0;
IQUEUE.RDPOS: = 0;
IQUEUE.CNT := 0;
IQUEUE.FETCH_STATE: = F_READ;
else
if(IQUEUE.FULL=’0′) puis
IQUEUE.FILE D’ATTENTE (IQUEUE.WRPOS): = IDB;
FETCH_ADDR: =FETCH_ADDR+1;
IAB < = FETCH_ADDR;
IQUEUE.WRPOS : = IQUEUE.WRPOS +1;
IQUEUE.CNT : = IQUEUE.CNT +1;
end if;
end if;
end if;
if(IQUEUE.CNT = 7) puis IQUEUE.PLEIN: = ‘1’; sinon IQUEUE.PLEIN: = ‘0’;
fin si;

LISTE 1. Moteur de file d’attente d’instructions.

La récupération est contrôlée par un signal d’activation principal (CAN_FETCH) qui peut être désactivé dans certains cas particuliers (traitement d’interruption, par instructions LDC/LDCI ou accès au débogueur). Il existe également une structure (IQUEUE) qui stocke plusieurs paramètres internes (état de récupération, pointeurs de lecture et d’écriture, tableau de file d’attente lui-même, compteur et indicateur complet).

Le compteur de file d’attente (CNT) est utilisé pour identifier le nombre d’octets disponibles pour une utilisation (lecture) dans la file d’attente. L’étage décodeur utilise ce nombre pour vérifier que le nombre d’octets souhaité pour l’instruction est déjà disponible dans la file d’attente.

Décodage d’instructions

C’est là que la magie se produit. Le décodeur d’instructions lit les opcodes de la file d’instructions et les traduit en opérations correspondantes.

La conception du décodeur d’instructions a commencé par déterminer la relation entre toutes les instructions et tous les modes d’adressage. À première vue, il est facile de voir que certaines instructions (Figure 3) sont regroupées par colonne (DJNZ, JR cc, X, LD r1, IM, JP cc, DA et INC r1). Le décodage d’une instruction INC r1 est simple : Sur ces instructions à un octet, le picotement haut spécifie le registre source/destination et le picotement bas spécifie l’instruction elle-même (0xE).

FIGURE 3. Opcodes par groupes.

La plupart des instructions peuvent être classées selon certaines règles de base:

  1. Les colonnes (le grignotage inférieur d’un opcode) spécifient généralement un mode d’adressage: Les instructions de la colonne 0x9, par exemple, utilisent principalement le mode d’adressage IM, ER1 et ont une longueur de quatre octets (le deuxième octet est l’opérande immédiat et les deux derniers octets sont l’adresse étendue de destination).
  2. Les lignes (le grignotage le plus élevé d’un opcode) spécifient généralement une opération : les instructions de la ligne 0x0 sont principalement des opérations d’addition ; les instructions de la ligne 0x2 sont principalement des opérations de soustraction, et ainsi de suite.

Si nous regardons la ligne 0x1, nous pouvons voir que les colonnes 0x0 et 0x1 sont des instructions RLC et que les colonnes 0x2 à 0x9 sont des instructions ADC. Ainsi, nous pouvons concevoir une ALU qui prend un grignotage en entrée (le grignotage le plus élevé de l’opcode) et le décode en conséquence. Bien que cela fonctionne pour les colonnes 0x2 à 0x9, nous aurions besoin d’une autre approche pour les deux premières colonnes.

C’est pourquoi j’ai fini par écrire deux unités: une ALU qui se concentre sur la plupart des instructions arithmétiques et logiques; et une seconde unité (Unité logique 2, ou LU2) qui effectue d’autres opérations indiquées dans les colonnes 0x0 et 0x1 (toutes les opérations vues sur ces colonnes ne sont pas effectuées par LU2). Les codes d’opération pour ALU et LU2 ont été choisis pour correspondre aux lignes d’opcodes illustrées à la figure 3.

Un autre détail important est que toutes les instructions dans la même colonne et le même groupe ont la même taille en octets, peuvent donc être décodées dans la même section de décodeur.

La conception du décodeur utilise une grande machine à états finis (FSM) qui avance à chaque tick d’horloge. Chaque instruction commence dans la stat CPU_DECOD. C’est là que le décodeur décode réellement les opcodes, prépare les bus et les signaux de support internes, et passe à d’autres états d’exécution. Parmi tous ces états, deux sont largement utilisés par de nombreuses instructions: CPU_OMA et CPU_OMA2. Pouvez-vous deviner pourquoi? Si vous avez dit parce qu’ils sont liés à ALU et LU2, vous avez tout à fait raison!

OMA est l’abréviation de One Memory Access et c’est le dernier état pour toutes les instructions associées à ALU (ADD, ADC, ADDX, ADCX, SUB, SBC, SUBX, SBCX, OR, ORX ET ANDX, XOR, XORX, CP, CPC, TCM, TCMX, TM, TMX et certaines variantes de LD et LDX). D’autre part, CPU_OMA2 est le dernier état pour toutes les instructions liées à LU2 (RLC, INC, DEC, DA, COM, RL, CLR, RRC, SRA, SRL, RR et SWAP).

Maintenant, jetons un coup d’œil à l’intérieur de l’état CPU_DECOD. Reportez-vous à la figure 4.

FIGURE 4. État du code CPU_DÉCOD.

Dans l’état CPU_DECOD, nous pouvons voir que beaucoup d’actions ont lieu. Au début, certaines variables temporaires sont initialisées à une condition par défaut. Notez que NUM_BYTES est très important car il contrôle le nombre d’octets consommés par le décodeur d’instructions. Sa valeur est utilisée dans la dernière partie de cette étape pour incrémenter le PC (compteur de programme), avancer le pointeur de lecture de la file d’attente et décrémenter le nombre d’octets disponibles dans la file d’attente.

Après la section d’initialisation, nous pouvons voir la section de traitement des interruptions. Il est responsable de la détection des interruptions en attente et prépare le PROCESSEUR en conséquence. Je vais aborder cela dans la section suivante.

Le bloc de décodage d’instructions réel vérifie si un mode basse consommation n’est pas actif et également si le mode débogueur est désactivé (OCDCR.DBGMODE = 0). Ou, en mode débogage, une commande de débogage en une seule étape a été émise (OCDCR.DBGMODE =1 et TOC.SINGLE_STEP=1). Il vérifie ensuite les octets disponibles dans la file d’attente et procède au décodage.

Certaines instructions (principalement celles à un octet) sont terminées dans l’état CPU_DECOD, tandis que d’autres ont besoin de plusieurs états jusqu’à ce qu’elles soient complètement terminées.

Notez que certains décodages d’instructions peuvent utiliser plusieurs fonctions et procédures écrites spécialement pour le FPz8:

  • DATAWRITE – Cette procédure prépare les bus pour une opération d’écriture. Il sélectionne si la destination est un SFR interne, un SFR externe ou un emplacement RAM utilisateur.
  • DATAREAD — Il s’agit d’une fonction réciproque pour DATAWRITE. Il est utilisé pour lire une adresse source et choisit automatiquement s’il s’agit d’un SFR interne, d’un SFR externe ou d’un emplacement RAM utilisateur.
  • CONDITIONCODE – Utilisé pour les instructions conditionnelles (telles que JR et JP). Il prend un code de condition de quatre bits, le teste et renvoie le résultat.
  • ADRESSEUR4, ADRESSEUR8 et ADRESSEUR12 — Ces fonctions renvoient une adresse 12 bits à partir d’une source à quatre, huit ou 12 bits. Ils utilisent le contenu du registre RP pour générer l’adresse finale de 12 bits. ADDRESSER8 et ADDRESSER12 vérifient également tout mode d’adressage échappé.
  • ADDITIONNEUR16 – Il s’agit d’un additionneur de 16 bits pour le calcul du décalage d’adresse. Il prend un opérande signé de huit bits, sign l’étend, l’ajoute à l’adresse de 16 bits et renvoie le résultat.
  • ALU et LU2 – Ceux-ci ont été discutés précédemment et effectuent la plupart des opérations arithmétiques et logiques.

Traitement d’interruption

Comme je l’ai déjà dit, eZ8 dispose d’un contrôleur d’interruption vectorisé avec priorité programmable. Au début, je pensais que cette section ne serait pas si difficile car les interruptions ne sont pas une grosse affaire, non? Eh bien, quand j’ai commencé à comprendre comment faire toutes les tâches nécessaires (sauvegarde du contexte, vectorisation, gestion des priorités, etc.), j’ai réalisé que ce serait plus difficile que je ne le pensais. Après quelques heures, j’ai trouvé le design actuel.

Le système d’interruption de FPz8 a fini par être simple. Il a huit entrées (INT0 à INT7); une activation d’interruption globale (bit IRQE situé dans le registre IRQCTL); deux registres pour le réglage des priorités (IRQ0ENH et IRQ0ENL); et un registre pour les indicateurs d’interruption (IRQ0). La conception utilise une chaîne IF imbriquée qui génère une adresse vectorielle lors de la détection d’un événement d’interruption concernant une interruption activée.

La figure 5 montre une vue compressée du système d’interruption. Notez qu’il existe une première instruction IF avec un symbole ATM_COUNTER. Il s’agit d’un compteur simple utilisé par l’instruction ATM (il désactive les interruptions pendant trois cycles d’instructions, permettant des opérations atomiques).

FIGURE 5. Système d’interruption FPz8.

Un dernier commentaire concernant les interruptions: Le registre d’indicateurs d’interruption (IRQ0) échantillonne les entrées d’interruption à chaque front montant de l’horloge système. Il existe également deux variables de tampon (IRQ0_LATCH et OLD_IRQ0) qui stockent l’état actuel et le dernier des indicateurs. Cela permet la détection de bord d’interruption et synchronise également les entrées externes à l’horloge interne (les FPGA ne fonctionnent pas bien avec les signaux internes asynchrones).

Débogueur sur puce

C’est probablement la fonctionnalité la plus cool de ce softcore car elle permet un environnement de développement intégré commercial (E; tels que ZDS-II de Zilog) pour communiquer, programmer et déboguer des logiciels s’exécutant sur le FPz8. Le débogueur sur puce (OCD) est composé d’un UART avec capacité autobaud et d’un processeur de commande qui lui est attaché. L’UART effectue une communication série avec un PC hôte et fournit des commandes et des données à la machine d’état du débogueur qui traite les commandes de débogage (la commande de débogage traitant le FSM est située à l’intérieur de l’état CPU_DECOD).

FIGURE 6. Débogueur sur puce UART (notez le synchroniseur DBG_RX).

Ma conception OCD implémente presque toutes les commandes disponibles sur le matériel réel, à l’exception de celles liées à la mémoire de données (commandes de débogage 0x0C et 0x0D); le compteur d’exécution de lecture (0x3); et la mémoire de programme de lecture CRC (0x0E).

Une chose que je voudrais souligner est que le soin est nécessaire lorsqu’il s’agit de signaux asynchrones à l’intérieur des FPGA. Ma première conception n’a pas tenu compte de cela lors du traitement du signal d’entrée DBG_RX. Le résultat était absolument bizarre. Ma conception avait parfaitement fonctionné en simulation. Je l’ai téléchargé sur un FPGA et j’ai commencé à jouer avec l’interface série de débogage en utilisant un terminal série (ma carte FPGA a un convertisseur série-USB intégré).

À ma grande surprise, alors que la plupart du temps je pouvais envoyer des commandes avec succès et recevoir les résultats attendus, parfois la conception se figeait simplement et cessait de répondre. Une réinitialisation logicielle rendrait les choses à leur bon fonctionnement, mais cela m’intriguait. Que se passait-il ?

Après de nombreux tests et quelques recherches sur Google, j’ai compris que cela était peut-être lié aux bords asynchrones du signal d’entrée série. J’ai ensuite inclus un verrou en cascade pour synchroniser le signal avec mon horloge interne et tous les problèmes ont disparu! C’est un moyen difficile d’apprendre que vous devez toujours synchroniser les signaux externes avant de les introduire dans une logique complexe!

Je dois dire que le débogage et l’affinage du code du débogueur ont été la partie la plus difficile de ce projet; principalement parce qu’il interagit avec tous les autres sous-systèmes, y compris les bus, le décodeur et la file d’attente d’instructions.

Synthétiser et tester

Une fois entièrement compilé (j’ai utilisé Quartus II v9.1 sp2), le cœur FPz8 a utilisé 4 900 éléments logiques, 523 registres, 147 456 bits de mémoire sur puce et un multiplicateur de neuf bits intégré. Globalement, la FPz8 utilise 80% des ressources disponibles de l’EP4CE6. Bien que ce soit beaucoup, il y a encore quelque 1 200 éléments logiques disponibles pour les périphériques (ma simple minuterie 16 bits ajoute environ 120 éléments logiques et 61 registres). Il s’adapte même sur le plus petit FPGA Cyclone IV – l’EP4CE6 – qui est celui monté sur la mini carte low cost que j’ai utilisée ici (Figure 7).

FIGURE 7. Mini carte Altera Cyclone IV EP4CE6.

La mini carte comprend (avec le périphérique EP4CE6): une mémoire de configuration série EPCS4 (montée sur la face inférieure); une puce de convertisseur série-USB FTDI ainsi qu’un module oscillateur à cristal de 50 MHz; quelques boutons; LED; et des en-têtes de broches pour accéder aux broches FPGA. Il n’y a pas de blaster USB intégré (pour la programmation FPGA), mais le package que j’ai acheté comprenait également un dongle de programmation externe.

Quant aux tests du monde réel, inutile de dire que le FPz8 n’a pas fonctionné la première fois! Après avoir réfléchi un peu et lu les messages de sortie du compilateur, j’ai compris que c’était probablement un problème de timing. C’est un dilemme très courant lors de la conception avec une logique programmable, mais comme c’était ma deuxième conception de FPGA, je n’y ai pas prêté assez d’attention.

En vérifiant les messages d’analyse de synchronisation, j’ai pu voir un avertissement indiquant que l’horloge maximale devrait être d’environ 24 MHz. Au début, j’ai essayé d’utiliser un diviseur par 2 pour générer une horloge CPU de 25 MHz, mais ce n’était pas fiable. J’ai ensuite utilisé un diviseur par 3. Tout a commencé à fonctionner parfaitement!

C’est pourquoi FPz8 fonctionne actuellement à 16,666 MHz. Il est possible d’atteindre des vitesses plus élevées en utilisant l’une des PLL internes pour multiplier / diviser l’horloge principale afin d’obtenir une horloge résultante inférieure à 24 MHz, mais supérieure à 16,666 MHz.

Programmation et débogage

L’utilisation du FPz8 est très simple et directe. Une fois la conception téléchargée sur le FPGA, le PROCESSEUR commencera à exécuter n’importe quel programme chargé en mémoire. Vous pouvez fournir un fichier hexadécimal et utiliser le gestionnaire de plug-ins MegaWizard pour modifier le fichier d’initialisation de la mémoire du programme. De cette façon, votre code d’application commencera à s’exécuter après un signal de réinitialisation.

Vous pouvez utiliser l’E Zilog ZDS-II pour écrire du code Assembleur ou C et générer les fichiers hexadécimaux nécessaires (je sélectionne généralement le Z8F1622 comme périphérique cible car il dispose également de 2 Ko de RAM et de 16 Ko de mémoire programme). Grâce au débogueur sur puce, il est également possible d’utiliser l’E ZDS-II pour télécharger du code sur le FPz8 à l’aide d’une connexion de débogage série (USB, dans notre cas).

Avant de vous connecter, assurez-vous que les paramètres du débogueur sont les mêmes que sur la figure 8. Décochez l’option « Utiliser l’effacement de la page avant de clignoter » et sélectionnez « SerialSmartCable » comme outil de débogage actuel. N’oubliez pas de vérifier également si le port COM virtuel du FTDI est correctement sélectionné comme port de débogage (utilisez le bouton Setup). Vous pouvez également définir la vitesse de communication souhaitée; 115 200 bps fonctionne très bien pour moi.

FIGURE 8. Paramètres du débogueur.

Notez que lors de la connexion au FPz8, l’EDI ZDS-II affichera un message d’avertissement vous informant que le périphérique cible n’est pas le même que le projet. Cela se produit parce que je n’ai pas implémenté certaines zones de mémoire d’identification. Ignorez simplement l’avertissement et poursuivez la session de débogage.

Une fois le code téléchargé avec succès, vous pouvez démarrer l’application (bouton GO), suivre les instructions, inspecter ou modifier les registres, définir les points d’arrêt, etc. Comme avec tout autre bon débogueur, vous pouvez, par exemple, sélectionner le registre PAOUT (sous groupe de PORTS) et même modifier l’état des LED connectées à PAOUT.

Quelques exemples de code C simples peuvent être trouvés dans les téléchargements.

Gardez simplement à l’esprit que le FPz8 a une mémoire de programme volatile. Ainsi, tout programme téléchargé sur celui-ci est perdu lorsque le FPGA est mis hors tension.

Fermeture

Ce projet m’a pris quelques semaines à terminer, mais c’était agréable de rechercher et de concevoir un cœur de microcontrôleur.

J’espère que ce projet pourra être utile à tous ceux qui souhaitent en apprendre davantage sur les bases de l’informatique, les microcontrôleurs, la programmation embarquée et / ou le VHDL. Je crois que — s’il est associé à une carte FPGA à faible coût – le FPz8 peut fournir un outil d’apprentissage (et d’enseignement) fantastique. Amuse-toi bien! NV

CEFET-PR:
www.utfpr.edu.br
ScTec:
www.sctec.com.br
HCS08 Déchaîné:
https://www.amazon.com/HCS08-Unleashed-Designers-Guide-Microcontrollers/dp/1419685929
Manuel du processeur Zilog eZ8 (UM0128):
www.zilog.com/docs/UM0128.pdf
Zilog Z8F64xx Product Specification (PS0199):
www.zilog.com/docs/z8encore/PS0199.pdf
Zilog ZDS II IDE User Manual (UM0130):
www.zilog.com/docs/devtools/UM0130.pdf
Zilog ZDS-II Software Download:
https://www.zilog.com/index.php?option=com_zcm&task=view&soft_id=7&Itemid=74
Zilog Microcontroller Product Line:
http://zilog.com/index.php?option=com_product&task=product&businessLine=1&id=2&parent_id=2&Itemid=56
Project Files available at:
https://github.com/fabiopjve/VHDL/tree/master/FPz8
FPz8 at Opencores.org:
http://opencores.org/project,fpz8

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.