Indholdsfortegnelse:
- Trin 1: Hurtigt overblik over ændringer + skemaer
- Trin 2: CPU, hukommelse og hukommelseskontrol
- Trin 3: Systemstatus -LED'er
- Trin 4: Input og Output
- Trin 5: Nulstil og afslut input og output
- Trin 6: Programmering
Video: Gennemgang af Z80 -computeren: 6 trin
2024 Forfatter: John Day | [email protected]. Sidst ændret: 2024-01-30 08:25
Tidligere har jeg skrevet en guide til, hvordan man bygger en Z80-baseret computer, og jeg designet kredsløbet til at være så enkelt som muligt, så det kunne bygges så let som muligt. Jeg skrev også et lille program ved hjælp af den samme idé om enkelhed. Dette design fungerede ret godt, men jeg var ikke helt tilfreds med det. Jeg startede med at omskrive et program til det, der tillod det at blive programmeret under runtime. Dette var for at lade mig teste stykker kode uden at skulle dedikere det til EEPROM, hvilket igen ville kræve, at jeg omprogrammerede EEPROM. Det her lyder ikke som en sjov idé for mig. Så begyndte jeg at tænke på hukommelsesrum. Hvis jeg ville interface et stykke hardware (hovedsageligt IO), kunne et stykke kode potentielt overstige mængden af hukommelsesplads, der er tilgængelig for systemet. Husk, at designet kun brugte den nederste byte i adressebussen, og derefter blev den nederste bit af den høje byte brugt til at vælge mellem ROM- og RAM -mellemrum. Dette betød, at jeg kun havde 253 bytes plads at bruge. Du spørger måske hvorfor 253 i stedet for 256. Det er fordi min nye kode injicerer tre bytes data i slutningen af et skriftligt program (dette vil blive dækket senere, da jeg ændrede det til at arbejde på det nye design).
n
Jeg gik tilbage over mine gamle skemaer for at se, hvad der ellers foregik. Jeg fandt en lille fejl med hukommelsesvalgkredsløbet, som jeg vil dække, når jeg kommer derhen. Den forenklede version: alle skriveforespørgsler ville faktisk gå igennem, selvom den altid blev sat i RAM. Dette var sandsynligvis ikke noget værd at bekymre sig om, men jeg ville gøre det ordentligt denne gang. Og med det begyndte jeg at tegne en ny skematisk. De to billeder, der er vedhæftet denne side, er før og efter det faktiske kredsløb. Jeg har ryddet så meget op i spaghetti -ledningerne, det er ikke sjovt.
n
Hvis du fulgte med min oprindelige indsendelse og planlægger at følge med i denne, kommer du til at hade mig. Hvis du starter frisk, har du held og lykke. Bare tag delene på listen (eller deres tilsvarende) og følg med.
Tilbehør:
LM7805 - 5 Volt regulator Z80 - CPU'en; hjernen i systemAT28C64B - EEPROM. "Permanent" datalagring, der bruges til computerens firmwareIDT6116SA - SRAM; bruges til lagring af brugerkode og /eller generel datalagringNE555 - Systemur74HC374 - Octal D -Latch med /OE; bruges som inputchip74LS273 - Octal D -Latch med /MR; outputchipTLC59211 - LED -driverchip (brugt, så 74LS273 kan drive lysdioder, da den ikke alene er i stand til den aktuelle output) MC14572 - Dette er en "Line Driver" -chip, men jeg fandt den perfekt til hukommelseskontrollogikken. Den har 4 invertere og en NAND- og NOR -port bygget in74LS32 - Quad OR gateCD4001 - Quad NOR gateCD4040 - 12 Stage Ripple Counter; Tegnet, men ikke implementeret urdeler (til at køre systemet ved lavere hastigheder) 2 10K Ohm modstande - Den ene bruges i 555 timerkredsløbet, så brug den værdi, du vil have for den 4 1K Ohm modstande - Den ene bruges til 555 timer kredsløb, så brug hvad du vil til det. En anden bruges til at køre LED'er, så varier den også, hvis du gerne vil 8x330 Ohm Resistor Bus8x10K Ohm Resistor Bus11 LED'er - Tre bruges til systemstatus, og de andre otte er output. Til de 8 brugte jeg et søjlediagram (HDSP -4836) 4 kondensatorer - To blev brugt LM7805; 0,22uF og 0,1uF. Den ene er til 555 -timeren, så brug det, du synes er rigtigt. Den sidste er til nulstilling ved opstart; 100uF2 N. O. Push -knapper - Den ene bruges til input, den anden til reset 8 SPST DIP -switches - Datainput; Jeg brugte Piano Key styleWire. Masser og masser af tråd
n
BEMÆRK: MC14572 gennemgående version er forældet, men SMD -versionen er stadig aktiv (ikke engang status "ikke til nyt design"), så du skal muligvis købe et printkort, så du kan bruge det. En anden 74LS32 kan bruges i stedet for MC14572 (se skematisk “hukommelsesvalgkredsløb” for tidligere ible)
Trin 1: Hurtigt overblik over ændringer + skemaer
Sådan læses skemaerne: En pil, der peges ind i en chip, er et input: Input> -En pil, der peges væk fra en chip, er en output: Output <-Busser bruger en linje i stedet for en pil: Bus |-
n
De fleste chips er blevet trukket med deres nøjagtige pinouts. Den lille dukkert er blevet trukket på disse chips. De fleste chips har også pin -numre og etiketter på dem. De er måske lidt svære at læse. Min blyant blev kedelig.
n
Med hensyn til kredsløbstilslutninger er layoutet på det nye design stort set uændret fra originalen. Jeg sluttede den nederste nibble af adressen high byte til hukommelserne og brugte derefter den lave bit af den øvre nibble (A12) til valg af RAM/ROM. Dette betød, at ROM-rummet gik fra 0000-00FF op til 0000-0FFF. Rampladsen gik fra 0100-01FF til 1000-1FFF. Jeg byttede også hukommelseskontrollogik til et bedre design og tilføjede to nye status -lysdioder (og lidt limlogik). Jeg har også tegnet (men trådede ikke) et uropdelerkredsløb. Det skulle udføre to funktioner. Den oplagte funktion er at dele urfrekvensen ned. Den anden funktion er til PWM (Pulse Width Modulation) formål, da 555 ikke genererer bølger med 50% driftscyklusser. Det gør ikke rigtig noget i dette kredsløb, men hvis du ville bruge uret til at køre nogle lysdioder, vil du helt sikkert bemærke effekterne (den ene (sæt af) LED (er) vil være svagere end den anden). Hele resten af kredsløbet er i det væsentlige uændret.
Trin 2: CPU, hukommelse og hukommelseskontrol
Dette er den del, hvor læsere af min tidligere version hader mig. I den originale konstruktion smed jeg lige lidt dele på tavlen et sted, de lignede, at de ville påføre lidt problemer med at få kablet op. Resultatet lignede, at nogen dumpede en tallerken spaghetti på det og var som "ledninger!" Jeg ville rydde det lidt op, så jeg startede med at rippe alt undtagen CPU, RAM og ROM op. Jeg trak næsten hele inputkredsløbet, outputkredsløbet og limlogikken op. Det gjorde mig næsten ondt at gøre, men det var nødvendigt. Jeg efterlod alle dataforbindelserne intakte og adressebusens nederste byte. Jeg tilsluttede derefter de næste fire bits i adressebussen (A8-A11) til ROM-chippen. Jeg sørgede for at gå rundt om chippen denne gang for at gøre det lettere at trække op til omprogrammering. Jeg hoppede også adresseforbindelserne ned til RAM -chippen.
n
Med det ude af vejen, var jeg nødt til nu at få hukommelseskontrollogikken tilsluttet. I den originale skematik havde jeg tilsluttet processorens /MREQ -linje direkte til /CE til begge hukommelseschips, derefter koblet jeg /WR til RAM'en /WE. Derefter havde jeg CPU'erne /RD og /MREQ logisk OR'd sammen samt A9. I det væsentlige var det konfigureret, så alle hukommelsesanmodninger aktiverede både RAM og ROM, men A9 blev brugt til at vælge, hvilken af chipsene /OE der blev valgt. Dette var fint, og alt fordi chipsene ville forblive inaktive, indtil der blev fremsat en hukommelsesanmodning, og derefter kun en /OE ville være aktiv under en læseanmodning. Dette forhindrede krydstale, men introducerede en akavet nuance. Fordi A9 kun blev brugt til at bestemme, hvilken chip der udsendte data, og fordi CPU'en havde direkte adgang til RAM's /WE -pin, ville alle skriveforespørgsler gå igennem. Dette var ok for ROM'en, fordi dens skrivemåde er hæmmet ved at binde /WE direkte til 5V forsyningen. RAM'en ville imidlertid blive skrevet til uanset A9. Dette betød, at et forsøg på at skrive til en ROM -plads ville skrive til det samme sted i RAM -rummet.
n
En løsning til dette ville være at rewire kontrollogikken, så CPU'en har direkte adgang til chips ' /OE- og /WE -benene og derefter bruge MREQ og A12 til at vælge, hvilke chips /CE der blev drevet. Jeg gik med denne idé, men i stedet for at bruge fire NOR -porte og en inverter som det originale design, fandt jeg en akavet lille chip, der var perfekt til opgaven. Jeg var nødt til at oprette et kredsløb, der kun brugte de logiske porte, der var tilgængelige i chippen, men det var let nok. A12 føder direkte ind i en NAND -port og en NOR -port. /MREQ føres ind i NOR -porten, og dets kompliment føres ind i NAND -porten. NAND -porten bruges til at drive /CE til RAM, og NOR -udgangen bliver inverteret og bruges til at drive ROM /CE. Dette gør det sådan, at /MREQ skal være lav, før hver chip vælges, og derefter vælger A12, hvilken der skal vælges. Med denne opsætning vil alle skriveforespørgsler til ROM nu ikke gøre noget. Det sparer også strøm, fordi kun en chip er aktiv i stedet for begge. Hvad angår selve logikchippen, har vi stadig to ubrugte invertere indeni. Man vil blive brugt senere, men vi kommer derhen, når vi kommer derhen.
Trin 3: Systemstatus -LED'er
Inden jeg startede dette projekt, forsøgte jeg at kommunikere med en bestemt IC, men jeg havde problemer med det. Usikker på, hvad der foregik, brugte jeg en panelmonteret LED til at sondre rundt (en af de forsamlinger, der har en modstand indbygget). At gøre dette gav mig en nostalgi -idé, der stadig bruges i dag: status -lysdioder, der bruges til at indikere, om hukommelse blev læst fra eller skrevet til. Den skulle bruges sammen med den input -LED, jeg allerede havde. Indgangs -LED'en var forbundet til /WAIT -signalgeneratoren for at indikere for os, at systemet godt venter på input (jeg kommer derhen, bare rolig). Jeg overvejede at tilføje en LED til angivelse af en IO -skrivning, men jeg regnede med, at output -LED'erne, der blev ændret, allerede ville være en god indikator på det. Når jeg tænker over det, kan jeg stadig tilføje det endnu. Ikke desto mindre finder jeg det nyttigt at vide, om hukommelsen læses eller skrives. Nå, det er alligevel nyttigt til programfejlfinding. Jeg brugte det faktisk kraftigt som sådan, da jeg forsøgte at få mit program til at fungere: “hvorfor skriver det til hukommelsen? Det skal ikke gøre det endnu!”
n
For at styre disse lysdioder brugte jeg quad NOR -porten. Jeg brugte alle portene. Kun to blev brugt til at generere statussignalerne, men chippen har ikke strømfunktioner til faktisk at drive LED'erne. De er i stand til at synke så meget strøm, så jeg brugte de to andre NOR -porte som invertere og tilsluttede lysdioderne som sådan. Fordi den ene LED bruges til at angive læsninger og den anden til skrivning, og en læse- og skriveforespørgsel ikke forekommer på samme tid, var jeg i stand til at slippe afsted med at bruge kun en modstand til begge lysdioder. Hvad angår de signaler, jeg havde brug for at afkode, var det også let nok. Jeg ville have, at alle hukommelseslæseanmodninger skulle blive angivet, så den første NOR -gate havde /MREQ og /RD på sine input. Skrivestatus var lidt vanskeligere, men lige så let. Jeg brugte stadig /MREQ som et input, men brug af /WR som det andet ville forårsage en mindre nuance, jeg ville undgå. Det ville have angivet ALLE skriveforespørgsler. Jeg ville kun have dem, der faktisk gik igennem. Så hvordan ville jeg gøre det? Kan du huske, hvordan jeg har konfigureret systemet, så kun RAM kan skrives? Jeg brugte RAM /CE som den anden input til NOR -porten. Det betyder, at LED'en kun lyser, når RAM er valgt, og der skrives en skriveanmodning. Med hensyn til LED -farve valgte jeg orange som læseindikator (men jeg fandt kun gule) og rød som skriveindikator.
Trin 4: Input og Output
I det foregående trin har du måske bemærket, at jeg allerede har tilføjet nogle af resten af komponenterne til brættet. Jeg reserverede pladsen, så jeg ikke ved et uheld ville placere ledninger, hvor jeg ville have en komponent (derfor skulle jeg finde en ny placering til komponenten). Du har muligvis også bemærket, at jeg forlod inputkontakterne på plads og kablet op til strømskinnen. Jeg besluttede, at den oprindelige placering var det perfekte sted og besluttede at placere output -LED'erne i nærheden (ovenfor). Til højre for søjledisplayet er inputlåsen. Ovenfor er udgangslåsen, og til venstre for den er LED -driveren. Jeg startede med at tilslutte skærmen til driveren, da det var det nemmeste at gøre. Derefter sluttede jeg kontakterne til indgangssiden af inputlåsen. Derefter sluttede jeg output -siden af output -låsen til LED -driveren. Dette kan virke som en akavet ordre om at få disse tilsluttet, men det var af en grund. Inputen på outputlatchen skulle forbindes til databussen såvel som output fra inputlatchen. Ideen var at forbinde input -låsens udgange til input fra output -låsen, hvilket jeg gjorde. Så var det eneste, jeg skulle gøre, at få det rod forbundet til databussen. Det var ligegyldigt, hvor disse forbindelser gik fysisk, fordi de alle ville være elektrisk forbundet. Computeren er nu næsten færdig.
Trin 5: Nulstil og afslut input og output
Beklager, ingen billeder til dette trin. Se forrige trin for billederne.
n
Du har muligvis bemærket i det sidste billede af det foregående trin, jeg havde en grøn knap og en anden logisk chip installeret. Chippen er OR -porten. To porte bruges til at generere /WAIT signalet. Godt, man genererer signalet ved OR-ing /IORQ og /RD fra processoren. Outputtet føres ind i den anden gate, hvor den igen får OR'd til en trykknap. Knappen bringer portens input højt og bringer dermed output højt. Denne udgang føres til processorer /WAIT pin. Selvom den ikke trykkes ned, holder en modstand input lavt. Jeg brugte oprindeligt en 10K modstand, men LS32 lagde faktisk spænding ud på indgangen. Modstanden faldt den ikke lavt nok, og jeg var nødt til at erstatte den med en 1K. Alligevel er tanken, at når der fremsættes en IO -læseanmodning, fortæller den første og anden OR -port processoren at vente. Når du har indstillet indgangskontakterne til det, du ønsker, trykker du på knappen, og det bringer CPU'en ud af ventetilstanden. Den grønne "input" -LED, som jeg kaldte det i et tidligere trin, er tilsluttet, så når /WAIT pin går lavt, lyser den.
n
Men vi er ikke færdige endnu. Input flip -floppen har brug for et signal for at lade det vide, når data input er gyldigt og skal sendes til CPU'en. Denne urnål er aktiv høj. Før forbandt vi det bare med knappen. Dette er stadig en gyldig mulighed, men denne gang valgte jeg at sætte det på samme output som den anden OR -gate. Denne IC har også en /OE pin, der skal køres. Hvis det skulle holdes højt, ville det aldrig indsætte data i bussen. Hvis den holdes lav, ville den altid køre bussen. For at løse dette brugte jeg simpelthen en tredje ELLER -gate. Indgangene er /IORQ og /RD, og output går direkte til låsen /OE.
n
Outputlåsen skal også have urpinden til at blive drevet. Igen er det aktivt højt. I min skematiske tegnede jeg den fjerde ELLER -port, der direkte drev stiften ved hjælp af /IORQ og /WR. Dette betød, at urnålen ville blive holdt højt, indtil der blev fremsat en skriveforespørgsel, derefter ville den gå lav og derefter høj igen. Dette ville sandsynligvis have været fint, fordi databussen stadig ville have haft gyldige data om det umiddelbart efter forsøget på at skrive, men fra et teknisk synspunkt var et affaldsdesign. Jeg lagde ikke mærke til denne fejl, før jeg havde taget de sidste billeder, men jeg rev den forbindelse op og fodrede derefter OR -gate -udgangen til en af de ubrugte invertere fra hukommelseskontrollogikken og sluttede derefter dens output til urpinden. Jeg rettede også skematikken og fandt en anden fejl, jeg havde lavet. Jeg rettede det også.
n
Da alt dette endelig var gjort, havde jeg en meget lille mængde arbejde at lave: nulstillingskredsløbet. Jeg tilføjede en knap til tavlen og brugte en 10K modstand til at holde den ene side højt. Den anden side går direkte til jorden. Siden holdt højt er /RESET output, som gik til hver chip med en /RESET pin (CPU og output latch). For at opnå nulstilling ved opstart tilføjede jeg en kondensator til /RESET-udgangen. Ideen er, at modstanden med stor værdi ville få den relativt store kondensator til at oplade langsomt og holde /RESET -benene lave for en vis mængde urcyklusser (CPU'en har brug for fire urcyklusser). Du kan sikkert allerede gætte, hvad den negative side af dette kredsløb er. Det er det samme negative som den tidligere version, fordi det er det samme kredsløb. Når der trykkes på knappen, kortsluttes kondensatoren i det væsentlige gennem knappen. Dette er dårligt for både hætten og knappen, så hvis du vil gøre din bygning lidt mere permanent, kan du måske redesigne den. Jeg tænkte på en anden 555 timer sat op i monostabil tilstand. Men med det er computerkredsløbet nu færdigt. Yay. Nu skal det programmeres.
Trin 6: Programmering
At programmere denne ting var et mareridt. Jeg byggede en Arduino EEPROM programmerer. Det virkede ikke. Jeg byggede en anden baseret på en andens design og kodning. Virkede stadig ikke. Jeg gik tilbage til den afprøvede metode til manuelt at indstille adresser og databyte i hånden. På en eller anden måde ødelagde jeg det. Jeg prøvede igen og fik det stadig forkert. Jeg gik tilbage igen og opdagede, at det var slukket med en enkelt byte, så jeg rettede det, og det fungerede endelig, gudskelov.
n
Hvad angår det egentlige program, ser det ud til at være super komplekst og svært at følge, men det er det ikke. Det er faktisk ret simpelt. Halvdelen af det kopierer tal rundt. Den anden halvdel deles mellem 16-bit matematik, betingede spring og endnu flere kopieringstal rundt. Så lad mig gå igennem det og fortælle dig, hvordan det fungerer.
n
Initialisering sætter bare nogle registerværdier til brug for programmet. Programsløjfen er lidt mere kompleks, men ikke meget. Først accepterer det input til A -registret på port 00. Derefter bliver E -registret skrevet til hukommelsen. På de to første sløjfer indeholder E -registeret uønskede data, så vi forsøger at skrive det til de sidste to bytes ROM -rum, fordi det faktisk ikke bliver skrevet; adressemarkøren (IY) øges derefter. Værdien, der er gemt i D, flyttes derefter til E for derefter at blive skrevet. A indlæses derefter i D, og L og E kopieres til H. HL er, hvor værdisammenligningen finder sted via subtraktion og kontrol af ZF (nulflag). Den første værdi, der sammenlignes med, gemmes i registrerne B og C. B og C behandles som et enkelt 16-bit register, BC. Hvis værdierne er de samme, hopper programmet direkte ind i RAM -rummet, hvor det antages, at brugerkoden ligger. Hvis koden i BC ikke er en match, genindlæses HL med de oprindelige værdier fra D og E og sammenlignes igen med værdien i SP på samme måde som den blev sammenlignet med BC. Hvis det er et match, har det det samme resultat, men tre ekstra bytes skrives til hukommelsen. Bytes er en kode, der får CPU'en til at hoppe tilbage til begyndelsen af sit program (en software -nulstilling). Hvis den anden sammenligning imidlertid ikke var en match, løber programmet derhen, hvor det får en værdi fra brugeren.
n
LD SP, EDBFH; exe -kode (tilføjer spring)
n
LD IY, FFEH; første hukommelsesmarkør til kodelagring
n
LD BC, EDC3H; exe -kode (ingen loop)
n
loop; assembler -direktiv, så vi ikke behøver at vide, hvor i hukommelsen denne del befinder sig
n
I A, (00H); få programdata
n
LD (IY+00H), E; E indeholder kode, der skal gemmes
n
INC IY; flytte til næste hukommelsessted
n
LD E, D; ld D til E
n
LD D, A; ld A til D
n
LD H, E; ld E ind i H
n
LD L, D; ld D til L
n
ELLER A; nulstil bæreflag
n
SBC HL, BC; returnerer 0, hvis exe -kode 2 blev indtastet
n
JP Z, 1000H; i så fald spring til og udfør program
n
LD H, E; Ellers skal du opdatere disse til de korrekte værdier
n
LD L, D
n
ELLER A; første træk kan have sat bæreflag. Ryd det
n
SBC HL, SP; returnerer 0, hvis exe -kode 1 blev indtastet
n
JP NZ, loop; hvis ikke, gentag processen (start med at få en værdi)
n
LD (IY+00H), C3H; Ellers skal du indsætte en springkode i slutningen af brugerprogrammet
n
LD (IY+01H), 00H; jump fungerer i bund og grund som en software -nulstilling
n
LD (IY+02H), 00H; det er en fuldstændig nulstilling, hvis registre blev ændret
n
JP 1000H; spring til og udfør brugerprogram
Anbefalede:
Z80-MBC2 Programmering af Atmega32a: 6 trin
Z80-MBC2 Programmering af Atmega32a: Før du kan bruge z80-MBC2, skal du programmere Atmeg32 efter at have bygget den. Denne instruktion viser dig, hvordan du bruger en billig arduino mini som programmerer til at uploade koden
Z80 MBC2 - Genkompilér QP/M Bios og Loader: 6 trin
Z80 MBC2 - Re -compile QP/M Bios and Loader: Hvis du, ligesom mig, befinder dig i en position, hvor du skal genkompilere QP/M bios til din MBC2 - så er det sådan du gør det. Jeg dokumenterede processen, hvordan man rekompilerer den eksisterende version. Det er op til dig at foretage ændringer i den faktiske Bios
Z80-mbc2 Z80 Code Flash User LED: 3 trin
Z80-mbc2 Z80 Code Flash User LED: Dette er et eksempel bruger-LED-program skrevet i Z80-assembler til z80-mbc2-computeren.Jeg lavede dette en test- og revisionsøvelse for mig, dette er mit første Z80-program i over 35 år.Nyd
Z80 MBC2 - Genkompilér CPM2.2 Bios: 4 trin
Z80 MBC2 - Re -compile CPM2.2 Bios: Hvis du, ligesom mig, befinder dig i en position, hvor du skal genskabe CP/M bios (2.2) til din MBC2 - så er det sådan du gør det. min sag Jeg ville fjerne meddelelsen “WARM BOOT” hver gang et program eksisterede, eller når du lavede en ctrl-c. Jeg en
Brug af ESP32/VGA32-terminal til Z80-MBC2: 7 trin
Brug af ESP32/VGA32-terminal til Z80-MBC2: Sådan opbygges og installeres ANSI Terminal-softwaren på et ESP32/VGA32-kort. Tilslutes derefter til et Z80-MBC2-kort