Systéme Z80 complet avec un Nano

Voici quelques temps, j'ai créé un projet à base d'un Arduino Mega et d'un CPU Z80. Ce projet n'avais en soit vraiment rien de complexe, ayant trouvé plusieurs tuto sur le sujet.

Apres réflexion, je me suis dit qu'il été possible de créer un système complet et fonctionnel basé non pas avec un Arduino Mega, mais avec le modèle Nano, mais également avec un minimum de composant et pour un cout moindre.

Pourquoi utiliser un CPU Z80 ?
• J'ai ai plusieurs en stock
• Il est facile de s'en procurer (occasion ou neuf)
• Pour du prototypage, je trouve que le format DIP est bien plus simple à utiliser.
• Ces CPU étant en 5V il est facile de les brancher sur un Arduino
• Ce CPU n'a pas besoin d'une horloge stable pour fonctionner.

De quoi doit être composé au minimum un système Z80 pour être fonctionnel ?
• 1 CPU Z80
• 1 ROM
• 1 RAM
• 1 alimentation
• 1 Signal d'horloge
• 1 ROM possédant le programme a utilisé
• 1 Décodeur de mémoire pour basculer entre ROM et RAM.
• 1 interface d'entrée sortie avec tous les composants que cela nécessite.

Dans ce projet nous allons remplacer la plus part de ces composants par un Arduino Nano.

Les rôles attribués à Arduino:
• Fournir une alimentation stabilisée à 5V
• signal d'horloge
• Virtualise les entrées sortie
• Emulation de la ROM en écrivant le programme directement en RAM
• Réinitialise le CPU

Problèmes à surmonter:
• Le Z80 possède 40 Pins, l'Arduino nano ne possède que 22 entrées-sortie.
• Les ports TX et RX seront utilisés comme interface d'entrées-sortie (écran et clavier du Z80)
• Le port PC6 de l'arduino (Reset) ne pourra pas être utilisé. (Il est possible d'activer ce port comme une entrée-sortie classique, mais cette opération compliquerait la mise à jour de la mémoire flash de l’Arduino)
• Nous ne possédons donc que 18 entrées-sorties possibles pour notre projet.
• L'arduino ne possédant pas assez de broche pour être relié à l'arduino, il faut ruser.
• Apres étude du datasheet de l’Arduino, le seul port complet de 8 bits utilisable est le PORT_D. En raison de son l’utilisation par les ports RX et TX, aucun port de 8 bits n’est disponible. Cela va nécessiter un peu de gymnastique sur les pins entrées-sorties.

Matériel nécessaire pour notre projet Arduino-Z80:
• une breadborad
• un arduino (nano ou uno)
• un CPU Z80 5V (peu importe la fréquence nous ne pourrons pas dépasser le 2 Mhz)
• une 60aine de fils

Détails des broches du Z80.
• 1 broche VCC (+Volt)
• 1 broche pour Masse
• 8 broches pour les Données (D0-D7)
• 16 broches pour l'adressage (A00-A15)
• 1 broche pour le signal d'horloge
• 1 broche pour le reset. (RST)
• 1 broche pour signaler une opération en mémoire (MREQ)
• 1 broche pour signaler une opération sur un périphérique (IORQ)
• 1 broche pour signaler une opération en lecture (WR)
• 1 broche pour signaler une opération en écriture (RD)
• 2 broches liées aux interruptions (INT et NMI)
• 2 broches liées aux demandes de passage en haute impédances (BUSRQ et BUSAK)
• 1 broche liée à l'état du cycle en cours (MI)
• 1 broche de demande de pause pour le CPU (WAIT)
• 1 broche pour signaler que le CPU est en attente d'une interruption (HALT)
• 1 broche de demande de rafraichissement mémoire (RFSH)

Fonctionnement du Z80:
Je ne vais pas vous expliquer en détail le fonctionnement de ce CPU, mais seulement de façon simplifiée, pour plus d'information, je vous conseille de consulter la documentation fournie par Zilog.
• A chaque x cycle d'horloge, le cpu incrémente la valeur du bus d'adressage (A0 à A15)
• Il lit la valeur sur le bus de données (D0 à D7)
• Il exécute l'information liée à la valeur lue dans le bus de données (opcode) qui peut être soit:

a.	modification d'un registre (LD, INc , DEC, JP, CALL, RLC ...)
b.	Lire une données en mémoire et la charge dans un registre (ld (xx),a ...) 
	Active le port MREQ
	Positionne le bus d'adresse sur la case mémoire à lire
	Active le port RD
	Lit la valeur sur le bus de données
	Désactive le port RD
	Désactive le port MREQ
c.	Ecrire la valeur d’un registre en mémoire (ld xx,(a)
	Active le port MREQ
	Positionne le bus d'adresse sur la case mémoire à écrire.
	Active le port WR
	Ecrit la valeur sur le bus de données
	Désactive le port WR
	Désactive le port MREQ
d.	Lire une donnée sur une périphérique (in (x),r ...)
	Active le port IORQ
	Positionne le bus d'adresse sur la mémoire à lire
	Active le port RD
	Lit la valeur sur le bus de données
	Désactive le port RD
	Désactive le port IORQ
e.	Ecrire une valeur sur un périphérique (out (x),r ...)
	Active le port IORQ
	Positionne le bus d'adresse sur la mémoire à lire
	Active le port WR
	Ecrit la valeur sur le bus de données
	Désactive le port WR
	Désactive le port IORQ
f.	Ne rien faire (nop)
  • JP , CALL modifie le registre SP
  • Attention les ports RD, WR, MREQ, IORQ sont actif en signal bas (0 volts)

Branchement du Z80 avec l'Arduino
• Le CPU Z80 est connecté avec la RAM de façon classique, la seule différence c'est le port Chips Enable (CE) de la mémoire qui n'est pas connecté avec le Z80, mais sur l'Arduino.
• Les ports non utilisé du Z80 sont connectés au +5 Volts (INT, NMI, WAIT, BUSRQ)
• Les ports CLK , RESET et IORQ son connecté à l'Arduino
• Seuls les ports 0 et 1 du bus d'adressage du Z80 est connecté à l'ARDUINO (décodage des IO ports 0 à 3), il servira qu’au décodage des demandes I/O.
• Le bus de données du Z80 est connecté à l'arduino.

Nous allons donc n'utiliser que 14 I/O pin sur l'arduino.

Un seul port du BUS d'adressage est connecté, comment est-il possible de transmettre des données ?
En synchronisant exactement les cycles d'horloges avec les valeurs du bus de données, il est possible de passer quelques commandes au Z80

Principe de fonctionnement du notre système à base d’un Arduino et d’un CPU Z80:
Chargement en RAM
 On désactive le module de RAM (CE)
 on active les ports connecté au bus de données en sortie
 on charge une valeur dans le registre HL (ld hl,xx)
 on charge une valeur dans le registre A (ld a,x)
 on demande au Z80 d'écrire la valeur A à l'adresse HL (ld (hl),a)
 on désactive les ports connecté au bus de données, juste avant l’écriture en mémoire.
 on active le module de RAM, le bus d’adressage de la RAM étant connecté au Z80, l’adresse présentée est bien HL
 le Z80 écrit la donnée voulue en RAM
 on désactive le module de RAM
 on réactive les ports connecté au bus de données en sortie
 on incrémente HL
 on recommence jusqu'au chargement complet du programme stocké sur l'ARDUINO en RAM
RUN
 Le programme Arduino est simple, il transmet des cycles d'horloge en continu tant qu'il ne reçoit pas de signal IORQ
 Le signal IORQ est traité, puis l'arduino transmet à nouveau ses cycles d'horloge.

Evolution possible :
• Ce montage peut être utilisé pour l'écriture de mémoire flash ou eprom sans ajout d’autres composants.
• L'avantage de ce montage c'est qu’il laisse suffisamment de ports IO disponible sur l'Arduino, pour installer un lecteur de carte SD. Le chargement du code en RAM pourrait être effectué par cette carte SD
• Un autre usage des pins libre serait l’utilisation de divers périphériques (jouer des sons, une extension de mémoire, ajout de port IO supplémentaires ….) le tout pilotable directement en basic depuis le Z80.
• Il serait également possible en gérant efficacement le port Série d’Arduino (Serial.Begin & Serial.End) d’avoir 2 pins de libre supplémentaires. De plus n’utiliser qu’un seul port (PORTD) pour la lecture et l’écriture des données, améliorerait considérablement les performances d’entrée sorties.
• Actuellement, l’horloge reliée au Z80 tourne à environ 2.15 Mhz, j’ai réussi grâce au timer interrupt à la faire tourner à 8Mhz sur mon CPU de 20Mhz, mais cela pose des problèmes avec la gestion des IO. Je n’arrive pas à trapper assez rapidement les requêtes IORQ, cela engendre des pertes de paquets. Si qq à la solution, je suis preneur.

Bonus :
Afin de tester que votre montage est correctement relié, je vous rajoute deux fichiers :
• io.hex : fichier gérant les entrées sorties du Z80 vers arduino
• basic.hex : fichier issu de « NASCOM ROM BASIC Ver 4.7, (C) 1978 Microsoft *»

  • la documentation liée au basic peut être consulté ici :
    http://www.nascomhomepage.com/pdf/Basic.pdf
    J’ai ajouté quelques fonctions à ce BASIC :
    • PEN
    • PAPER

  • le terminal série d’Arduino ne prenant pas en charge la couleur, je vous conseille d’utiliser Putty ou mobaxterm. L’utilisation avec le terminal d’Arduino est possible, mais les caractères d’échappement liés à la couleur seront afficher, rendant la lecture parfois difficile.

Voici les fichiers joints

boot.cpp (538 Bytes)

basic.cpp (49.3 KB)

Z80.ino (10.4 KB)

très beau projet Thierry.

je suis tombé par hasard sur ce Topic.( je viens de m inscrire récemment sur ce forum);

j avais réalisé il y a bien longtemps une carte a base d 'un Z80.

petite carte automate, 8 entrées et 8 sorties...

une Eprom 2716 et une rame (j ai oublié son appellation);

Programmé en assembleur , et utilisant le livre de Rodney ZACk, ainsi qu un programmateur d 'Eprom carte d application du ZX 81...

Que de souvenirs...!!!...

bonne réalisation à vous.

au plaisir de vous suivre .

cordialement.

philippe