[Z80] Un testeur de Z80 programmable utilisant un PIC18F

Placez ici vos trucs et astuces, étalez sans retenue votre savoir-faire et votre science qui va nous permettre de redonner une apparence neuve et fonctionnelle à nos bouzes.

Modérateurs : Papy.G, fneck, Carl

Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

[Z80] Un testeur de Z80 programmable utilisant un PIC18F

Message par hlide »

Je suis en train d'étudier un projet sur la base d'un existant "2-chip Z80" appelé EMUZ80 par son auteur japonais. C'est une carte qui permet à un Z80 d'accéder à une SRAM et à une ROM émulées par le PIC18F en question. Et la ROM en question contient un TinyBASIC en 8 Ko.
me1PTvt9.jpg
me1PTvt9.jpg (391.02 Kio) Consulté 1297 fois
Je suis en contact avec l'auteur et il devrait me fournir une carte pour que je puisse faire mes dents dessus et améliorer la partie software. En effet, mon intention est de refaire le software sans l'utilisation d'interruption qui grève les performances car actuellement le Z80 ne peut tourner qu'à 2,5 MHz avec pas loin de 7 cycles d'insertion /WAIT = 0. La solution sans interruption que je lui ai proposée offre de bien meilleure performance (entre 0 et 2 cycles d'insertion /WAIT = 0 selon la nature de l'accès mémoire) mais reste encore perfectible pour être stable. Il faut dire que c'est la première fois que je code du PIC et il n'y a que l'expérimentation pour devenir un expert.

Voici le schéma :
FL3MsNBaIAEdlpD.png
FL3MsNBaIAEdlpD.png (52.79 Kio) Consulté 1297 fois
L'auteur a fait quelque choix que je pense discutable. Il utilise par exemple /RFSH dans sa génération du /WAIT mais j'aurais préféré qu'il utilise /RD et /WR en plaçant ce dernier à la place du /RFSH et pouvoir inclure /IORQ et pas seulement /MREQ même si dans son cas, ça lui est suffisant. Bon, j'en dis trop parce que l'objet ce n'est son projet, ce que j'aimerais faire comme projet à la suite de ça.

Je souhaiterais m'en inspirer avec une version du PIC18F offrant plus de broches :
- la possibilité de monter un piano pour choisir un programme de test au démarrage. Voir un deuxième piano pour un paramétrage spécifique à chaque programme.
- la possibilité de piloter une LED RGB qui pourra offrir alors jusqu'à 8 couleurs (voire 8x8 par le biais d'un transition entre deux couleurs toutes les 500 ms par exemple - en sachant que la led non allumée sera considérée comme "noir") pour encoder des états à signaler.
- et peut-être d'autre choses encore que vous pourriez m'indiquer si le projet vous intéresse autant.

Je commence à maîtriser la programmation de cette bête.

Bon comment on synchronise le Z80 avec le PIC18F ? en utilisant un CLC (voir plusieurs). "C'est quoi ça ?". Un "Configurable Logic Cell". Voici ce que j'envisage pour générer un /WAIT = 0 dès une tentative d'accès de mémoire ou I/O :
PZGRdZmF.jpg
PZGRdZmF.jpg (176.83 Kio) Consulté 1297 fois
J'ai programmé le CLC1 (on peut en avoir jusqu'à 8 que l'on peut enchaîner !) pour être un D-FF qui sort un /WAIT = 0 si jamais j'ai D = (/MREQ == 0 ou /IORQ == 0) quand CLK = (/RD == 0 ou /WR == 0) passe à 1. Dans le programme, on attend que sa valeur passe à 0 puis on traite la demande. Une fois la demande traitée on bascule S à 1 pour remettre /WAIT à 1 puis on revient recommence le cycle d'attente/traitement.

Donc un programme de test va avoir un handler qui aura son propre cycle d'attente/traitement :
1) Un test du NOP sur une fréquence donnée programmée par le second piano par exemple : on poll jusqu'à ce que /WAIT == 0; on vérifie que /M1 == 0; on sort un $00 sur le bus de donnée; on relève /WAIT à 1; on attend que /M1 repasse à 1 (ça veut dire que le Z80 a fetch-é le NOP et en passe de l'exécuter) puis on revient sur le poll. Utiliser la LED RGB pour indiquer le status succès/échec sur /M1 qui ne repasse jamais à 0 au delà de 4 cycles.
2) Avoir le même test mais un augmentant graduellement la fréquence par pallier. La LED RGB indiquant par une couleur la fréquence maximale obtenue (exemple: bleu = 1 MHz, vert = 2 MHz, jaune = 4 MHz, ...). A noter que le PIC18F peut générer jusqu'à 32 MHz (lui-même tourne à 64 MHz) mais qu'il ne faudra pas trop compter pour aller jusqu'à ces fréquences (le déclenchement de /WAIT = 0 par le CLC1 peut être soumis à des limites de timings limitant la fréquence du Z80).
3) Un test de détection NMOS/CMOS : on lui présente l'instruction non officielle OUT(C),0 au lieu d'un NOP et quand ce dernier nous donne la valeur dans son bus de donnée suite à un /IORQ = 0, on vérifie qu'il est à $00 (NMOS) ou $FF (CMOS).

On peut simuler de la SRAM et de la ROM au travers le PIC18F comme c'est le cas du projet original.

Il faut noter que pour les tests de fréquence, l'important ce n'est pas le nombre d'insertion /WAIT = 0 mais que l'on peut atteindre des fréquences assez hautes même si cela engendre plus d'insertions tant que le Z80 est en mesure de répondre à cette fréquence.

La force de ce PIC18F, c'est que l'on programmer des portes logiques ou des D, D-FF, SR, etc. dans 8 CLC sans devoir avoir recours à des 74xx sur le PCB.

A noter que l'on peut ajouter des LED autour de certaines broches (D0-7, A0-A15, /M1, etc.) pour avoir un visuel sur des fréquences plus basses.

Est-ce qu'un tel projet vous inspire ? si vous avez des suggestions ou des envies d'y participer, faites part.
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Z80] Un testeur de Z80 programmable utilisant un PIC18F

Message par hlide »

Je devrais recevoir la carte sous huit jours pour pouvoir développer dessus en autonome.
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Z80] Un testeur de Z80 programmable utilisant un PIC18F

Message par hlide »

Bon j'ai pu faire joujou avec et tester plusieurs solutions :

1) La version originale utilisait deux interruptions codées en C. L'une vient au front descendant de la sortie d'un CLC1 en mode D-FF connectée à l'entrée /WAIT du Z80. Le relâchement du /WAIT se fait par une pulsion sur le R (la sortie Q étant inversée). L'autre interruption est déclenchée au front montant de /RD (car il faut remettre le port du PIC représentant le bus D0..7 en input). Le nombre d'insertion de Tw était énorme et limitait la fréquence fournie au Z80 à 2.5 MHz au plus.

2) Une version sans interruption que j'ai écrite avec de l'insertion assembleur stratégique car le compilateur n'est pas aussi "smart" que ça. En gardant le CLC1 sans le déclenchement de l'interruption et en me débarrassant de l'autre interruption. Je peux quasiment doubler la fréquence de fonctionnement du Z80. Je ne suis pas seul à développer car une autre personne a la même idée. L'auteur original a effectué des benchmarks et je détiens le premier record en performance en réduisant par deux le temps.

3) Les CLC me fascinent alors je décide de les utiliser pour s'occuper du décodage d'adresse et je rajoute 4 CLC supplémentaires pour détecter : un accès en ROM, un accès en RAM, un accès UART et enfin un accès lecture ou écriture. Je récupère alors un bitmap des sorties des CLC depuis CLCDATA que je me sers comme un index d'une table de saut. En fait, tout la boucle de traitement de la requête mémoire est écrite en assembleur pour une exécution optimale que ne permet pas le C. Cette version me fait battre un second record en performance mais qui me fait dire que j'ai probablement atteint un mur infranchissable.

4) Dans la version (3), je dois faire un "polling" actif pour détecter un /WAIT = 0 et chaque itération prend 187,5 ns. J'aimerais le réduire à une instruction de 62,5 ns. En effet, le PIC dispose de l'instruction SLEEP paramétrable qui peut effectuer la reprise même sur une interruption signalée mais non exécutée en gardant GIE = 0 (équivalent du DI en Z80). Mais même dans son paramétrage "fatest wake-up", le réveil sur une interruption /WAIT 1->0 engendre plus de cycles que la version (3). Version abandonnée car très déçu du résultat alors que la documentation laissait entrevoir quelque chose de meilleur si on utilise les bons paramètres.

5) Une version avec le mode DOZE (mode qui ralentit l'exécution de l'instruction) pour 1:256 (sur 256 cycles, on en exécute un seul). L'idée est qu'en activant ce mode, l'instruction suivante ne sera pas exécutée avant un bon moment. On a alors suffisamment de temps pour qu'un /WAIT 1->0 la fasse sortir de sa léthargie et répondre à la requête de mémoire du Z80 en full-speed. Problème, ça ne semble fonctionner que si une interruption est réellement exécutée (GIE = 1), ce qui n'est pas avantageux du tout. Version abandonnée.

6) Une version EN COURS avec interruption sur la base de la version (3). J'ai des temps bien meilleurs que ceux de (1) mais ce n'est pas stable. J'ai encore du mal à en comprendre les raisons.

A côté de ça, j'aurais la volonté de rajouter une SRAM (ou une FRAM) pour faire en sorte que le Z80 ait un accès direct à sa "ROM" et à sa "RAM" :
1) Phase BOOT : le PIC s'arrange pour transférer la ROM vers la SRAM via une séquence du type [LD HL,0000 : N * [LD (HL),nn : INC HL]]. L'accès lecture mémoire sera interceptée par le PIC comme un OPCODE FETCH en produisant l'octet de la séquence quelque soit l'adresse demandée puis un RESET à la fin de la séquence de copie pour prépare la deuxième phase. L'écriture activera la SRAM.
2) Phase NORMAL : le PIC reconfigure ses CLC pour qu'un accès lecture/écriture mémoire (/MREQ=0 et /RFSH=1) active la SRAM et qu'un accès port E/S (/IORQ=0) soit traité par le PIC.

La raison de la SRAM est que le Z80 est très impacté par le /WAIT=0 en accès mémoire car on parle d'une exécution effective de l'ordre de 500 KHz avec une fréquence de 4 MHz. Avec une SRAM sans glue externe (merci PIC18F) en troisième IC, on aurait alors une fréquence effective de 4 MHz pour une fréquence de 4 MHz fournie par le PIC et voir une possible montée de la fréquence limite que fourni le PIC (au delà d'une certaine fréquence, le PIC a du mal à répondre de façon stable).
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Z80] Un testeur de Z80 programmable utilisant un PIC18F

Message par hlide »

Voici un exemple des signaux du Z80@4.2MHz avec la version (3) à quelques opcodes après un RESET. Comme le signal jaune /M1 n'est connecté à rien sur le Z80 (oubli de l'auteur de la carte originale), je m'en sers pour la mise au point. Ici je fais une pulsion d'une instruction juste après que la routine sort de la boucle de détection /WAIT=0. Vous comprenez pourquoi je fondais mes espoirs sur l'instruction SLEEP...

Note: il faut retrancher 62,5 ns aux mesures car il faut prendre en compte la latence d'exécution de l'instruction qui crée l'impulsion.
jCxOG3Mw.png
jCxOG3Mw.png (359.03 Kio) Consulté 1090 fois
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Z80] Un testeur de Z80 programmable utilisant un PIC18F

Message par hlide »

Enfin, je suis parvenu à faire la version avec interruption et les performances ne sont pas mauvaises du tout. Là où c'est le plus intéressant, c'est qu'avec cette version, on peut transformer le PIC18F en coprocesseur I/O qui pourra faire des tâches en fond, utiliser la RAM qui lui reste pour faire du cache ou du FIFO, utiliser la DMA, etc. et quand même pouvoir répondre à une requête du Z80 immédiatement. Ce qui n'était pas la cas pour la version sans interruption.

Le source est à cet endroit :
https://github.com/hlide/emuz80-hlide/t ... Cinterrupt
Avatar de l’utilisateur
6502man
Messages : 12286
Inscription : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: [Z80] Un testeur de Z80 programmable utilisant un PIC18F

Message par 6502man »

Sympa l'utilisation du PIC18F pour piloter le Z80 :D

C'est marrant de voir le nombre de projet autour des 8bits utilisant des composants modernes :wink:

Et la façon de chacun de trouver une solution à une problématique donné avec des composants différents :D
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Z80] Un testeur de Z80 programmable utilisant un PIC18F

Message par hlide »

@6502man

Moi c'est en regardant sans grande conviction le source main.c où j'ai été surpris de la simplicité. C'est là aussi que j'ai réalisé que le PIC18F avec des fonctionnalités que je n'ai jamais trouvé sur un AVR. Je me suis mis à imaginer des solutions à base de carte SD qui ne demanderait pas du CPLD ou autres glues à côté et que l'on pourrait brancher sur le socle d'un Z80 ou sur le bus d'extension. Bon je suis un peu revenu de ça, car je pense qu'il faudrait une ROM (ou RAM selon la perspective) pour ne pas pénaliser les performances Z80 mais le PIC18F est parfaitement capable de jouer le rôle d'un CPLD pour le décodage d'adresse. Et le PIC18F a déjà une libraire SdFat. C'est assez tentant.
Répondre