Дешифратор команд V2 (Decoder V2)
Входы (Inputs)
| Пин | Тип | Описание |
|---|---|---|
| Instr | bus8 | Байт инструкции из ROM (биты 7:4 = opcode, биты 3:0 = operand) |
Выходы (Outputs)
| Пин | Тип | Описание |
|---|---|---|
| ALUOp0 | bit | Младший бит кода операции АЛУ |
| ALUOp1 | bit | Старший бит кода операции АЛУ |
| MemWr | bit | Сигнал записи в RAM (1 = запись) |
| JumpUncond | bit | Безусловный переход (JMP) |
| JumpZero | bit | Переход по нулю (JZ), отдельный выход |
| JumpNeg | bit | Переход по минусу (JN), отдельный выход |
| RegLoad | bit | Выбор источника данных аккумулятора (операнд или RAM) |
| ACC_WE | bit | Разрешение записи в аккумулятор (WE регистра) |
| ImmOp | bit | Выбрать непосредственный операнд из ROM (LDA) |
| IXLoad | bit | Загрузка индексного регистра (LDX) |
| IXInc | bit | Инкремент индексного регистра (INX) |
| UseIX | bit | Адрес RAM берётся из IX (LDAX, STAX) |
Чем V2 отличается от базового Decoder
Протокол тот же: Decoder V2 читает опкод (старшие биты 7:4 байта Instr) и остаётся комбинационной схемой без тактов и памяти. Изменился набор сигналов: двенадцать выходов вместо девяти.
Три отличия. Первое: JZ и JN получили отдельные выходы JumpZero и JumpNeg. У базового Decoder один выход JumpCond обслуживает оба кода (8 и 12), и различить команды в готовой схеме невозможно. Второе: сигнал ACC_WE подключается к входу WE аккумулятора и разрешает запись только в нужных тактах. В базовой разводке аккумулятор не имел load-enable и принимал результат на каждом такте, поэтому приходилось «держать его в узде» программно. Третье: готовый выход ImmOp выбирает непосредственный операнд для LDA; в базовой разводке тот же результат собирали из внешних вентилей NOT и AND.
Таблица сигналов
| Opcode | Команда | Активные сигналы |
|---|---|---|
| 0 | NOP | нет |
| 1 | ADD | ACC_WE |
| 2 | SUB | ALUOp0, ACC_WE |
| 3 | AND | ALUOp1, ACC_WE |
| 4 | OR | ALUOp0, ALUOp1, ACC_WE |
| 5 | LDA | RegLoad, ACC_WE, ImmOp |
| 6 | STA | MemWr |
| 7 | JMP | JumpUncond |
| 8 | JZ | JumpZero |
| 9 | LDX | IXLoad |
| 10 | LDAX | RegLoad, ACC_WE, UseIX |
| 11 | STAX | MemWr, UseIX |
| 12 | JN | JumpNeg |
| 13 | INX | IXInc |
| 14 | резерв | нет |
| 15 | HLT | нет |
Каждая строка задаёт полный набор сигналов такта: аккумулятор пишется только там, где в таблице есть ACC_WE, память пишется только по MemWr.
Разводка условных переходов
Флаги снимаются с выходов регистра ACC, а не с живого выхода АЛУ. Флаг N даёт Splitter на шине ACC: бит 7 попадает на вентиль AND вместе с JumpNeg. Флаг Z даёт zero-детектор (BusZero) на выходе ACC: его результат складывается по AND с JumpZero. Дальше оба условия и JumpUncond собираются двумя вентилями OR на вход Load счётчика команд:
AND(JumpNeg, ACC[7]) → OR(JumpUncond, ·) → OR(·, AND(JumpZero, Zero(ACC))) → PC.Load
В такте перехода ACC_WE равен нулю, аккумулятор не меняется, и флаги остаются теми, что были после последней арифметики. С базовым Decoder флаг снимался с выхода АЛУ прямо в такте JN: АЛУ считал ACC + RAM[адрес метки], и переход зависел от содержимого ячейки, на которую указывает метка.
Применение
Decoder V2 доступен в палитре песочницы: рецепт «Процессор с ассемблером» собран на нём и исполняет все 15 команд, включая JZ, косвенную адресацию через IX и семейство LDX/INX. Базовый Decoder остаётся в уровнях 25–29 и во всех сохранённых схемах: копировать их не нужно, старые разводки продолжают работать.
Смежные компоненты
Статьи по теме
Частые вопросы
Чем Decoder V2 отличается от базового Decoder?
Двенадцать выходов вместо девяти: JZ и JN разведены по отдельным выходам JumpZero и JumpNeg, добавлены ACC_WE (разрешение записи в аккумулятор) и ImmOp (выбор непосредственного операнда).
Зачем нужен сигнал ACC_WE?
Он подключается к входу WE регистра-аккумулятора. Запись происходит только в тактах, где ACC_WE = 1: команды STA, JMP, JZ, JN, NOP и HLT не меняют аккумулятор.
Откуда брать флаги для JZ и JN?
С выходов регистра ACC: zero-детектор (BusZero) даёт флаг Z, бит 7 через Splitter даёт флаг N. В такте перехода аккумулятор не меняется, поэтому флаги стабильны.