Дешифратор команд V2 (Decoder V2)

Входы (Inputs)

ПинТипОписание
Instrbus8Байт инструкции из ROM (биты 7:4 = opcode, биты 3:0 = operand)

Выходы (Outputs)

ПинТипОписание
ALUOp0bitМладший бит кода операции АЛУ
ALUOp1bitСтарший бит кода операции АЛУ
MemWrbitСигнал записи в RAM (1 = запись)
JumpUncondbitБезусловный переход (JMP)
JumpZerobitПереход по нулю (JZ), отдельный выход
JumpNegbitПереход по минусу (JN), отдельный выход
RegLoadbitВыбор источника данных аккумулятора (операнд или RAM)
ACC_WEbitРазрешение записи в аккумулятор (WE регистра)
ImmOpbitВыбрать непосредственный операнд из ROM (LDA)
IXLoadbitЗагрузка индексного регистра (LDX)
IXIncbitИнкремент индексного регистра (INX)
UseIXbitАдрес 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КомандаАктивные сигналы
0NOPнет
1ADDACC_WE
2SUBALUOp0, ACC_WE
3ANDALUOp1, ACC_WE
4ORALUOp0, ALUOp1, ACC_WE
5LDARegLoad, ACC_WE, ImmOp
6STAMemWr
7JMPJumpUncond
8JZJumpZero
9LDXIXLoad
10LDAXRegLoad, ACC_WE, UseIX
11STAXMemWr, UseIX
12JNJumpNeg
13INXIXInc
14резервнет
15HLTнет

Каждая строка задаёт полный набор сигналов такта: аккумулятор пишется только там, где в таблице есть 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. В такте перехода аккумулятор не меняется, поэтому флаги стабильны.