8-битный процессор Z-80 знаменит тем, что использовался во многих ранних персональных компьютерах, таких как Osborne 1, TRS-80 и Sinclair ZX Spectrum, и до сих пор применяется во встраиваемых системах и графических калькуляторах Texas Instruments (TI). Я всегда считал, что АЛУ в Z-80 имеет 8-битную разрядность, как почти у любого другого 8-битного процессора. Но во время реверс-инжиниринга Z-80 я с удивлением обнаружил, что АЛУ у него всего 4-битное! Основатели Zilog упоминали 4-битное АЛУ в очень интересной беседе в Computer History Museum, так что это не совсем секрет, но и широко известным фактом это тоже не назовёшь.

Я занимаюсь реверс-инжинирингом процессора Z-80, используя изображения команды Visual 6502. На иллюстрации ниже показана общая структура кристалла Z-80 и расположение АЛУ. Остальная часть статьи подробно разбирает АЛУ: его архитектуру, принцип работы и то, как именно оно реализовано.

Я сделал следующую блок-схему, чтобы дать общее представление о структуре АЛУ Z-80. В отличие от блок-схем Z-80, опубликованных в других местах, эта блок-схема основана на реальной топологии кристалла. АЛУ состоит из 4 однобитных ячеек, которые «сложены» в 4-битное АЛУ. Слева на схеме регистровая шина обеспечивает связь АЛУ с регистровым файлом и остальной частью процессора.

Работа АЛУ начинается с загрузки двух 8-битных операндов из регистров во внутренние защёлки. Затем АЛУ выполняет вычисление над младшими 4 битами операндов и сохраняет результат во внутренних защёлках. После этого АЛУ обрабатывает старшие 4 бита операндов. Наконец, АЛУ записывает все 8 бит результата (4 младших бита из защёлки и 4 старших бита, только что вычисленные) обратно в регистры. Таким образом, выполняя два цикла вычислений, АЛУ способно обработать все 8 бит данных. («Полные 8 бит» могут не звучать впечатляюще, если вы читаете это на 64-битном процессоре, но по тем временам этого вполне хватало.)

Как видно из блок-схемы, у АЛУ есть две внутренние 4-битные шины, подключённые к 8-битной регистровой шине: младшая шина даёт доступ к битам 0, 1, 2 и 3 регистров, а старшая шина — к битам 4, 5, 6 и 7. АЛУ использует защёлки, чтобы хранить операнды, пока не сможет их обработать. Защёлки op1 хранят первый операнд, а защёлки op2 — второй. У каждого операнда есть 4 бита в «младшей» защёлке и 4 бита в «старшей» защёлке, чтобы сохранить все 8 бит.

Мультиплексоры выбирают, какие данные используются для вычисления. Защёлки op1 подключены к мультиплексору, который выбирает либо младшие, либо старшие четыре бита. Защёлки op2 подключены к мультиплексору, который выбирает либо младшие, либо старшие четыре бита, а также позволяет выбрать либо исходное значение, либо инвертированное. Инвертированное значение используется для вычитания, отрицания и сравнения.

Два операнда поступают в «ядро АЛУ», где выполняется нужная операция: сложение, логическое И, логическое ИЛИ или логическое исключающее ИЛИ (XOR). Сначала АЛУ выполняет вычисление над младшими битами и сохраняет 4-битный результат в защёлке младшего результата. Затем АЛУ выполняет второе вычисление над старшими битами, записывая на шину сохранённый младший результат и только что вычисленные старшие биты. Перенос из первого вычисления при необходимости используется во втором вычислении.

В Z-80 есть развитые битово-адресуемые операции, позволяющие установить, сбросить или проверить один конкретный бит в байте. В битово-адресуемой операции биты 5, 4 и 3 инструкции выбирают, какой из 8 бит нужно использовать. В крайней правой части блок-схемы АЛУ показана схема выбора бита, которая поддерживает эти операции. В этой схеме простые логические элементы выбирают один из восьми бит в зависимости от команды. 8-битное значение записывается на шину АЛУ, где и используется для битово-адресуемой операции. Таким образом, декодирование этой части команды происходит прямо в АЛУ, а не в обычной логике декодирования инструкций.

Схема сдвигов в Z-80 тоже интересная. У 6502 и 8085 есть отдельная операция АЛУ для сдвига вправо, а сдвиг влево они выполняют, прибавляя число само к себе. Z-80, в отличие от них, выполняет сдвиг во время загрузки значения в АЛУ. Когда Z-80 считывает значение с регистровой шины, схема сдвига выбирает, какие линии регистровой шины использовать. Она загружает значение без изменений, со сдвигом влево на один бит или со сдвигом вправо на один бит. Биты, «вдвигаемые» в позиции 0 и 7, обрабатываются отдельно, поскольку зависят от конкретной инструкции.

На блок-схеме также показан путь от младшей шины к старшей защёлке op2 и от старшей шины к младшей защёлке op1. Это нужно для 4-битных BCD-вращений RRD и RLD, которые вращают 4-битную цифру в аккумуляторе вместе с двумя цифрами в памяти.

На блок-схеме не показаны простые схемы для вычисления чётности, проверки на ноль и проверки того, что 4-битное значение меньше 10. Эти значения используются для установки флагов состояния.

Кристалл, реализующий АЛУ

На иллюстрации выше показан увеличенный фрагмент области АЛУ на кристалле Z-80. Видны четыре горизонтальные «секции». Организация каждого слоя примерно соответствует блок-схеме. Слева видна регистровая шина, идущая вертикально; входы сдвигателя торчат из АЛУ как «пальцы», чтобы брать нужные биты. Справа видна шина данных, тоже идущая вертикально. Горизонтальные линии ALU low и ALU high видны вверху и внизу каждого слоя. Жёлтые стрелки показывают расположение некоторых компонентов АЛУ в одном из слоёв, но отдельные схемы АЛУ в таком масштабе неразличимы. 

Базовая вычислительная схема АЛУ

The silicon that implements one bit of ALU processing
Кремниевый чип, реализующий обработку одного бита АЛУ.

Сердце каждого битового разряда АЛУ — это схема, которая для двух одноразрядных операндов вычисляет бит суммы, И, ИЛИ или XOR. При увеличении видно кремний, на котором реализована эта схема; в таком масштабе уже различимы транзисторы и соединения, из которых состоят логические элементы. Питание, земля и управляющие линии выполнены вертикальными металлическими дорожками. Блес��ящие горизонтальные полосы — это «проводники» из поликремния: они образуют соединения в схеме, а также сами транзисторы. Понимаю, что это выглядит как загадочные серые линии, но если разбирать изображение методично, можно восстановить исходную схему. Схема показана на диаграмме ниже.

Схема принимает два операнда (op1 и op2) и входной перенос. Она выполняет операцию (выбираемую управляющими линиями R, S и V) и формирует внутренний перенос, выходной перенос (carry out) и результат.

Подробно о логике вычислений в АЛУ

Первый шаг — «вычисление переноса». Оно выполняется одним большим многоуровневым логическим элементом. Он берёт два бита операндов (op1 и op2) и входной перенос и вычисляет (инверсный) внутренний перенос, возникающий при сложении op1 + op2 + входного переноса. Перенос в такой сумме может возникнуть только двумя способами: если op1 и op2 оба равны 1 (нижний элемент И) или если есть входной перенос и хотя бы один из операндов равен 1 (верхние элементы). Эти два случая объединяются элементом НЕ-ИЛИ (NOR), который и выдаёт (инверсный) внутренний перенос. Затем внутренний перенос инвертируется нижним элементом НЕ-ИЛИ, образуя выходной перенос, который становится входным переносом для следующего разряда. Есть пара управляющих линий, которые слегка усложняют формирование переноса. Если S = 1, внутренний перенос принудительно устанавливается в 0. Если R = 1, выходной перенос принудительно устанавливается в 0 (а значит, и входной перенос следующего разряда).

Многоуровневый элемент вычисления результата интересен тем, что он выдаёт SUM, XOR, AND или OR. Нужно немного поработать, чтобы пройти все варианты, но если кому-то нужны детали:

  • SUM: если R = 0, S = 0 и V = 0, схема формирует младший бит суммы op1 + op2 + входного переноса, то есть op1 xor op2 xor входной перенос. Это видно так: выход равен 1, если установлены все три сигнала op1, op2 и входной перенос, или если установлен хотя бы один из них и при этом нет внутреннего переноса (то есть установлен ровно один).

  • XOR: если R = 1, S = 0 и V = 0, схема формирует op1 xor op2. Здесь логика такая же, как в предыдущем случае, но входной перенос равен 0 из-за R.

  • AND: если R = 0, S = 1 и V = 0, схема формирует op1 и op2. Сначала отметим, что внутренний перенос принудительно равен 0, поэтому нижний элемент И никогда не может сработать. Входной перенос принудительно равен 1, поэтому результат задаётся верхним элементом И.

  • OR: если R = 1, S = 1 и V = 1, схема формирует op1 или op2. Внутренний перенос принудительно равен 0 из-за S, а выходной перенос (и, значит, входной перенос) принудительно равен 0 из-за R. Поэтому верхний элемент И отключён, и результатом управляет трёхвходовой элемент ИЛИ.

Как ни странно, концептуально это намного проще, чем АЛУ 8085. Правда, понять это труднее, чем АЛУ 6502: там простые логические элементы параллельно вычисляют AND, OR, SUM и XOR, а затем нужный результат выбирается с помощью проходных транзисторов.

Заключение

АЛУ Z-80 заметно отличается от АЛУ 6502 или 8085. Самое главное различие в том, что 6502 и 8085 используют 8-битные АЛУ, тогда как в Z-80 АЛУ 4-битная. Z-80 поддерживает би��ово-адресуемые операции, которых нет у 6502 и 8085. Поддержка BCD в Z-80 более продвинутая, чем «десятичная коррекция» в 8085, потому что Z-80 умеет работать и со сложением, и с вычитанием, а 8085 — только со сложением. Зато у 6502 поддержка BCD ещё более развитая: есть флаг десятичного режима и быстрая, запатентованная логика BCD.

Если вы проектировали АЛУ на занятиях в университете, интересно сравнить «академическое» АЛУ с сильно оптимизированным АЛУ, используемым в реальном чипе. Любопытно увидеть, какие упрощения и компромиссы применяются в настоящем железе.

Я сделал более подробную принципиальную схему АЛУ Z-80: она развивает блок-схему и базовую схему выше и показывает логические элементы и транзисторы, из которых состоит АЛУ.

Надеюсь, это погружение в Z-80 убедило вас, что даже с 4-битным АЛУ Z-80 всё равно мог выполнять 8-битные операции. Ваш старый TRS-80 вас не обманул.

Если хочется перейти от абстрактных рассуждений к системной практике, посмотрите, как эти принципы применяются на курсе «Разработчик встраиваемых систем» (Embedded Developer). Чтобы узнать, подойдет ли вам программа курса, пройдите вступительный тест.

Для знакомства с форматом обучения и экспертами приходите на бесплатные уроки:

  • 17 февраля, 20:00. «Разработка встраиваемых устройств для интернета вещей». Записаться

  • 24 февраля, 20:00 — «Айпи-форвардинг в L2 и L3 сегментах». Записаться

  • 10 марта, 20:00. «Создаём автономную сеть: Обходимся без роутера с ESP32)». Записаться

Полный список открытых уроков в календаре мероприятий.