CLAUDIA Lite

primitivní 4-bitový procesor/počítač sestavený z obvodů TTL 74xx



Sequencer

Sequencer je základní řídící částí procesoru. Někdy se mu také (nesprávně) říká procesor uvnitř procesoru. Jeho úkolem je řídit všechny transakce, které uvnitř procesoru probíhají a to na základě instrukčního souboru. Každou přijatou instrukci, resp. její binární operační kód, z vnější paměti programu si sequencer uloží do tzv. instrukčního registru (IR) a promění ji ve sled (sekvenci) řídících signálů (tzv. mikroinstrukcí). Tyto signály pak řídí vzájemnou komunikaci mezi jednotlivými obvody procesoru tak, aby došlo k očekávanému vykonání instrukce (třeba skoku na jinou adresu, sečtení dvou čísel, přesunu dat mezi registry apod.) Existují i procesory, které dovedou vykonávat všechny instrukce v jediném kroku, nicméně náš TTL procesor je tzv. klasického střihu a instrukce vykonává tak, že je rozloží do sekvence několika mikroinstrukčních kroků. Název sequencer jsem si vymyslel, protože ve skutečnosti se takovému zařízení říká mikroprogramový sekvenční řadič. Jeho ústřední součástkou je totiž pevná paměť ROM s tzv. mikroprogramem tvořeným tzv. mikroinstrukcemi. Ale název sequencer mi přijde příhodnější...

Jak bylo uvedeno v popisu generátoru hodin, máme vnitřní obvody procesoru hypoteticky rozděleny na vysílače dat (TX) a přijímače (RX). Úkolem sequenceru je pro každou zpracovávanou instrukci generovat sled (sekvenci) signálů, které řídí přesuny dat mezi jednotlivými TX a RX. Sequencer tedy musí generovat dvě základní skupiny signálů: signály pro ovládání vysílačů (TX signály) a signály pro ovládání přijímačů (RX signály). Aby bylo možné data přesouvat "odkudkoliv kamkoliv" je nutné aby TX signály byly generovány nezávisle na RX signálech a naopak. To zajišťuje právě pevná paměť s mikroprogramem, za kterou následují dekodéry BIN na 1zN (pro každou skupinu signálů jeden).


Princip sequenceru

Nyní již k vlastnímu principu sequenceru. Ústřední součástkou je tedy pevná paměť ROM s tzv. mikroinstrukcemi. Mikroinstrukce jsou binární kódy, které jsou pomocí dekodérů BIN na 1zN překódovány na řídící signály vysílačů TX a přijímačů RX. V podstatě je mikroinstrukce jen adresou konkrétního vysílače a konkrétního přijímače. Adresaci paměti ROM společně zajišťují tzv. instrukční registr IR s čítačem mikroinstrukcí. Více napoví následující zjednodušené schéma sequenceru:

Zjednodušené schéma sequenceru
Zjednodušené schéma sequenceru

Jak to tedy pracuje? Má-li sequencer začít zpracovávat novou instrukci z paměti programu, je nutné tuto instrukci (její operační kód) vložit do instrukčního registru IR. Současně je nutné vynulovat čítač mikroinstrukcí. Operační kód instrukce (v IR) tedy bude tvořit vyšší část adresy paměti s mikroinstrukcemi a výstupy čítače zase tvoří nižší část adresy. Společně tedy IR s čítačem tvoří úplnou adresu mikroinstrukce v řídící ROM. Důležité je, aby IR i čítač pracovaly synchronně a nahrání instrukce do IR a vynulování čítače proběhlo současně na náběžnou hranu F1. Signál k nahrání instrukce do IR a signál k vynulování čítače jsme pojmenovali jako /LIR (Load Instruction Register). Tento signál je generován řídící ROM a není nijak synchronizován s hodinami (F1 a F2). Signál /LIR se na výstupu z ROM musí objevit vždy při adresování poslední mikroinstrukce ze sekvence právě zpracovávané instrukce. Po vykonání této poslední mikroinstrukce je s následující náběžnou hranou F1 vložen kód nové instrukce do IR, vynulován čítač a začne mikroinstrukční sekvence této nové instrukce. Sekvence opět musí končit generováním signálu /LIR. Je jasné, že v okamžiku, kdy chceme do IR nahrát nový operační kód instrukce, musí být tento kód přítomen na vstupech IR a tedy na sběrnici (BUS) procesoru. Z toho plyne, že poslední instrukce každé sekvence musí kromě generování signálu /LIR generovat také signál pro čtení paměti programu. Během zpracovávání instrukce a jejího rozkladu na sekvenci mikroinstrukčních kroků se obsah IR nemění a stále drží poslední načtený kód instrukce. Naopak čítač mikroinstrukcí je s každou náběžnou hranou F1 inkrementován a jeho výstupy tak adresují jednotlivé mikroinstrukční kroky dané instrukce až do okamžiku nahrání (/LIR) nové instrukce do IR, kdy je čítač vynulován.

Paměť mikroinstrukcí je v reálných procesorech tvořena diodovou maticí přímo na čipu a mívá mnohem větší bitovou šířku, než je šířka datové sběrnice daného CPU. V amatérských procesorech se namísto diodové matice používá nějaká běžná paměť typu (E)PROM. V Claudii Lite jsem použil stejnou PROM jako je v PIP-2, tedy 74188 s 8-bitovou šířkou dat. Těch 8 bitů neumožňuje generovat moc řídících signálů, ale pro takto jednoduchý procesor to stačí. Koneckonců v PIP-2 je mnoho bitů dokonce nevyužito a tak má sequencer PIPa docela slušné rezervy a díky tomu bylo možné přidat další funkcionalitu do Claudie Lite. Ovšem zásadní omezení je v tom, že adresový rozsah této PROM je jen 5 bitů a je tedy možné do paměti vložit pouze 32 mikroinstrukčních kroků. To bylo zásadní omezení, se kterým jsem se musel vypořádat při rozšiřování funkcionality (a tedy i počtu instrukcí, potažmo sekvencí mikroinstrukcí) Claudie Lite.

Výstup z řídící paměti PROM je zaveden do dvou dekodérů 1zN, které již generují příslušné TX a RX signály. Dekodéry musí být dva, aby se daly TX a RX generovat nezávisle. Abychom dosáhli správného časování signálů a synchronizace s hodinami, můžeme s výhodou "hradlovat" celé dekodéry a to tak, že dekodér pro TX bude uvolněn s aktivní částí fáze F1 a dekodér RX zase s fází F2. Více viz. popis generátoru hodin na předešlé stránce. Pokud bychom chtěli plně využít 8-bitové šířky dat naší PROM 74188 pro nezávislé generování signálů TX a RX, mohli bychom použít dva dekodéry BIN4 na 1ze16 (74154). Při rozdělení půl na půl (4 bity adresují vysílač a 4 bity adresují přijímač - obě skupiny musejí být nezávislé!), je možné generovat nezávisle 16 TX signálů pro vysílače a 16 RX signálů pro přijímače. Pro plnohodnotný procesor je to málo, ovšem pro Claudii Lite je to až moc. Ukázalo se, že budou stačit převodníky BIN3 na 1z8 (74138). PIP-2 využívá obvodů 7442, ale ty není možné tzv. hradlovat a právě možnost hradlování (blokování/uvolňování) dekodérů 74138 výrazně zjednodušilo zapojení a uspořila mnoho separátních hradel. Dva dekodéry 1z8 potřebují pro své vstupy 6 bitů. 2 bity z výstupu PROM nám tedy zbyly. Jeden je využit na nehradlovaný signál /LIR a druhý na signál /NOP, jehož význam bude popsán dále.

8-bitová šířka dat mikroprogramové ROM je opravdu velmi málo, byť s ní vystačí i složitější Claudie-1. Proto musel být omezen počet řízených obvodů uvnitř procesoru na nezbytné minimum. Reálné procesory mohou mít bitovou šířku řídící paměti i desítky či stovky bitů! Další navýšení funkcionality procesoru a tedy i složitosti je možné jen zvýšením bitové šířky paměti mikroinstrukcí, tedy třeba použitím dvou pamětí (adresy paralelně, data sériově). Ruku v ruce s tím jde ale i nutnost většího počtu adres v mikroprogramové ROM. Jak uvidíme dále, je těch 32 pozic v PROM 74188 Claudie Lite opravdu hrana, a to se ještě musely vymýšlet fígle, jak zkrátit mikroinstrukční sekvence na minimum kroků.

Takže si to zopakujeme: výběr požadované mikroinstrukce se děje adresací paměti mikroinstrukcí (ROM). Adresa mikroinstrukce se skládá z operačního kódu instrukce (nejvyšší bity adresy) a z pořadí mikroinstrukce v sekvenci (nejnižší bity adresy). Operační kód instrukce je vždy načten z externí paměti programu a je uložen v Instrukčním Registru (IR). V tomto registru kód setrvává po celou dobu zpracování této instrukce, tedy jejího rozkladu na sekvenci mikronstrukcí. Nižší část adresy mikroinstrukce a tedy její pořadí v sekvenci, generuje binární čítač, který musí být v okamžiku nahrání nové instrukce do IR vynulován. V případě mé Claudie-1 jsou IR i čítač 4-bitové. Paměť mikroinstrukcí tedy musí mít rozsah 256 adres a pro zpracování každé instrukce je k dispozici maximálně 16 kroků. Nejsložitější instrukcí tam je skok do podprogramu (CALL), který potřebuje 13 mikroinstrukčních kroků.

U Claudie Lite má paměť mikroinstrukcí pouze 32 adres, tedy adresace je 5-bitová. 4 bity tvoří operační kód instrukce (načtený z externí paměti po 4-bitové sběrnici) a pouze 1 bit zbývá na čítání mikroinstrukcí (tedy jen 2 kroky). To je ale žalostně málo a nestačí to. Proto není možné využít všech 4 bitů na operační kód, ale jen část a zbytek ponechat na krokování. Tím je dáno i to, že Claudia Lite nemůže mít 16 instrukcí, což je počet odpovídající 4-bitové sběrnici. Bude jich méně. Ale jak uvidíte dále, nebude to o moc a bude jich mnohem více, než má PIP-2 se stejnou PROM:-)

Pokud bychom použili 3 bity na operační kód instrukce a zbylé 2 bity na krokování mikroinstrukční sekvence, dostaneme maximálně 8 různých instrukcí z nichž každá může sestávat ze 4 mikroinstrukčních kroků. Je to sice rozumný kompromis, ale mě to bylo málo. Nakonec jsem tam těch instrukcí nacpal 13 a každá sestává v podstatě ze 4 mikrokroků. To znamená 13x4=52 potřebných pozic v řídící ROM. My ale v 74188 máme jen 32 pozic. Jak dále uvidíte, dá se těch 52 kroků nacpat do těch 32 pozic. Jen to chtělo trochu myslet:-) Bude vysvětleno dále.


Sequencer Claudie Lite

Výše uvedené schéma sekvenceru je jen pro pochopení funkce. Reálné schéma je malinko složitější, ale ne zase o moc:

Sequencer Claudie Lite
Sequencer Claudie Lite

V zapojení je několik změn daných pouze 5-bitovou adresou řídící ROM 74188. Instrukční registr a čítač mikroinstrukcí jsou sloučeny do jednoho obvodu a sice čítače 74163 s možností resetu a předvolby. Jedná se o synchronní čítač se synchronním resetem i předvolbou (vše na náběžnou hranu hodin). Čítač je 4-bitový, takže je doplněn o jednobitový pomocný registr typu D (polovina 7474), kam je ukládán nejvyšší bit operačního kódu instrukce. Spolu s tímto pomocným registrem pak čítač dohromady vytváří 5-bitovou adresu pro řídící ROM. Jelikož máme na vstupu k dispozici jen 4 bity, je nejnižší bit předvolby čítače trvale na nule. Z tohoto kompromisního zapojení "expanderu" ze 4 bitů na 5 plynou i následující omezení. Za prvé musí každá mikroinstrukční sekvence v ROM začínat na sudé adrese (nejnižší bit počáteční adresy je vždy 0). To není problém, jelikož počet mikroinstrukčních kroků vychází na max. 4, je tato podmínka splněna. Za druhé nesmí mikroinstrukční sekvence "přetékat" přes polovinu kapacity ROM, protože nejvyšší bit v pomocném registru není možné během čítání čítače měnit. I to je díky 4 mikroinstrukčním krokům na instrukci zajištěno (4x4=16). Zužitkovala se tak druhá půlka obvodu 7474 z generátoru hodin a nemusel se klasicky nastavovat čítač 74163 o jeden další stupeň...

Kromě 5 bitového instrukčního registru IR tvořeného čtyřbitovým čítačem 74163 (IR2) a jednobitovým registrem 7474 (IR1) je v zapojení ještě tzv. pomocný instrukční registr IR* z obvodu 74175. Tento je klasicky 4-bitový a je do něj ukládán operační kód instrukce načtený z paměti RAM počítače. Tento pomocný registr je velmi důležitý pro správnou synchronizaci procesoru na začátku každéno instrukčního cyklu. Je důležitý také pro správnou synchronizaci po resetu a v poslední řadě umožnil též ono "záhadné" zhuštění potřebných 52 kroků do 32 pozic ROM.

Výstupem z paměti PROM 74188 jsou tedy adresy vysílačů (TX) a přijímačů (RX), které jsou pomocí dekodérů BIN3 na 1z8 74138 převedeny na výběrové signály konkrétních TX a RX. S výhodou jsem využil uvolňovacích vstupů těchto dekodérů k přivedení hodinových fází /F1 a /F2 a tím jsem zároveň získal synchronizaci výběrových signálů s hodinami a tedy i správné časování přesunu dat mezi TX a RX. Druhé uvolňovací vstupy jsem použil k nucenému zablokování dekodérů signálem /PROG během ručního programování paměti RAM počítače. TX signály mají být zpravidla aktivní v úrovni LOW a můžeme je tedy použít přímo z dekodéru. RX signály mohou být žádoucí spíše v HIGH a je nutné příslušné výstupy dekodéru invertovat.

Může se však vyskytnout případ, kdy je nutné generovat jen signál přijímače, bez vysílače. Jedná se zejména o inkrementaci nějakých interních čítačů (program counter PC, ukazatel zásobníku, apod). V takovém případě jsou dvě možnosti: buď adresovat vysílač, který v dané operaci nic neovlivní, nebo mít jeden TX signál neobsazený a adresovat ten. Ve svých Claudiích to tak mám a signál jsem pojmenoval příhodně /PLONK, protože je opravdu plonkový a nikam nevede:-)

Ze schématu je patrné také využití původně neobsazených dvou datových bitů ROM 74188 jakožto signálů /LIR a /NOP. Jejich funkce bude vysvětlena dále v popisu synchronizace a průběhu instrukčního cyklu CPU. Seznam všech výstupních signálů sequenceru a způsob sestavení kódů mikroinstrukcí je na separátní stránce o mikroinstrukcích našeho procesoru.


Instrukční cyklus sequenceru Claudia Lite

Pokud jste si někdy četli popis činnosti nějakého komerčního procesoru, asi tam bylo uvedeno, že instrukční cyklus vždy začíná vyzvednutím operačního kódu instrukce z externí paměti programu a jeho vložení do instrukčního registru uvnitř procesoru. Ve skutečnosti tímto instrukční cyklus nezačíná, ale končí. Končí tím instrukční cyklus předešlé instrukce a na začátku instrukčního cyklu nové instrukce již její operační kód musí být uložen v instrukčním registru. V našem případě se jedná o pomocný IR* (74175), protože v hlavním IR (74163 + 7474) stále musí být zpracovávaný kód předešlé instrukce. Teprve s příchodem další náběžné hrany F1 je nový kód přepsán z IR* do IR a začíná cyklus nové instrukce.

Jelikož opakování je matkou moudrosti, tak ještě jednou: Instrukční registr Claudie Lite je zdvojený a je rozdělený na hlavní IR (74163 a 7474) a pomocný IR* (74175), přičemž hlavní IR je tvořen částečně jednobitovým registrem 7474 a částečně je sloučen s čítačem mikroinstrukcí do obvodu 74163. Tyto dva obvody dohromady tvoří hlavní instrukční registr IR s integrovaným čítačem mikroinstrukcí. Sice jsou ve schématu označeny jako IR1 a IR2, ale v dalším textu toto rozdělení nebudeme používat a budeme je považovat za jediný hlavní instrukční registr IR. Pomocný instrukční registr IR* je tvořen obvodem 74175 s asynchronním nulováním, které je zde velmi důležité.

Důvodem zdvojení instrukčního registru a zavedení pomocného IR* je zajištění správné synchronizace na začátku každého instrukčního cyklu. Nový operační kód instrukce je nejprve na konci zpracovávání předešlé instrukce přečten z vnější paměti programu a uložen do pomocného IR*. To zajistí mikroinstrukce generující signály /MEMRD+LIR2. V této chvíli je důležité, že hlavní IR obsahuje stále původní instrukci a paměť mikroinstrukcí tak zůstává adresována na mikroinstrukci /MEMRD+LIR2 a nedochází k žádné změně. Jedná se o standardní přesun dat. Mikroinstrukce /MEMRD+LIR2 však musí aktivovat také signál /LIR, který slouží k předvolbě čítače mikroinstrukcí. Jenže zde je fígl ten, že na pozici čítače je použit synchronní 74163, který na signál předvolby /LIR zareaguje synchronně až s další náběžnou hranou hodin F1. Stejnou náběžnou hranou zároveň převezme obsah pomocného IR* i jednobitový registr IR1 7474. Náběžnou hranou F1 při současné aktivaci /LIR tedy v jednom okamžiku dojde k přepisu nového operačního kódu instrukce z pomocného IR* do hlavního IR. Na adresových vstupech ROM paměti mikroinstrukcí se tedy objeví nová adresa a začíná nový instrukční cyklus synchronně s F1. Nový instrukční cyklus opět musí končit mikroinstrukcí /MEMRD+LIR2+/LIR. Důležité je, že přechod na nový instrukční cyklus je plně synchronizován s hodinami, konkrétně s F1. To, že k přepisu obsahu pomocného IR* do jednobitového 7474 probíhá s každou náběžnou hranou F1 nevadí, protože IR* svůj obsah během zpracování stávající instrukce nemění. Pochopitelně by tento přepis bylo také možné podmínit aktivním signálem /LIR, ale jsou to další hradla navíc a je to zbytečné.

Mikroinstrukce /MEMRD+LIR2+/LIR musí být vždy jako poslední mikroinstrukce každé sekvence. Tedy mikroinstrukční kód pro všechny instrukce MUSÍ vždy končit mikroinstrukcí aktivující signály /MEMRD+LIR2+/LIR. Z uvedeného popisu je patrná i synchronizace mikroinstrukčních signálů s hodinami. A sice /MEMRD je synchronizován s hodinovou fází F1 a je aktivní v LOW. LIR2 je synchronizován s fází F2 a je aktivní v HIGH. /LIR není s hodinami synchronizován vůbec a je aktivní v LOW.

Netvrdím, že toto řešení synchronizace na počátku instrukčního cyklu je jediné správné. Nicméně je vyzkoušené, funkční a snad i snadno pochopitelné.

A nyní ještě k signálu /NOP a ke způsobu jak nahustit potřebných 52 mikrokroků do 32 pozic paměti 74188. Když jsem si udělal rozklad všech instrukcí, které jsem v procesoru chtěl mít na sekvence mikroinstrukcí, všiml jsem si dvou věcí. Za prvé, že u většiny instrukcí potřebuji na jejich vykonání 3-4 mikrokroky a za druhé, že dva z těchto mikrokroků se ve většině instrukcí stále opakují. A sice tyto mikrokroky:

1) /PLONK + /INCA
2) /MEMRD + LIR2 + /LIR

V prvním uvedeném kroku dojde pouze k inkrementací (/INCA) programového čítače (synchronně s /F2) a tedy k vystavení adresy další instrukce na adresovou sběrnici paměti programu. Signál /PLONK, jak jsem již zmínil je plonkový a nedělá nic. Ve druhém kroku je pak synchronně s /F1 otevřena signálem /MEMRD paměť programu pro čtení a následně je synchronně s /F2 nahrán signálem LIR2 nový operační kód instrukce z programové paměti do pomocného IR*. Současně je aktivován signál /LIR pro přepis pomocného IR* do hlavního IR synchronně s následující náběžnou hranou F1. Časování tohoto kroku je následující:

Časování LIR

Tyto dva kroky se tedy až na vyjímky (instrukce skoků) objevují na úplný konec mikroinstrukční sekvence každé instrukce. Přišlo mi tedy zbytečné je do řídící ROM zapisoval tolikrát a tím obsazovat cenný prostor. Nešlo by je zapsat jen jednou a nějak na ně vždy skákat? Šlo:-) Navíc se ukázalo, že tyto dva kroky tvoří úplnou mikroinstrukční sekvenci instrukce NOP. A bylo vymalováno. U instrukcí, které takto mají končit stačí provést jen jejich odlišnou výkonnou část a pak skočit na sekvenci pro NOP a dokončit je pomocí mikroinstrukční sekvence pro NOP. K zajištění tohoto skoku se výborně hodí poslední zbývající bit řídící ROM. Uděláme z něj signál /NOP (aktivní v nule) a s jeho pomocí vynulujeme pomocný IR*. Tím mu vlastně vnutíme instrukci NOP, kterou si s následující náběžnou hranou F1 převezme hlavní IR a dokončí tak mikroinstrukční cyklus jako cyklus NOPu. Tím je dáno i to, že operační kód instrukce NOP musí být 00h.

Aby nedošlo k náhodnému nechtěnému nulování IR* při změně na adresových vstupech řídící ROM, je vhodné signál /NOP synchronizovat s fází /F2 a vytvořit tak jakýsi /NOP2, který bude tím nulovacím pro IR*. Je zřejmé, že společně s aktivací /NOP musíme vždy aktivovat i /LIR, aby došlo k žádoucímu přepisu IR* do IR. Tímto fíglem se počet mikroinstrukčních kroků instrukcí snížil ze 4 na 2 a bylo tak možné nacpat do 32 pozic ROM více instrukcí. Více kroků zůstalo akorát u instrukcí skoků, které výše uvedenou sekvencí končit nemohou, viz rozklad instrukcí na mikroinstrukce.


Ukázka zpracování instrukce LDA X

Pro ilustraci si ukážeme rozklad a zpracování instrukce LDA X pro přímé naplnění pracovního registru A konstantou "X" z programové paměti. Konstanta "X" se nachází na adrese následující za adresou s operačním kódem instrukce LDA. Operační kód LDA byl již vložen do IR* v rámci instrukčního cyklu předešlé instrukce. Další náběžnou hranou F1 je operační kód LDA přepsán z IR* do IR a začíná tento mikroinstrukční cyklus:

LDA X:
1) /PLONK + /INCA
2) /MEMRD + LA + /NOP + /LIR

(NOP:)
3) /PLONK + /INCA
4) /MEMRD + LIR2 + /LIR

Prvním krokem je inkrementace (/INCA) programového čítače PC, který dosud ukazoval na adresu s operačním kódem LDA. Programový čítač nyní ukazuje na adresu s konstantnou "X". V dalším kroku otevřeme s /F1 paměť pro čtení (/MEMRD) a synchronně s /F2 přepíšeme (signálem LA) konstantu X z RAM do registru A. Současně jsou aktivovány signály /LIR a /NOP. Tím zápis mikroinstrukční sekvence LDA X v paměti ROM končí. Vystačili jsme s pouhými dvěma pozicemi paměti. Ovšem ještě nekončí instrukční cyklus instrukce LDA X, který nadále pokračuje zpracováním vnucené instrukce NOP. Ta zajistí další inkrementaci programového čítače a načtení operačního kódu následující instrukce do IR*. To je vše. Jednoduchý jak facka:-)

Seznam všech implementovaných instrukcí a jejich rozklad na mikroinstrukce naleznete zde.

Seznam a význam všech mikroinstrukcí a jejich vyjádření pomocí signálů naleznete zde.

V níže uvedeném ZIPu je kompletní obsah PROM 74188 s mikroinstrukcemi pro sequencer Claudie Lite. K nahrání do paměti je určen soubor s koncovkou BIN, ale dávám k dispozici i zdrojový kód:


obsah PROM 74188



inicializace sequenceru - RESET

Zbývá ještě vysvětlit inicializaci sequenceru po zapnutí či RESETu. Signál /RESET zajistí okamžité vynulování pomocného instrukčního registru (IR*, proto je zde nutné použít 74175) a synchronně s příchodem náběžné hrany F1 také vynulování čítače mikroinstrukcí 74163 a jednobitového registru 7474 (ten převezme nulu z pomocného IR*, proto jej není nutné nulovat extra). Zde je důležité, aby operační kód 00h, odpovídající vynulovanému IR, patřil instrukci NOP! Procesoru je tak po RESETu vnucena instrukce NOP bez ohledu na to, jaká je první instrukce v externí paměti programu. NOP, jak známo, nedělá nic. Pouze inkrementuje čítač adres PC a z nové adresy v paměti programu vyzvedne další instrukci ke zpracování. Jenže právě ta inkrementace je v tuto chvíli špatně, protože procesor by pak první instrukci nečetl z adresy 00h, ale 01h programové paměti. Bylo tedy nutné během signálu /RESET zabránit v inkrementování čítače adres, respektive ho také držet v RESETu. Z výše uvedeného plynou dva požadavky na signál /RESET: musí být dostatečně dlouhý, aby během něj mohlo dojít jednak k ustálení napěťových poměrů v obvodech (po zapnutí) a hlavně k vynulování synchronního čítače 74163 a registru 7474 náběžnou hranou F1. Druhým požadavkem je to, že /RESET nesmí končit nevhod. Toto zajišťuje obvod resetu se signálem /EOR popsaný v předešlé části spolu s generátorem hodin.

RESET tedy proběhne tak, že procesoru je "vnucena" instrukce NOP, která má na adrese 00h mikroprogramové PROM mikroinstrukci zajišťující inkrementaci čítače adres pro externí paměť. Jenže po celou dobu zpracování této první mikroinstrukce je čítač adres držen v resetu a tedy nulován. RESET je uvolněn až při generování další mikroinstrukce která s F1 zajistí vystavení adresy z programového čítače PC (tedy adresy 00h) pro programovou paměť a následně s F2 načte nový operační kód další instrukce (/MEMRD+LIR2+/LIR). Tím instrukční cyklus NOP končí.

To, že se mi podařilo vyřešit startování procesoru vnucenou instrukcí NOP bez inkrementace programového čítače a tedy čtení první platné instrukce z adresy 00h programové paměti, není úplná samozřejmost. Například tvůrci komerčního procesoru SC/MP 8060 (použit například v prvním Sinclairu MK-14) si s tím neporadili a čtení programové paměti začíná až od adresy 01h. Adresa 00h se přeskakuje a nelze na ní mít žádnou platnou instrukci!


Závěrem

Výše uvedený popis sekvenceru byl hodně polopatický, ale je to opravdu nejdůležitější část procesoru a velmi tam záleží na té synchronizaci. S dalšími obvody už se tak párat snad nebudu:-)

Z předchozích odstavců je patrné, že instrukce NOP, která "nedělá nic", je veledůležitou instrukcí a proto nechybí snad v žádném instrukčním souboru žádného procesoru:-) Pochopitelně má i další využití a sice ke generování krátkých časových zpoždění, kdy třeba čekáme na ustálení dat na vstupních či výstupních portech počítače.

Dalším funkčním celkem počítače Claudia Lite je část RAM + PC, tedy blok programové paměti RAM a programového čítače PC.


Generátor hodin

RAM + PC





Tipy na zvýšení kapacity sequenceru

Pokud bychom chtěli přidat do procesoru další funkcionalitu, neobejde se to bez zvýšení kapacity sequenceru. Je zde několik možností:

První z nich již byla popsána a spočívá v navýšení bitové šířky paměti mikroinstrukcí. Tedy v připojení další paměti, jejíž adresové vstupy připojíme paralelně k té stávající a datové výstupy opatříme novými dekodéry pro generování dalších RX a TX signálů pro nové obvody uvnitř procesoru. Dekodéry nebudou třeba, pokud budeme chtít dalšími bity řídit složitější obvody s vícero řídícími vstupy, například ALU 74181, multiplexery, apod.

Další možností je zvýšení počtu instrukcí rozšířením na jejich 8-bitové kódování. To bude znamenat zdvojení instrukčních registrů, kdy do každého se bude nahrávat jedna nibble instrukčního kódu. Dohromady se složí osmibitový kód, který bude tvořit vyšší část adresy. Není to zas tak náročné a v principu se to bude synchronizovat stejně jako v prípadě 4-bitových instrukcí, jen k přepisu z pomocných IR* registrů do hlavních IR už nelze použít F1, ale speciální signál, který za tímto účelem bude nutné vytvořit. Pochopitelně je nutné použít řídící ROM s podstatně větším adresovým rozsahem a také je nutné zvýšení kapacity paměti programu počítače (každá instrukce bude zabírat více místa) a tedy i rozsahu programového čítače procesoru.

Pokud by nevyhovoval maximální počet mikrokroků na každou instrukci, lze rozšířit čítač mikroinstrukcí kaskádním připojením dalšího synchronního čítače 74163. Ale opět bude potřeba použít ROM s více adresovými vstupy. Věřili byste, že v takovém případě pro interní paměť mikroinstrukcí v procesoru potřebujete paměť s kapacitou v řádech kilobajtů?

Všechny předchozí rozšíření lze pochopitelně zkombinovat a použít "širokou" paměť, 8-bitové instrukce a více kroků mikroinstrukcí (to bude asi nutné, protože 4 kroky by asi byly málo při obsluze dvou párů IR, nebo obsluze alespoň 12-bitové adresové sběrnice).

Poslední možností je udělat procesor ryze osmibitový. To se aplikují všechna předchozí vylepšení, jen IR se budou plnit současně, nebo se rovnou použijí osmibitové registry. Ale to už je jiná písnička a obvodová složitost zapojení poletí do oblak. 4-bity stačí, drahouškové:-)


Generátor hodin

RAM + PC


RET



Odladěno na MS IE 8.0 a Firefoxu při rozlišení min. 1024 x 768 pixelů
www.NOSTALCOMP.cz    2010  -  2019