Урок 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 при сбросе: иначе при включении он стоит в «ничего», как любая защёлка.
НЕ CLK2 даёт сам триггер (нога nQ) — отдельный NOT не нужен.
5.2. Почему теперь не ломается
На осциллографе видно: адрес меняется в одном срезе, окно открывается через срез и закрывается за два среза до следующей смены адреса. Нет ни одного среза, где «новый адрес» и «открытое окно» были бы одновременно.
Цена. Команда занимает два периода CPUCLK — процессор стал вдвое медленнее. На последних уровнях игры шаг может не успевать; играть удобнее в Fast.
5.3. Сборка
Всё внутри GW-CPU («Редактировать»). Ноги чипа и всё снаружи — без изменений.
Шаг 1. Удалить окно урока 4
| Элемент | Действие |
|---|---|
| NOT, выход которого = nCLK | удалить |
| AND, выход которого = weRAM | удалить |
Шаг 2. Делитель и новое окно
Что собираем. NOT сброса, AND делителя, DFF и AND3 окна. Выход AND3 — снова метка weRAM, поэтому WE памяти перецеплять не нужно.
| Элемент | Нога | Направление | Метка |
|---|---|---|---|
| NOT | I0 | вход | RST |
| NOT | O0 | выход | nRST |
| AND | I0 | вход | nCLK2 |
| AND | I1 | вход | nRST |
| AND | O0 | выход | dCLK2 |
| DFF | D | вход | dCLK2 |
| DFF | CLK | вход | CPUCLK |
| DFF | Q | выход | CLK2 |
| DFF | nQ | выход | nCLK2 |
| AND3 | I0 | вход | oST |
| AND3 | I1 | вход | nCLK2 |
| AND3 | I2 | вход | CPUCLK |
| AND3 | O0 | выход | weRAM |
Шаг 3. Регистры на CLK2
У каждого из 28 регистров на ноге CLK своя метка CPUCLK — переименовать её двойным кликом в CLK2.
⚠ Одна из этих меток соединена проводом ещё и с ногой-портом CPUCLK чипа. Её не переименовывать: у того регистра отрезать провод от неё и поставить на CLK новую метку CLK2. Иначе на CLK2 уедет вход чипа, и делитель перестанет делить.
| Элемент | Нога | Было | Стало |
|---|---|---|---|
| Memory (RAM) ACC | CLK | CPUCLK | CLK2 |
| Memory (RAM) FZ | CLK | CPUCLK | CLK2 |
| Memory (RAM) FC | CLK | CPUCLK | CLK2 |
| Memory (RAM) PC | CLK | CPUCLK | CLK2 |
| Memory (RAM) PH | CLK | CPUCLK | CLK2 |
| Memory (RAM) PT | CLK | CPUCLK | CLK2 |
| Memory (RAM) P | CLK | CPUCLK | CLK2 |
| Memory (RAM) HT | CLK | CPUCLK | CLK2 |
| Memory (RAM) H | CLK | CPUCLK | CLK2 |
| Memory (RAM) MT | CLK | CPUCLK | CLK2 |
| Memory (RAM) M | CLK | CPUCLK | CLK2 |
| Memory (RAM) STK | CLK | CPUCLK | CLK2 |
| Memory (RAM) STATE | CLK | CPUCLK | CLK2 |
| Memory (RAM) T0 | CLK | CPUCLK | CLK2 |
| Memory (RAM) T0HI | CLK | CPUCLK | CLK2 |
| Memory (RAM) T1 | CLK | CPUCLK | CLK2 |
| Memory (RAM) T1HI | CLK | CPUCLK | CLK2 |
| Memory (RAM) T2 | CLK | CPUCLK | CLK2 |
| Memory (RAM) T2HI | CLK | CPUCLK | CLK2 |
| Memory (RAM) T3 | CLK | CPUCLK | CLK2 |
| Memory (RAM) T3HI | CLK | CPUCLK | CLK2 |
| Memory (RAM) ARMS | CLK | CPUCLK | CLK2 |
| Memory (RAM) BODY | CLK | CPUCLK | CLK2 |
| Memory (RAM) MISS | CLK | CPUCLK | CLK2 |
| Memory (RAM) OVER | CLK | CPUCLK | CLK2 |
| Memory (RAM) FALL | CLK | CPUCLK | CLK2 |
| Memory (RAM) COMET | CLK | CPUCLK | CLK2 |
| Memory (RAM) LEVEL | CLK | CPUCLK | CLK2 |
Порт 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)Не получается? Что-то не работает →