Урок 5. Двухфазный такт: запись не встречается с новым адресом

В картинках

После этого урока игра работает на вашей памяти без ошибок — в Fast и в REAL. Для этого процессор начнёт делать каждую команду за две фазы: в первой устанавливаются адрес и команда, во второй — запись. Так устроены настоящие процессоры: у Intel 8080 и MOS 6502 два такта, φ1 и φ2.


5.1. Идея: разнести «новый адрес» и «запись» по разным срезам

Из урока 4: беда в том, что окно записи открывается и закрывается на тех же фронтах, где меняется адрес. Решение — дать каждой команде два периода быстрого такта:

  • делитель на 2: DFF, у которого nQ возвращается на вход D, на каждом фронте CPUCLK переворачивается — получается медленный такт CLK2;
  • все регистры процессора (PC, аккумулятор, флаги, стек, экранные защёлки — 28 штук) шагают по CLK2: фаза ① — адрес и команда меняются и устанавливаются;
  • окно записи weRAM = AND3(oST, nCLK2, CPUCLK) — фаза ②: вторая половина CLK2, и только пока CPUCLK = 1. Оно закрывается за полтакта CPUCLK до того, как CLK2 сдвинет PC;
  • AND с nRST держит делитель в 0 при сбросе: иначе при включении он стоит в «ничего», как любая защёлка.
DFFделитель на 2DCLKQnQCPUCLKCLK2→ все регистрыnCLK2RSTnRSTdCLK2oSTAND3weRAM
Двухфазный такт. Триггер DFF, у которого nQ через AND возвращается на D, делит CPUCLK на 2 — получается CLK2, на нём шагают все регистры. AND с nRST держит делитель в 0 при сбросе. Окно записи — AND3(oST, nCLK2, CPUCLK): команда ST (oST от дешифратора), вторая половина CLK2 и только пока CPUCLK = 1.

НЕ CLK2 даёт сам триггер (нога nQ) — отдельный NOT не нужен.

5.2. Почему теперь не ломается

CPUCLKCLK2ir0-7611413oSTweRAM① адрес② окноследующий адресокно закрылось за 2 среза до смены адреса
Осциллограф, урок 5. Процессор шагает по CLK2 — вдвое реже CPUCLK. ① на фронте CLK2 меняется адрес и команда успевает устояться; ② через срез открывается окно weRAM и закрывается задолго до следующей смены адреса. Ни один срез не содержит одновременно «новый адрес» и «открытое окно».

На осциллографе видно: адрес меняется в одном срезе, окно открывается через срез и закрывается за два среза до следующей смены адреса. Нет ни одного среза, где «новый адрес» и «открытое окно» были бы одновременно.

Цена. Команда занимает два периода CPUCLK — процессор стал вдвое медленнее. На последних уровнях игры шаг может не успевать; играть удобнее в Fast.

5.3. Сборка

Всё внутри GW-CPU («Редактировать»). Ноги чипа и всё снаружи — без изменений.

Шаг 1. Удалить окно урока 4

ЭлементДействие
NOT, выход которого = nCLKудалить
AND, выход которого = weRAMудалить

Шаг 2. Делитель и новое окно

Что собираем. NOT сброса, AND делителя, DFF и AND3 окна. Выход AND3 — снова метка weRAM, поэтому WE памяти перецеплять не нужно.

ЭлементНогаНаправлениеМетка
NOTI0входRST
NOTO0выходnRST
ANDI0входnCLK2
ANDI1входnRST
ANDO0выходdCLK2
DFFDвходdCLK2
DFFCLKвходCPUCLK
DFFQвыходCLK2
DFFnQвыходnCLK2
AND3I0входoST
AND3I1входnCLK2
AND3I2входCPUCLK
AND3O0выходweRAM

Шаг 3. Регистры на CLK2

У каждого из 28 регистров на ноге CLK своя метка CPUCLK — переименовать её двойным кликом в CLK2.

⚠ Одна из этих меток соединена проводом ещё и с ногой-портом CPUCLK чипа. Её не переименовывать: у того регистра отрезать провод от неё и поставить на CLK новую метку CLK2. Иначе на CLK2 уедет вход чипа, и делитель перестанет делить.

ЭлементНогаБылоСтало
Memory (RAM) ACCCLKCPUCLKCLK2
Memory (RAM) FZCLKCPUCLKCLK2
Memory (RAM) FCCLKCPUCLKCLK2
Memory (RAM) PCCLKCPUCLKCLK2
Memory (RAM) PHCLKCPUCLKCLK2
Memory (RAM) PTCLKCPUCLKCLK2
Memory (RAM) PCLKCPUCLKCLK2
Memory (RAM) HTCLKCPUCLKCLK2
Memory (RAM) HCLKCPUCLKCLK2
Memory (RAM) MTCLKCPUCLKCLK2
Memory (RAM) MCLKCPUCLKCLK2
Memory (RAM) STKCLKCPUCLKCLK2
Memory (RAM) STATECLKCPUCLKCLK2
Memory (RAM) T0CLKCPUCLKCLK2
Memory (RAM) T0HICLKCPUCLKCLK2
Memory (RAM) T1CLKCPUCLKCLK2
Memory (RAM) T1HICLKCPUCLKCLK2
Memory (RAM) T2CLKCPUCLKCLK2
Memory (RAM) T2HICLKCPUCLKCLK2
Memory (RAM) T3CLKCPUCLKCLK2
Memory (RAM) T3HICLKCPUCLKCLK2
Memory (RAM) ARMSCLKCPUCLKCLK2
Memory (RAM) BODYCLKCPUCLKCLK2
Memory (RAM) MISSCLKCPUCLKCLK2
Memory (RAM) OVERCLKCPUCLKCLK2
Memory (RAM) FALLCLKCPUCLKCLK2
Memory (RAM) COMETCLKCPUCLKCLK2
Memory (RAM) LEVELCLKCPUCLKCLK2

Порт CPUCLK и метки CPUCLK у DFF и AND3 остаются на CPUCLK.

5.4. Проверка

Движок Fast, такт MAX, программа — та же game-myram.rom.json.

Что делаешьЧто видишь
включитьчасы 12:00
держать Q / A / P / Lрука: верхняя левая / нижняя левая / верхняя правая /
нижняя правая
STARTкристаллы катятся по трубам до края, рука их ловит
осциллограф: те же щупы +окно weRAM — через срез после смены адреса, закрывается
GW-CPU.CLK2до следующей

Если не так:

ВидноГде смотреть
часы стоятделитель: DFF CLK = CPUCLK, D = dCLK2,
AND(nCLK2, nRST) → dCLK2; nRST = NOT(RST)
процессор идёт вдвое быстрее нужногоCLK2 попал на порт CPUCLK (см. ⚠ в шаге 3)
часть регистров «отстаёт»какой-то регистр остался на CPUCLK — таблица шага 3

Вставка урока 5 (Cmd+I)

В режиме редактирования GW-CPU, после шага 1. Шаг 3 (28 меток) — руками.

# Урок 5 — двухфазный такт.# Вставка: Cmd+I В РЕЖИМЕ РЕДАКТИРОВАНИЯ чипа GW-CPU, после шага «удалить» (NOT → nCLK и AND → weRAM урока 4).# CLK2 — медленный такт процессора (CPUCLK / 2): на нём все регистры.# Окно записи — во второй половине CLK2 и только пока CPUCLK = 1: закрывается за полтакта до смены адреса. # ---------- делитель такта на 2 (со сбросом) ----------NOT(RST, nRST)AND(nCLK2, nRST, dCLK2)DFF(D=dCLK2, CLK=CPUCLK, Q=CLK2, nQ=nCLK2) # ---------- окно записи памяти ----------AND3(oST, nCLK2, CPUCLK, weRAM)

Не получается? Что-то не работает →