Я решил внести и обсудить некоторые модификации в схемотехнику
4-bit CPU, которые должны позволить ввести довольно оригинальный механизм возврата из подпрограмм без значительного усложнения схемотехники.
Для реализации безусловного перехода
JMP ADDR используем в конструкции в качестве программного 12-разрядного счётчика
PC, позволяющего адресовать
2^12 = 4096 слов памяти программ, три 4–битных счётчика типа
К155ИЕ7 с опцией параллельной загрузки. Выходы счётчиков через регистры с тристабильным выходом подключены к адресным линиям ОЗУ программ.
Входы же счётчиков поразрядно
подключены к 12 выходным тристабильным линиям данных микросхем ОЗУ программ.
Четыре оставшиеся линии данных микросхем ОЗУ выводят
код команды на входы ПЗУ микропрограмм.
В свете такого аппаратного решения безусловный переход
JMP ADDR в разрабатываемом ЦПУ реализуется параллельной загрузкой в программный счётчик
PC 12–ти бит адреса перехода по стробу параллельной загрузки
/STB ADDR.
Поскольку реализация аппаратного стека в такой простой конструкции, конструируемой по
RISC–концепции, вызывает неоправданное усложнение,
первоначально было решено реализовать стек хотя бы с одним адресом возврата. С этой целью в конструкцию вводились три 4–битных регистра с тристабильными выходными линиями, входы которых подключались к выходам 12–ти битного программного счётчика
PC, а выходы — к его входам. При вызове подпрограммы
CALL ADDR, адрес возврата фиксировался в трёх 4–битных регистрах по стробу
/STB RETADDR, а в 12–ти битный программный счётчик записывался адрес перехода с линий данных микросхем ОЗУ программ по сигналу
/STB ADDR. При выполнении команды возврата
RET выходы трёх 4–битных регистров по сигналу
/E RETADDR подают адрес возврата на входы 12–ти битного программного счётчика, куда он и записывается по стробу
/STB ADDR.
Такое решение в значительной мере бюджетно и минимально с точки зрения схемотехники. Процессоры с одноуровневым стеком известны, но глубина стека в один адрес возврата несколько неудобна, как показывает практика.
Известно также решение по реализации механизма возврата из подпрограмм без использования стека адресов возврата. Оно заключается
в записи адреса возврата в первую ячейку подпрограммы (
JMS SUBR). При этом сама подпрограмма заканчивается оператором косвенного перехода по значению, записанному в первой ячейке подпрограммы. У решения имеются и недостатки: невозможно прервать и повторно вызвать ту же самую подпрограмму (невозможность рекурсии), а, кроме того, подпрограммы должны находиться в оперативной памяти.
С аппаратной точки зрения метод хотя и проще механизма стека адресов возврата, но всё же достаточно сложен для схемотехники простого ЦПУ.
На мой взгляд,
наиболее простой в существующих условиях является модификация этого метода, которая заключается в том, что в первую ячейку подпрограммы будем записывать не адрес возврата, а команду безусловного перехода на адрес возврата JMP RETADDR целиком, вместе с кодом операции. При этом для формирования кода команды
JMP в схему
добавим всего один дополнительный 4–битный регистр с тристабильными выходными линиями, на входе которого значение кода команды
JMP будет формироваться подключением их соответственно к сигналам логических уровней нуля и единиц. Подпрограмма в таком случае заканчивается безусловным переходом
JMP ADDR на адрес её первой ячейки, где, собственно, предварительно и была записана команда безусловного перехода
JMP RETADDR на адрес возврата.
Рассмотрим весь механизм несколько подробнее.
1. В цикле выполнения команды вызова подпрограммы
JMS SUBR ЦПУ вначале выполняет инструкцию выборки кода команды
FETCH, которая заключается в фиксации текущего значения программного счётчика
PC в регистре адреса сигналом
STB INSTR, и в инкременте значения
PC на единицу сигналом
INC PC.
2. В этот момент счётчик
PC содержит значение адреса возврата, которое фиксируется тремя 4–битными регистрами по сигналу
/STB RETADDR. В четвёртый регистр по этому же сигналу записывается значение кода
JMP. Таким образом, во всех четырёх регистрах записана комбинация бит
JMP RETADDR. Сигнал
/STB RETADDR блокирует следующую инструкцию
FETCH, (либо на ПЗУ, либо переключив строб чтения ОЗУ).
3. По сигналу
/E INSTR DATA на входы программного счётчика
PC выдаётся адрес подпрограммы
SUBR, который и записывается в
PC по сигналу
/STB ADDR. Эти операции выполняются за 4 такта цикла выполнения команды.
4. После этого должен выполниться следующий цикл выборки кода команды
FETCH, но ранее сигналом она была заблокирована, поскольку вместо выборки кода команды нам необходимо выполнить запись по адресу, содержащемуся в программном счётчике
PC. Для этого значение
PC выводим в регистр адреса сигналом
STB INSTR, и увеличиваем значения
PC на единицу сигналом
INC PC.
Адрес начала подпрограммы зафиксирован на линиях адреса ОЗУ программ, в то же время
PC содержит адрес следующей ячейки. Эта часть цикла аналогична выполнению команды
FETCH, но во второй части цикла сигналом
/E RETADDR подадим код комбинации
JMP RETADDR с выходов четырёх регистров на
входы данных микросхем ОЗУ программ. После чего запишем этот код в ОЗУ программ стробом
/PRG WRITE. Сигнал
/E RETADDR должен разблокировать выполнение команды
FETCH на следующем цикле. Поэтому следующей будет выполняться первая инструкция подпрограммы,
по начальному же адресу вызова подпрограммы нами записана инструкция
JMP RETADDR.
5. Возврат из подпрограммы осуществляется в её конце безусловным переходом
JMP ADDR на адрес начала подпрограммы, где хранится записанный ранее код безусловного перехода
JMP RETADDR на адрес возврата из подпрограммы. Механизмы работы безусловных переходов вместе с действующими управляющими сигналами подробно описаны выше.
Замечания:
в схеме, которая существует на данный момент, выходы ОЗУ инструкций подключены на входы ПЗУ микрокоманд через вентили постоянно, поскольку активный сигнал /RUN MODE постоянно подаёт сигналы на входы выборки /CS ОЗУ инструкций. Чтобы иметь возможность реализовать изложенный выше механизм возврата из подпрограмм схемотехнику следует изменить, введя регистр инструкций (команд, кодов операций) и фиксируя в нём инструкцию, а выходы ОЗУ инструкций выключать после фиксации инструкции.
Возможно, ширину инструкции следует увеличить до 8 бит, что позволит более просто схемотехнически ввести либо 2 префикса (Eh, Fh), либо расширить систему команд до 2^8 = 256 инструкций. С двумя префиксами получим 16+16+14=36 команд.
Инструкция, ВЫБОРКА (FETCH код 00H), всегда используется логикой микрокоманд в тактах 1 – 3 и никогда не должна использоваться программой. Лучше вынести код FETCH за 15H, подав вывод 8 счетчика импульсов 74LS93(ИЕ5) на один из старших адресов ПЗУ микрокоманд (573РФ2,5) через инвертор. В этом случае код 00H может быть назначен операции NOP, что удобно для замещения отдельных кодов даже в ПЗУ. Это даст возможность заблокировать инструкцию FETCH в цикле записи адреса возврата.
PS. Единственное чего не хватает, это косвенной адресации... не вижу как массив обработать...
Хотя бы PIC-овский RETLW пригодился... надо обдумать...