LXESP32






Antonio Giuliana, 2025
2
Questo documento rappresenta la prima parte (di tre) della descrizione dell’implementazione
della scheda LXESP32, realizzata a partire da un modulo ESP32 di basso costo e facile
reperibilità, nell’ambito della replica del sistema NEZ80 da me realizzata sulla base di quello
originale. In questa parte sarà descritto tale replica su cui si basa tutto il lavoro relativo alla
LXESP32, come è stato pensato e realizzato e il suo funzionamento di base.
L’idea di partenza, che si è sviluppata strada facendo, era di poter utilizzare il modulo ESP32
collegato ad una SDCARD come device di storage per file e programmi del NEZ80. Tuttavia,
questo tipo di utilizzo rendeva necessarie delle modifiche sostanziali al firmware e al software
del NEZ80, dalle EPROM al BASIC 16K, dal NE-DOS a tutto il software che gestisse file.
Durante lo sviluppo il progetto è quindi cambiato affinché il device si comportasse nel modo
più trasparente possibile emulando i chip di controllo delle varie schede disponibili.
In pratica cè stato reso possibile grazie al firmware appositamente scritto e implementato
nell’ESP32 per emulare la scheda per la gestione tape LX385 e il suo chip CDP1854, la scheda
per la gestione printer LX389 e i suoi integrati per l’I/O e la scheda per la gestione floppy disk
LX390 e il suo chip FD1771. Inoltre è stata implementata l’emulazione della scheda per la
generazione interrupt LX547 utilizzabile dal NE-DOS. Altre funzionalità estese sono state
implementate, fino ad un collegamento con wifi per sincronizzare data e ora con Internet.
In una prossima versione potrà essere gestita anche la scheda per hard disk LX683.
3
Il sistema attuale
Il progetto della scheda LXESP32 si innesta sul sistema esistente che da tempo ho realizzato
(e che è in continuo sviluppo) per replicare il NEZ80 e le sue funzionalità. Prima di discutere
della LXESP32, è utile riassumere le caratteristiche hardware e software di tale sistema.
Componenti del sistema attuale
Il sistema attuale è contenuto fisicamente in un box plastico con coperchio trasparente mobile
(dimensioni 350 x 250 x 150 mm)
che garantisce un supporto a tutto l’hardware utilizzato. In tale box (v. figura in prima pagina)
ho installato una presa per un cordone di rete IEC munita di interruttore luminoso per garantire
l’alimentazione a 220 V. All’interno ho sistemato il circuito stampato dell’alimentatore e il
circuito stampato del Bus con i connettori che ospitano le schede del NEZ80. Le dimensioni
della scheda Bus e delle schede del NEZ80 sono state ridotte per adattarle al contenitore e per
rendere il sistema più semplice da trasportare.
Alimentatore
L’alimentatore, che ho denominato LX000, non è particolarmente elaborato e ho preferito
mantenerlo compatto e semplice piuttosto che complicarne lo schema e la realizzazione pratica
con molti componenti. Il suo schema è il seguente
4
con il relativo circuito stampato (non nelle dimensioni reali, realizzato a partire dal progetto
elaborato su KiCad e da un costruttore cinese molto efficiente)
Il circuito si basa su due moduli già pronti e montati su circuito stampato che accettano
direttamente la tensione alternata a 220V e forniscono le tensioni continue necessarie in uscita.
Tutto il resto del circuito è costituito da condensatori di filtro e connettori per il collegamento
alla presa IEC da una parte e al Bus dall’altra. I moduli utilizzati sono
- IRM-20-5 della MeanWell da 20W che fornisce +5V max. 4A
(https://www.meanwellusa.com/webapp/product/search.aspx?prod=IRM-20)
- RAC20-12DK della RECOM da 20 W che assicura +12V/-12V max. 800 mA per
ramo (https://www.mouser.it/datasheet/2/468/RAC20_K-1661844.pdf)
Le tensioni a +/-12V non sono utilizzate attualmente dal mio progetto, ma presenti sul Bus per
eventuali estensioni future.
5
Bus
La scheda Bus LX381, è semplice e prevede lo spazio solo per i connettori e i condensatori di
filtro. Le modifiche apportate riguardano
- le dimensioni (è più stretta, per adattarla al contenitore)
- prevede 5 connettori a doppia fila per un contatto più stabile
- non utilizza la corrente alternata a 9V per il contatto S
Il suo schema è il seguente
e il circuito stampato, realizzato come per tutti gli altri, è (non nelle dimensioni reali)
6
che prevede 9 fori per il fissaggio con viti al pavimento del box in maniera stabile.
La stabilità dei contatti dei connettori utilizzati non è il massimo e, a volte, i falsi contatti che
si verificano dopo aver inserito le schede non fanno avviare il sistema o lo bloccano. In futuro
vedrò di ovviare con un sistema di connettori che garantisca maggiore stabilità.
Le CPLD
Prima di esaminare in dettaglio le schede che compongono il sistema, è bene fare una premessa
riguardante la scelta di utilizzare le CPLD (Complex Programmable Logic Device) al posto dei
(tanti) circuiti integrati TTL presenti su ogni scheda.
Questi device sono circuiti integrati con funzioni programmabili, che dispongono di molti pin
di I/O utilizzabili per sostituire intere reti di circuiti TTL collegati tra loro. Sono dispositivi più
semplici delle moderne FPGA ma queste ultime non sono reperibili nella versione funzionante
a 5V e sono disponibili solo in package SMD complessi da saldare. Le FPGA dunque non sono
adatte al mondo hobbystico e soprattutto al collegamento con i dispositivi legacy, quali possono
essere quelli presenti nel sistema Z80 di NE.
Al contrario, esistono CPLD che funzionano a 5V e che sono disponibili in contenitori PLCC
e dunque facilmente utilizzabili per i nostri scopi. È vero che sono device perlopiù obsoleti
(fuori produzione) ma si possono ancora trovare in commercio nel mercato secondario. Sono
facilmente utilizzabili anche grazie a software gratuiti di progettazione di facile apprendimento
e a sistemi di programmazione semplici e poco costosi. Un singolo circuito integrato può
sostituire decine e decine di TTL collegati tra loro e dunque permette un notevole risparmio di
spazio sul circuito stampato.
Esistono alternative utilizzabili di CPLD ancora in produzione di cui tratterò in seguito.
7
La famiglia EPM7000SLC
Le CPLD che ho usato nelle schede che ho riprogettato sono quelle della famiglia
EPM7000SLC prodotte in origine dalla ALTERA, società che dal 2015 non esiste più dato che
è stata acquisita da INTEL. Esistono dunque dei chip marcati ALTERA e altri INTEL,
reperibili sul mercato ma quasi tutti di “seconda mano”. Per questo bisogna fare attenzione che
siano funzionanti (purtroppo ce ne sono tantissimi che non lo sono più e vengono venduti
ugualmente). Questa famiglia mette a disposizione alcuni modelli, con caratteristiche differenti,
tra cui quelli più utilizzati sono nelle seguenti tabelle
In queste è mostrano come i dispositivi siano disponibili in package PLCC da 44 o da 84 pin e
mettano a disposizione un numero diverso di pin di I/O e di capacità di ospitare varie quantità
di elementi logici per l’implementazione del circuito complessivo. La maggior parte delle volte
utilizzerò i dispositivi EPM7064S e EPM7128S in PLCC da 84 pin. Se la necessità di pin lo
richiede, potranno essere usati due dispositivi nella stessa scheda avendo cura di suddividere
logicamente in modo congruo le parti di circuito da realizzare.
Il suffisso S di questi dispositivi indica che possono essere programmati anche molte volte,
tramite una interfaccia JTAG che si collega a specifici pin riservati (denominati TMS, TDI,
TDO, TCK), anche se montati nella scheda in cui dovranno lavorare. Questa caratteristica
renderà semplice l’aggiornamento dell’hardware della scheda, molte volte senza dover
effettuare saldature ma semplicemente riscrivendo il circuito e programmandolo al loro interno.
8
Per quanto riguarda la velocità di questi device, non ci dobbiamo preoccupare in quanto sono
facilmente reperibili con il suffisso -10 o -15, comunque con velocità superiori ai 35-40 MHz,
più che sufficienti per i nostri scopi.
La famiglia ATF15xx
Una alternativa all’uso degli integrati ALTERA/INTEL è la famiglia ATF1xx prodotta in
origine dalla ATMEL, acquisita nel 2016 dalla MICROCHIP (che tuttora mantiene questa linea
in produzione). Queste CPLD sono praticamente compatibili con le EPM700S e in particolare
possiamo vedere nella seguente tabella l’equivalenza tra i modelli delle due famiglie
Modello
ATMEL/MICROCHIP
Equivalente
ALTERA/INTEL
ATF1502AS EPM7032SLC
ATF1504AS EPM7064SLC
ATF1508AS EPM7128SLC
Le CPLD ATF15xxAS hanno alcune caratteristiche migliorative rispetto alle EPM7000SLC,
tuttavia sono equivalenti a queste ultime per quello che serve nel mio progetto. Bisogna fare
attenzione ad utilizzare la versione AS (5V) e non la ASL (3.3V) (non disponibile per le
EPM7000SLC) e che il contenitore usato sia il PLCC. Ad esempio, ho montato e utilizzato con
successo questi due componenti nelle schede del mio sistema, una EPM7064SLC84-10 della
ALTERA e una ATF1504AS-10JU84 della ATMEL
9
Un aspetto positivo della famiglia ATF15xxAS è che è possibile progettare il circuito interno
con lo stesso tool utilizzato per le EPM7000S, a patto di convertire alla fine il file risultato nel
formato adatto alla famiglia ATF15xxAS. Pur essendo l’interfaccia di programmazione (e i
rispettivi quattro pin utilizzati) la medesima per le due famiglie, purtroppo l’hardware e il
software utilizzato per la programmazione delle EPM sono diversi da quelli utilizzati per le
ATF e quindi è necessario munirsi di tutti gli strumenti necessari per le due famiglie. Se ne
parlerà nel paragrafo dedicato alla progettazione/programmazione.
Interfaccia MultiVolt
Una caratteristica di questi componenti, denominata MultiVolt è disponibile per tutte le versioni
tranne che per quelle a 44 pin. Questa funzionalità permette di alimentare il core del device a
5V e i pin di I/O con una alimentazione diversa, ad esempio 3.3V, per poterlo interfacciare a
device che non supportano i 5V. In questo modo si evitano tutti i circuiti di traslazione
dell’alimentazione che si rendono necessari se si devono utilizzare componenti a 3.3V. In
particolare, questa funzionalità sarà utile per collegare la CPU Z80 al modulo ESP32 che
funziona solo a 3.3V.
Quando i pin di I/O sono alimentati a 3.3V, sono comunque tolleranti ai segnali a 5V e quindi
possono essere impiegati sia lato Z80, sia lato ESP32. In questo caso i pin VCCINT saranno
collegati ai 5V (VCC INTernal) mentre i pin VCCIO (con cui sono alimentati i buffer interni
di I/O) sono collegati ai 3.3V, come mostrato nel circuito seguente, adottato nella scheda
LXESP32
10
Naturalmente, se il circuito opera completamente a 5V, tutti i pin VCCINT e VCCIO saranno
alimentati dalla tensione a 5V.
Open Drain
Un’altra funzionalità utile di questi componenti è quella di poter programmare una uscita come
Open Drain, modalità funzionalmente equivalente alla Open Collector, quando il circuito a
valle lo richiede. Molti segnali dello Z80 sono Open Collector, ad esempio quello su cui
arrivano gli interrupt (INT) e con questa caratteristica di questi componenti si evita altro
hardware esterno (buffer appositi o transistor). La definizione di tali uscite si fa via software.
Progettazione e programmazione delle CPLD
Per realizzare i circuiti che verranno programmati nelle CPLD e che sostituiscono, in gran parte,
le reti di TTL presenti sulle schede originali, può essere usato il software gratuito della
ALTERA Quartus II 13.0sp1, compatibile con la famiglia EPM7000SLC (che ricordo essere
obsoleta e dunque non programmabile con versioni più recenti del software).
L’uso di questo tool è intuitivo anche se, ovviamente, prevede una conoscenza minima
dell’elettronica digitale, dei componenti utilizzabili e del linguaggio di programmazione
VHDL (ove utilizzato). In queste pagine non è possibile entrare molto più nel dettaglio, ma
proverò a spiegare i vari circuiti utilizzati nelle CPLD nella descrizione di ogni scheda.
11
Un fattore importante è che tale software può costituire un valido strumento anche per la
famiglia ATF15xxAS in quanto è possibile partire dal progetto e convertire il risultato per tale
famiglia prima della programmazione.
Per programmare i device di entrambe le
famiglie si utilizza un programmatore con
interfaccia JTAG e un collegamento del genere
(ad esempio per la EPM7064SLC84).
Ho scelto un programmatore “compatibile USB Blasterperché ancora compatibile con le
versioni più recenti di Windows, reperibile facilmente su Internet e a basso costo
La programmazione è semplice, ma bisogna seguire questi semplici passi (alcuni da fare una
sola volta)
- installare i driver della USB Blaster sul PC
- collegare l’USB Blaster al computer
- collegare il device al connettore JTAG
- alimentata la scheda
- selezionare il menu Tools->Programmer e scegliere il tipo di programmatore (che
dovrebbe apparire tra quelli disponibili)
- controllare che il device venga rilevato correttamente (Auto Detect), nel caso mostrato
una EPM7128SLC84
12
- scegliere il file da programmare (il file con estensione .pof ottenuto dalla compilazione
del circuito) e spuntare le operazioni di programmazione e verifica
- avviare lo Start della
programmazione e attendere
che la barra di avanzamento
sia completamente verde fino
al 100%.
Programmare le ATF15xx
Se si volessero utilizzare le CPLD della famiglia ATF15xxAS (ad esempio la ATF1504AS al
posto della EPM7064SLC oppure la ATF1508AS al posto della EPM7128SLC), come già
accennato, si può utilizzare sempre il software Quartus II 13sp1 e ottenere il file .pof risultato
della compilazione. A questo punto però, non può essere usato lo stesso software per
programmare il device con il dispositivo USB Blaster ma bisogna seguire i seguenti passi,
fermo restando che il collegamento tra il connettore JTAG sulla scheda e il CPLD rimane
invariato
- da linea di comando, all’interno della cartella in cui è contenuto il file .pof, usare il
software Pof2Jed (scaricabile dal sito INTEL), avendo cura di indicare i parametri
corretti, ad esempio
POF2JED.exe -1504AS -i LX388.pof
per ottenere un file con estensione .jed a partire dal .pof
- usare un programmatore per ATF15xxAS con relativo software (l’USB BLASTER
non va bene). Ho usato un ATDH1150USB della Microchip, non proprio economico
ma affidabile
13
-
Esistono soluzioni di terze parti ma queste sembrano un po’ “improvvisate”, poco versatili,
scomode da usare e, alla fine, non si risparmia poi tanto. Con il programmatore è possibile
utilizzare il programma ATMISP creando un nuovo file e indicando il numero di device da
programmare (normalmente 1), il tipo (esempio ATF1504AS), istruzioni JTAG per
program/verify e il file .jed sorgente appena ottenuto. Questa configurazione può essere salvata
in un file .chn che sarà utilizzabile, con il comando RUN, per far partire l’upload su device e
concludere la programmazione.
L’ATF così ottenuto sarà utilizzabile pin to pin nel circuito come se fosse un EPM.
14
La scheda CPU LX382
La prima scheda da inserire sul Bus del mio sistema è, ovviamente, quella che ospita la CPU
Z80. Lo schema del circuito adottato è il seguente
in cui si possono subito individuare dei blocchi ben specifici, ovvero
a) la CPU Z80, al centro
b) la memoria del sistema, NVRAM, subito sotto
c) i due connettori A e B, che interfacciano il Bus al resto del circuito
d) le due CPLD denominate LX382S e LX382D, rispettivamente a sinistra e a destra della
CPU (indicate come EPM7128SLC ma scambiabili con le EPM7064SLC)
e) un connettore con i componenti utili alla programmazione JTAG delle due CPLD, in
basso a sinistra
f) il modulo oscillatore già pronto per generare la frequenza di clock da 7.68 MHz, subito
sopra
g) il circuito di RESET costituito da un dispositivo apposito che si attiva all’accensione
(DS1233-5+) e un pulsante per il reset manuale
Il circuito stampato (non nelle dimensioni reali) misura 152 x 68.5 mm ed è il seguente
15
Tutti i componenti sono montati su zoccolo e, per la sola memoria NVRAM ho previsto un
TEXTOOL necessario per poter estrarre/programmare/testare il codice durante i test di
funzionamento molto più facilmente che con zoccoli classici. La configurazione dei pin per la
programmazione delle CPLD è a cascata” in modo che, con un solo connettore, i
programmatori possano riconoscere e programmare le due CPLD anche in modo indipendente.
Dopo il montaggio, il CS si presenta così
16
Ho usato la NVRAM (modello DS1245Y della DALLAS, da 128 K x 8 byte, anche se obsoleta
e relativamente costosa) per diversi motivi, tra cui
a) copertura di tutta la memoria indirizzabile dallo Z80 (64 K), senza necessità di
utilizzare schede di memoria aggiuntive sul Bus
b) disponibilità di altri 64 K indirizzabili tramite gestione della linea A16, che permette di
avere più spazio per dati e codice (con una gestione appropriata) e di implementare un
meccanismo di boot che permetta l’avvio al reset a partire da qualsiasi indirizzo del
sistema
c) possibilità che tutta la memoria si comporti nello stesso momento come RAM o ROM,
in quanto mantiene le informazioni anche se non alimentata (contiene una batteria
tampone) e scrivibile come una RAM
d) è facilmente programmabile “fuori” dal sistema tramite programmatori disponibili in
commercio più o meno costosi (ho usato un TL866 II che è utile anche per i PIC)
Il modulo oscillatore, reperibile facilmente in commercio, è alimentato dalla tensione a 5V e
genera la frequenza di 7.68 MHz con la precisione del quarzo direttamente senza altri
componenti. Questa frequenza viene inviata ad una CPLD per la divisione e l’inoltro alla CPU.
Per il circuito di reset ho voluto utilizzare un piccolo componente dedicato (il DS1233-5+) che
fornisce l’impulso corretto all’accensione e gestisce il pulsante per il reset manuale. Il reset
viene reso disponibile sul Bus, alla CPLD e alla CPU.
A parte il LED che indica l’alimentazione della scheda, le resistenze di pull-up per alcuni
segnali che sono in open collector e i due connettori per collegarsi al Bus, tutto il resto dei
circuiti è implementato e programmato nelle CPLD. Ne ho previsto due per poter implementare
anche un sistema di gestione della linea A16 secondo un modello a “banchi”.
17
La gestione della linea A16 e i banchi
È noto che lo spazio di indirizzi gestibili direttamente dallo Z80 va da 0x0000 a 0xFFFF e si
realizza tramite le 16 linee di indirizzamento denominate A0…A15.
La NVRAM (Non Volatile RAM) utilizzata è da 128 K e dunque dispone di una diciassettesima
linea denominata A16; quando questa è a 0, gli indirizzi visibili dallo Z80 saranno nel range
0x0.0000…0x0.FFFF mentre, se A16 è a 1, gli indirizzi saranno nel range
0x1.0000…0x1.FFFF.
Il circuito logico inserito nelle due CPLD ha lo scopo di gestire la linea A16 seguendo alcune
regole che si basano sul contenuto di un registro di I/O che la CPU può scrivere all’indirizzo
0x00 tramite l’istruzione OUT. Questo registro è implementato nella CPLD LX382S.
Al Reset questo registro conterrà il valore binario 11111111 (situazione iniziale) e ogni bit
rappresenterà il valore che viene assegnato alla linea A16 nel momento in cui viene usato un
indirizzo specifico, secondo la seguente tabella
Range indirizzi con
0
Range indirizzi con
valore del bit =
1
Bit 0
0x0.0000…0x0.1FFF
0x1.0000…0x1.1FFF
Bit 1
0x0.2000…0x0.3FFF
0x1.2000…0x1.3FFF
Bit 2
0x0.4000…0x0.5FFF
0x1.4000…0x1.5FFF
Bit 3
0x0.6000…0x0.7FFF
0x1.6000…0x1.7FFF
Bit 4
0x0.8000…0x0.9FFF
0x1.8000…0x1.9FFF
Bit 5
0x0.A000…0x0.BFFF
0x1.A000…0x1.BFFF
Bit 6
0x0.C000…0x0.DFFF
0x1.C000…0x1.DFFF
Bit 7
0x0.E000…0x0.FFFF
0x1.E000…0x1.FFFF
Al Reset dunque, la CPU vedrà la memoria compresa nella seconda parte della memoria (da
64 a 128 K). In questo modo, il codice presente a partire dalla locazione RAM 0x1.0000 verrà
eseguito e questo potrà
1) impostare il registro in modo che solo il primo banco abbia A16=1, per continuare ad
eseguire il codice e predisporre l’accesso alla prima parte della memoria
18
2) preparare del codice per far partire da qualsiasi indirizzo dei primi 64 K il sistema (ad
esempio, da 0x0.F000)
3) resettare il registro 0x00 per rendere visibile il primo blocco di memoria
4) passare all’indirizzo prescelto
Questo semplice meccanismo garantisce un metodo semplice e unificato per il boot in diverse
configurazioni. Ad esempio, per avviare il codice della EP1390 e caricare il NE-DOS, il codice
sarà il seguente
; BOOT per EP1390
10000 DI ; Disabilita interruzioni
10001 LD A,0x01
10003 OUT 0x00,A ; 8K A16=1, 56K A16=0
10005 LD A,0xD3
10007 LD (0xEFFE),A ; Opcode OUT in 0xEFFE
1000A LD A,0x00
1000C LD (0xEFFF),A ; Porta per OUT in 0xEFFF
1000F OUT 0xE7,A ; Azzera pagina video (vedi LX388)
10011 JP 0xEFFE ; Passa a 0xEFFE (A16=0)
;
; da 0x0EFFE viene avviato con A=0
;
; 0xEFFE: D300 OUT 0x00,A ; Tutta la memoria con A16=0
; 0xF000: <START EP1390>
19
La CPLD LX382S
La prima CPLD, a sinistra sul circuito stampato, implementa il circuito mostrato di seguito e
utilizza una EPM7064SLC84 (o in alternativa una ATF1504AS)
Alcuni segnali che hanno origine dalla CPU (M1, RD, WR, IORQ, MREQ, HLT) sono resi
disponibili attraverso dei buffer tristate a seconda del valore del segnale BUSACK (BAC)
generato dalla CPU e vanno verso il connettore A del Bus; il segnale BUSACK, invece,
procede direttamente. Altri segnali che provengono dal Bus (NMI, INT, BUSRQ, WAIT) sono
inviati alla CPU.
I singoli buffer semplici o tristate svolgono le funzioni dei circuiti TTL originali IC14 e IC15.
Il segnale di CLOCK a 7.68 MHz, generato esternamente dal modulo oscillatore, viene portato
ad un blocco dello schema (denominato XCLK) che fa da divisore per 2 e per 4 (in alto nello
schema), il cui circuito equivalente è il seguente
20
Il segnale diviso per 4 risulta alla frequenza di 1.92 MHz, che è quella di funzionamento della
scheda originale di NE. Tuttavia, come si vede dai collegamenti che ho previsto, il segnale di
clock che viene inviato alla CPU (direttamente) e al Bus (tramite buffer tristate) è quello diviso
per 2, ovvero alla frequenza di 3.84 MHz. Ho scelto di far funzionare il sistema alla frequenza
doppia per renderlo un po’ più veloce e “responsive”. Una CPLD è comunque molto versatile
e basta cambiare il collegamento nel progetto, ricompilare e programmare la CPLD per usare
la frequenza originale a 1.92 MHz. Non è necessario l’integrato IC9 per l’oscillatore con il
quarzo del circuito originale.
Altri due blocchi (denominati RBKED e RSBKED) contengono la logica per la gestione del
registro di controllo dei banchi e della generazione della linea A16.
Nel primo blocco è implementato un registro a 8 bit che è possibile leggere e scrivere
decodificando l’indirizzo 0x00 per le linee A0..A7 e usando i segnali M1, IORQ e WR per
accedere in R/W ai dati memorizzati. Al Reset tutti i bit del registro sono settati e il suo valore
diventa 11111111 abilitando il segnale A16 per ogni blocco da 8 K della memoria.
21
Questo meccanismo rende inutili gli integrati IC10 e IC13 dello schema originale.
I dati del registro, presenti su Q[7..0] sono passati al secondo blocco che è realizzato tramite
un codice in linguaggio VHDL (che descrive il comportamento di un circuito)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.ALL;
entity SEL8 is
Port (
CA : IN STD_LOGIC_VECTOR(15 DOWNTO 13);
R8 : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Q : OUT STD_LOGIC
);
end SEL8;
architecture Behavioral of SEL8 is
begin
process (CA, R8)
begin
--- Assign out
Q <= R8(to_integer(unsigned(CA)));
end process;
end Behavioral;
Il circuito equivalente allo script, generato automaticamente dal compilatore, è il seguente
22
In questo caso, la parte dell’indirizzo delle pagine da 8 K (A15..A13) viene utilizzata (tramite
un MUX) per restituire il bit del registro corrispondente alla pagina, assegnandolo alla linea
A16.
La CPLD LX382D
La seconda CPLD, posta a destra nel circuito stampato, è utilizzata, principalmente, alla
corretta decodifica degli indirizzi durante l’accesso alla NVRAM in lettura e scrittura.
A parte la gestione del segnale RFH che dalla CPU raggiunge, tramite buffer tristate, il
connettore A del Bus, il resto del circuito è fatto in modo che
1) la NVRAM sia indirizzata e abilitata in lettura o scrittura quando la CPU accede alla
memoria compresa tra gli indirizzi (A16).0000 e (A16).FDFF; in questo caso il bus
dati e il bus indirizzi sono isolati tramite buffer tristate
2) nel caso in cui venga indirizzata l’area FE00…FFFF, la NVRAM non viene attivata in
alcun modo; in questo caso, le linee degli indirizzi (A0…A15) vengono inviate al
connettore B del Bus cocome i dati (D0…D7) vengono ricevuti o inviati sempre
tramite Bus; quel range verrà usato dalla scheda LX388 (video) per la propria memoria
video
23
In questo modo sarà disponibile, senza interruzioni, tutta la memoria da 0x0000 a 0xFDFF e
l’area 0xEC00..0xEDFF sarà disponibile per dati e programmi. Questo cambiamento rispetto
al progetto originale di NE dovrà essere tenuto in considerazione modificando il codice di
accesso al video nel software di sistema (BASIC, NE-DOS). Per questo motivo ho realizzato
le versioni F di tali software.
Il blocco denominato XDEC contiene la rete logica (descritta con il linguaggio VHDL) che
genera i segnali di abilitazione e scrittura della NVRAM quando necessario.
Il codice tiene conto del valore corrente della parte alta delle linee degli indirizzi (A15..A8), e
dei segnali MREQ, RFH, WR, RD per generare il segnale di abilitazione della NVRAM (CEN)
e della scrittura (MWE). Notare il controllo con il valore FE (minore di) per l’abilitazione della
NVRAM
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ADDR_DEC is
Port (
A : IN STD_LOGIC_VECTOR(15 DOWNTO 8);
MR : IN STD_LOGIC;
RFH : IN STD_LOGIC;
WR : IN STD_LOGIC;
RD : IN STD_LOGIC;
CEN : OUT STD_LOGIC;
MWE : OUT STD_LOGIC
);
end ADDR_DEC;
architecture Behavioral of ADDR_DEC is
begin
process (A, MR, RFH, WR, RD)
begin
--- Disable NVRAM Access
CEN <= '1';
--- Disable NVRAM WE
MWE <= '1';
--- Check Memory Request
if (RFH = '1') then
if (MR = '0') then
if (A < x"FE" AND (RD = '0' OR WR = '0')) then
--- Enable NVRAM Access
CEN <= '0';
24
--- Handle WR Access
MWE <= WR;
end if;
end if;
end if;
end process;
end Behavioral;
Il circuito equivalente allo script, generato automaticamente dal compilatore, è il seguente
Programmazione della NVRAM
La NVRAM (Non Volatile RAM) è una RAM alimentata da una batteria tampone contenuta
nello stesso package del componente. È dunque possibile leggere e scrivere senza che il
contenuto venga perso in assenza di alimentazione. Funziona a 5V e, come già accennato, il
modello utilizzato nel sistema è un DALLAS DS1245Y da 128K x 8.
Naturalmente è necessario che del codice iniziale venga inserito in tale componente per
permettere al sistema di avviarsi e dunque possiamo fare delle scelte.
Per il BASIC da 16 K contenuto in EPROM (schema LX548 ed EPROM da EP548-1 a EP548-
8) non è necessario altro circuito (quello della scheda LX548 non serve) e il contenuto delle
varie EPROM può essere unito in un solo file binario (EP548F.bin) e trasferito con un
programmatore apposito nella NVRAM, a partire dall’indirizzo 0x0000 fino all’indirizzo
0x3FFF. Ricordo che il sistema, per la gestione della linea A16, si avvierà dall’indirizzo
25
0x1.0000 dove sarà inserito del codice (già mostrato per la EP1390) con le modifiche opportune
per avviare il BASIC. Tale codice è
; BOOT per EP548F
10000 DI ; Disabilita interruzioni
10001 LD A,0x01
10003 OUT 0x00,A ; 8K A16=1, 56K A16=0
10005 LD A,0xC3
10007 LD (0xF002),A ; Opcode JP in 0xF002
1000A LD A,0xD3
1000C LD (ATARGET),A ; Opcode OUT in 0xF000
1000F LD A,0x00
10011 LD (ATARGET+3),A ; Parte L indirizzo BASIC in 0xF003
10014 LD (ATARGET+4),A ; Parte H indirizzo BASIC in 0xEFF4
10017 LD (ATARGET+1),A ; Porta per OUT in 0xF001
1001A OUT 0xE7,A ; Azzera pagina video (vedi LX388)
1001C JP 0xF000 ; Passa a 0xF000 (A16=0)
;
; da 0x0F000 viene avviato con A=0
;
; 0xF000: D300 OUT 0x00,A
; 0xF002: C30000 JP 0x0000
; 0x0000: <START EP548F BASIC>
Il contenuto della EP548 (modificato da me in EP548F per poter utilizzare la memoria video
agli indirizzi 0xFE00…0xFFFF) è trasferito da nella NVRAM tramite il programmatore
TL866 II (ma ne esistono di altre marche e modelli), utilizzando l’apposito software Xgpro
Il file trattato dal software del programmatore è un binario (.BIN) generato dall’assemblatore
Z80 utilizzato (ZASM nel mio caso).
26
La scheda video LX388
La seconda scheda da inserire sul Bus del mio sistema è l’interfaccia video testo
monocromatica. Lo schema del circuito adottato è il seguente
in cui esistono i seguenti blocchi
a) il controller video, circuito integrato MC6847, completo di modulo oscillatore al quarzo
dedicato per il clock a 3.579545 MHz, a sinistra
b) il circuito con i due transistor per amplificare il segnale video in uscita, in alto
c) la memoria RAM video modello 6116 (sostituisce le due 2114 originali), al centro
d) la CPLD denominate LX388, con una EPM7064SLC (o anche una ATF1504AS),
visibile a destra
e) il connettore PS/2 collegato al circuito integrato PIC18F628A programmato con il
firmware per gestire la tastiera, al centro in alto
f) i due connettori A e B, che interfacciano il Bus al resto del circuito
g) un connettore con i componenti utili alla programmazione JTAG della CPLD, in basso
al centro
27
Anche in questo caso il modulo oscillatore è alimentato dalla tensione a 5V e genera la
frequenza di 3.579545 MHz con la precisione del quarzo direttamente senza altri componenti.
Questa frequenza viene utilizzata direttamente dal controller CRT, l’integrato MC6847.
Esiste anche in questo caso un LED blu per indicare che la scheda è alimentata e sono presenti
alcuni componenti necessari al PIC per la gestione dell’interfaccia USB; inoltre, sono presenti
i due connettori per collegarsi al Bus e tutto il resto dei circuiti è emulato e programmato nella
CPLD. Il circuito stampato (non riprodotto nelle dimensioni reali), è compatto, misura 152 x
65 mm ed è il seguente
Anche in questo caso, tutti i componenti sono montati su zoccoli classici. La configurazione
dei pin per la programmazione della CPLD è quella consueta.
Dopo il montaggio, il circuito stampato si presenta co (notare che in questa scheda è montata
una CPLD ATF1504AS)
28
La memoria video
Nel circuito originale erano utilizzate due RAM 2114 che mettevano a disposizione una
memoria complessiva di 1 K x 8, anche se la memoria video (mappata in origine agli indirizzi
0xEC00…0xEDFF) occupa 512 byte (32 caratteri per 16 linee). Nella LX388 originale un la
linea di indirizzamento A9 delle RAM non era dunque utilizzata. Come detto in precedenza,
ho modificato il range degli indirizzi della scheda video portandolo a 0xFE00..0xFFFF in
modo da non interrompere la continuità dell’area RAM utilizzabile dal sistema, tramite le
modifiche discusse per la scheda LX382.
Per comodità e per rendere più compatto il circuito stampato (oltre per il fatto che le 2114 sono
meno facilmente reperibili), ho adottato un singolo integrato 6116 che gestisce direttamente
tutti gli 8 bit e mette a disposizione 2 K di memoria. Questa memoria è grande 4 volte quella
necessaria e, per poterla utilizzare tutta, ho implementato il controllo delle linee di indirizzo
A9 e A10 della RAM tramite un registro interno alla CPLD, utilizzabile in lettura/scrittura dalla
CPU all’indirizzo 0xE7.
29
In questo modo, si può utilizzare la memoria video in “pagine”, ovvero, pur restando
accessibile alla CPU sempre nello stesso range di indirizzi, viene sfruttata fisicamente una delle
4 parti della RAM, tramite l’impostazione dei primi 2 bit della porta 0xE7.
In pratica, secondo la seguente tabella
Numero
pagina video
attiva
Valore del
registro 0xE7
Range indirizzi RAM
utilizzato durante l’accesso
a 0xFE00..0xFFFF
0
0x00
(default)
0x000…0x1FF
(default)
1
0x01
0x200…0x3FF
2
0x02
0x400…0x5FF
3
0x03
0x600…0x7FF
è possibile utilizzare fino a 4 pagine video indipendenti in maniera trasparente da come sta
operando il sistema. Questo spiega la linea di codice
OUT 0xE7,A
usata nel codice di avvio del sistema. Scrivendo 0x00 in tale registro, si assicura l’utilizzo della
pagina 0 della memoria video per default. Tale registro può essere modificato con una
istruzione OUT dal BASIC o in assembly e le pagine video liberamente usate per vari scopi.
La gestione della tastiera
Per gestire una tastiera PS/2 ho adottato il circuito di Pino Giaquinto (che ringrazio), nella
versione con il PIC16F628A, anche se ho intenzione di cambiare a breve tale integrato con il
PIC16F648 per usare la nuova versione 3.3.1 del firmware. Il dialogo tra il PIC e lo Z80 viene
effettuato tramite la CPLD.
La CPLD LX388
La CPLD che implementa tutto il circuito dell’interfaccia video è mostrato di seguito e utilizza
una EPM7064SLC84 (o in alternativa una ATF1504AS)
30
Il circuito implementato realizza tutte le parti di quello originale, aggiungendo alcune
funzionalità. In particolare, il registro a due bit in alto a destra, viene scritto con i due bit b1 e
b0 dei dati quando viene indirizzata la porta 0xE7 e memorizza la pagina video attuale che
viene inviata alle linee A9 e A10 della RAM video.
Il segnale CS_MBOARD viene generato quando viene acceduta la memoria video della scheda
video da parte della CPU, con conseguente passaggio dell’indirizzo dal sistema alla RAM
(compito originariamente svolto da IC3 e IC4). Lo stesso segnale gestisce, insieme a RD e WR,
la corretta abilitazione e impostazione della direzione dei dati dalla CPU e verso la CPU
(compito essenzialmente dell’integrato IC11 e della rete di porte che lo controllano).
I bit VDDR[6] e VDDR[7] sono combinati per generare i segnali VINT e VINTAS per il
controller video (vedere IC5D, IC8B e IC2D).
Il segnale IOEAR_KBD permette la lettura dei dati della tastiera, provenienti dal PIC,
attraverso l’accesso alla porta 0xEA (vedere IC12 e reti vicine).
Il segnale IOEBR_RTRC invece, permette di attivare la lettura della linea VFS sul bit 7 dei
dati quando la CPU accede alla porta 0xEB, per conoscere lo stato del retrace video attuale
(vedere IC6B, IC6C, IC8A).
31
Il blocco XIODEC genera i segnali per l’indirizzamento dei vari registri (CSVMEM non è
utilizzato in questa versione), ovvero
Uscita sul blocco Segnale Descrizione
CSIOVP
IOVPW
Seleziona porta 0xE7 per registro banco video
CSKBD
IOEAR_KBD
Seleziona porta 0xEA per lettura dato tastiera da PIC
CSSYNC
IOEBR_RTRC
Seleziona porta 0xEB per lettura bit retrace
Il blocco è realizzato tramite un codice in linguaggio VHDL, ovvero
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity IO_DEC is
Port (
BM1 : IN STD_LOGIC;
BIORQ : IN STD_LOGIC;
BA : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
CSVMEM : OUT STD_LOGIC;
CSIOVP : OUT STD_LOGIC;
CSKBD : OUT STD_LOGIC;
CSSYNC : OUT STD_LOGIC
);
end IO_DEC;
architecture Behavioral of IO_DEC is
begin
process (BIORQ, BM1, BA)
begin
--- Disable unused CSVMEM Access
CSVMEM <= '1';
--- Disable 0xE9 CSIOVP Access
CSIOVP <= '1';
--- Disable 0xEA CSKBD Access
CSKBD <= '1';
--- Disable 0xEB CSSYNC Access
CSSYNC <= '1';
if (BIORQ = '0' AND BM1 = '1') then
if (BA = x"E7") then
CSIOVP <= '0';
end if;
if (BA = x"EA") then
CSKBD <= '0';
end if;
if (BA = x"EB") then
CSSYNC <= '0';
end if;
end if;
end process;
end Behavioral;
Il circuito equivalente di questo blocco è il seguente
32
Il contenuto del PIC16F628A è stato programmato sempre tramite il programmatore TL866 II,
con lo stesso software Xgpro dopo aver impostato il device corretto e letto il file HEX fornito
da Pino Giacquinto