Проектирование процессорных ядер.
Часть 1. Цели, задачи, инструменты

PDF версия
Проектирование процессоров является несомненно актуальным направлением современной электроники. Процессоры уверенно ассоциируются с высокотехнологичными изделиями, и владение методикой их проектирования открывает широкие возможности для организации или специалиста. Вместе с тем в настоящее время явно недостаточно русскоязычной литературы, освещающей практические вопросы проектирования процессоров с точки зрения цифровой электроники. Предлагаемый цикл статей описывает различные аспекты проектирования микропроцессоров и их прототипирования на базе программируемых логических интегральных схем, что предоставляет возможность практической работы с процессорной техникой не только для крупных организаций, но и для небольших лабораторий и даже разработчиков энтузиастов. В процессе описания используется преимущественно язык описания аппаратуры VHDL в сочетании с элементной базой компании Xilinx.

Введение

Для современной интегральной электроники характерно постоянное повышение стоимости подготовки производства с одновременным уменьшением себестоимости изготовления одного экземпляра микросхемы. Это обусловливает высокую экономическую эффективность выпуска крупных партий однотипных полупроводниковых изделий, для которых высокие затраты на подготовку производства окупаются за счет большого серийного объема. Однако существуют не только риски, связанные с ошибками при выполнении разработки или подготовки производства, но и организационно-экономические риски, проистекающие из неверной оценки рыночной потребности в продуктах или требуемых технических характеристик. В таком случае даже устройство, выполненное в соответствии с условиями технического задания, не может окупить затраты на проект из-за своей экономической нецелесообразности, обнаруживающейся уже после вывода решения на рынок.

Существенный объем безвозвратных финансовых потерь, вероятных при выпуске оригинальной микроэлектронной компонентной базы, существенно ограничивает круг российских организаций, ориентирующихся на данный подход к изготовлению этого вида продукции. Поскольку номенклатура готовых изделий, доступных со стороны российских предприятий, весьма мала, широко распространен порядок разработки, основанный на использовании приобретаемых электронных компонентов зарубежного происхождения. Большинство отечественных компаний не заинтересовано в выпуске устройств с заказом новых интегральных микросхем, и происходит это по причинам, указанным выше, — весьма значительного уровня безвозвратных финансовых потерь и высокой степени риска, связанного с сильной конкуренцией со стороны зарубежных производителей ИС.

Эффективным способом повышения привлекательности вновь разрабатываемой элементной базы является предоставление потенциальным потребителям программных и аппаратных эмуляторов будущей продукции, в том числе возможности конфигурирования изделия и тестирования макетов при работе с реальными объектами управления и источниками сигналов. Получение результатов испытаний макета создаваемой ИС становится существенным аргументом в пользу начала ее массовой разработки, а низкая стоимость моделирования и макетирования минимизирует финансовые потери, если внедрение вновь разрабатываемой микросхемы будет признано нецелесообразным.

Упрощенная схема FPGA

Рис. 1. Упрощенная схема FPGA

Прототипы цифровых микросхем, в том числе процессоров, обычно выполняют на базе программируемых логических интегральных схем (ПЛИС). Эти микросхемы, выпускаемые такими компаниями, как Xilinx, Intel (Altera), Microsemi, Lattice, позволяют разрабатывать широчайший спектр цифровых устройств на основе матрицы логических ячеек с программируемым поведением и программируемой архитектурой внутренних соединений. Упрощенная схема ПЛИС с архитектурой FPGA представлена на рис. 1.

Кроме логических ячеек, реализующих базовые элементы цифровых схем — триггеры и логические вентили, — FPGA содержат непрограммируемые аппаратные блоки, осуществляющие часто встречающиеся в проектах функции. К числу основных блоков такого типа относятся:

  • блоки статической синхронной памяти (BRAM, Block RAM);
  • блоки умножителей независимых операндов, или так называемые секции DSP, реализующие умножение или умножение с накоплением;
  • компоненты формирования тактового сигнала: DLL или PLL.

Некоторые семейства микросхем FPGA могут иметь также аппаратные ядра следующих типов:

  • высокоскоростные последовательные приемопередатчики (MGT) для передачи сигналов со скоростями 3,125–32 Гбит/с;
  • аппаратные контроллеры памяти DDR2/3;
  • аппаратные контроллеры PCI Express;
  • аппаратные процессоры (PowerPC, ARM).

Микросхемы с архитектурой FPGA, выпускаемые в настоящее время, содержат от 4 тыс. до 4,5 млн логических ячеек. Следует отличать их от более простых микросхем CPLD (Complex Programmable Logic Device), которые имеют более простую структуру и существенно меньший логический объем 32–512 (1024) ячеек. Микросхемы CPLD (Intel (Altera) MAX 10, Xilinx CoolRunner II) предназначены в основном для замены дискретных компонентов, выполнены по более простым технологическим процессам и имеют значительные ограничения, не позволяющие в полной мере использовать их для прототипирования процессоров. Нужно отметить, что существуют проекты несложных 8‑разрядных микроконтроллеров, которые возможно разместить в некоторых CPLD (например, софт-процессор PicoBlaze).

Платы начального уровня Avnet Spartan‐6 Microboard и Digilent Arty на базе Artix‐7

Рис. 2. Платы начального уровня Avnet Spartan‐6 Microboard и Digilent Arty на базе Artix‐7

На рис. 2–5 показаны платы на базе FPGA Xilinx, пригодные для прототипирования процессоров и устройств на их основе.

Плата Zedboard на базе СНК Zynq‐7000

Рис. 3. Плата Zedboard на базе СНК Zynq‐7000

Платы имеют существенно различающиеся возможности: от Microboard и Arty начального уровня, с учетом цены пригодные даже для домашней лаборатории, до модуля HAPS производства Synopsys, содержащего несколько FPGA большого логического объема.

Плата KC‐705 производства Xilinx на базе ПЛИС Kintex‐7

Рис. 4. Плата KC‐705 производства Xilinx на базе ПЛИС Kintex‐7

Модуль HAPS‐70 Series производства Synopsys для прототипирования сверхбольших ИС

Рис. 5. Модуль HAPS‐70 Series производства Synopsys для прототипирования сверхбольших ИС

 

Программные инструменты разработки проектов на базе ПЛИС

Производители ПЛИС выпускают САПР для сквозного проектирования цифровых систем — от ввода исходного описания до программирования микросхемы. Такие САПР обычно поддерживают языки описания аппаратуры (Hardware Description Language, HDL), с помощью которых можно описать требуемое поведение микросхемы.

Внешний вид САПР ISE Xilinx, предназначенного для работы с семейством Spartan‐6

Рис. 6. Внешний вид САПР ISE Xilinx, предназначенного для работы с семейством Spartan‐6

На рис. 6 показан внешний вид САПР Xilinx ISE, а на рис. 7 — более современной САПР Xilinx Vivado. Несмотря на то, что ISE в настоящее время не поддерживается, она требуется для работы с семейством ПЛИС Spartan‑6 (рис. 2), которое отсутствует в Vivado.

Внешний вид САПР Vivado Xilinx

Рис. 7. Внешний вид САПР Vivado Xilinx

В составе семейства Spartan‑6 имеются микросхемы, выполненные в корпусе TQFP‑144 с шагом выводов 0,5 мм, что делает возможным их монтаж на двусторонних печатных платах с использованием широкодоступного оборудования. Это позволяет быстро и с небольшими затратами разрабатывать собственные платы, демонстрирующие управление различными устройствами с помощью процессоров.

Необходимо разделить проекты процессоров на прототипы будущих заказных микросхем (ASIC — Application-Specific Integrated Circuits) и на так называемые софт-процес-соры — процессоры, собираемые из программируемых ячеек и изначально проектируемые для будущей эксплуатации в составе проектов в ПЛИС. Формально прототип процессора также является софт-процессором, поскольку состоит из программируемых ресурсов ПЛИС. Однако смысл разделения заключается в том, что решения, эффективные для ПЛИС с учетом архитектуры этих микросхем, не обязательно будут выигрышны для ASIC и наоборот. В таблице приведены краткие сравнительные сведения о ресурсах ПЛИС с архитектурой FPGA и соответствующих ресурсах ASIC, доступных для оригинальных проектов.

Таблица. Сравнительные сведения о ресурсах FPGA и ASIC

 

FPGA

ASIC

Регистры

Размещены в ячейках FPGA

Нет ограничений по размещению

Логика

Сложность и быстродействие определяются архитектурой LUT. Мелкая гранулярность
(fine-grained), требуется схемотехническая оптимизация с учетом характеристик LUT

Нет ограничений, возможна оптимизация путем выбора вентиля с большим быстродействием и энергопотреблением

Статическая память

Аналогична ASIC, количество блоков и разрядность заданы производителем FPGA

Нет ограничений, используются компоненты, оптимизированные фабрикой

Умножители независимых операндов
и блоки «умножение с накоплением»

Реализованы производителем FPGA и оптимизированы для выбранного производителем технологического процесса

Сложность достижения высокого качества реализации, часто необходимо приобретение IP-ядра, оптимизированного под выбранный технологический процесс

Тактовые сети

Реализованы производителем FPGA и оптимизированы для выбранного производителем технологического процесса

Требуется самостоятельная реализация тактовых сетей для обеспечения синхронного распространения тактового сигнала

Цепи сброса

Реализованы производителем FPGA,
обеспечен гарантированный сброс компонентов при включении питания

Требуется самостоятельная реализация цепей сброса компонентов при включении питания

Анализ таблицы показывает, что логика общего назначения имеет в ASIC существенно лучшие показатели, поскольку реализуется не на базе логических генераторов (LUT), а непосредственно в том виде, в котором требуется для конкретного узла. Отсутствие программируемых соединений (с металлическими проводниками вместо них) обеспечивает более высокое быстродействие и меньшее энергопотребление. Поэтому тактовые частоты ASIC при сопоставимых характеристиках технологического процесса могут быть в 3–5 раз выше, чем для FPGA.

Анализ той же таблицы демонстрирует, что при проектировании процессора важно определить, разрабатывается прототип будущего ядра, входящего в состав ASIC ,или же проект изначально предназначен для работы в ПЛИС. Для ПЛИС достижимая тактовая частота определяется в основном сложностью комбинационных схем, которые строятся на базе LUT. Аппаратные ресурсы (умножители, блочная память) не менее важны для планирования характеристик процессора, поскольку конкретная микросхема, используемая для проекта, имеет определенное сочетание основных ресурсов (логики, памяти, умножителей). Для ПЛИС превысить объем имеющихся на кристалле ресурсов невозможно, в то время как для ASIC сочетание ресурсов выбирают в существенно более широких пределах. В то же время проекты заказных микросхем в значительной степени зависят от квалификации разработчика и уровня освоения им инструментов проектирования. Поэтому для исследовательских работ и эксплуатации экспериментальных образцов новых архитектур настоятельно рекомендуется использовать ПЛИС.

 

Назначение и разновидности процессорных устройств

Полная классификация процессоров с учетом их технических характеристик, схемотехники, назначения и прочего — задача чрезвычайно сложная и неоднозначная. Многообразие современных архитектур не позволяет в полной мере представить четкую и непротиворечивую классификацию столь огромного класса цифровых микросхем. Тем не менее на основе подходов к проектированию можно рассмотреть основные классы вычислительных устройств с точки зрения порядка их применения инженерами-схемотехниками и программистами.

По назначению можно выделить следующие типы процессорных устройств.

  • процессоры общего назначения;
  • процессоры цифровой обработки сигналов (сигнальные процессоры);
  • микроконтроллеры.

Приведенная классификация чересчур схематична и не учитывает подклассы внутри указанных больших групп. Особенно это важно для микроконтроллеров, которые имеют крайне широкий спектр характеристик.

Процессоры общего назначения, как следует из названия данного типа, предназначены для решения широкого класса задач. Они не имеют узкой специализации и могут быть применены как в персональных устройствах (компьютерах, планшетах, смартфонах), так и для управления промышленным оборудованием, работы в мультимедийных устройствах, медицинском оборудовании и т. д. К этому типу принадлежат такие семейства, как x86, ARM Cortex-A (высокопроизводительное семейство ARM, используемое в планшетах и смартфонах), и другие.

Процессоры цифровой обработки сигналов (также DSP, или сигнальные процессоры) характеризуются высокой производительностью при выполнении операции «умножение с накоплением» (Multiply And Accumulate, MAC), которая лежит в основе многих алгоритмов цифровой обработки сигналов: фильтрации, быстрого преобразования Фурье, моделирования нейросетей и т. п. Актуальным на сегодня направлением является т. н. программно-зависимое радио (также SDR, Software-Defined Radio). Представителями процессоров цифровой обработки сигналов являются серии C66x, C67x (и др.) производства Texas Instruments, ADSP‑21xx и TigerSHARC от Analog Devices.

Микроконтроллеры представляют собой микросхемы, содержащие процессорное ядро, память и периферийные устройства на одном кристалле. Это позволяет минимизировать габариты электронной части изделия, сосредоточив основные функции в единственной микросхеме. Обычно производительность микроконтроллеров существенно меньше, чем у процессоров общего назначения и сигнальных процессоров, однако набор периферийных устройств (USB, SD, UART, PWM, АЦП) шире, хотя часто в конкретном наименовании микроконтроллера его ограничивают для решения определенного круга задач. По различным оценкам, приблизительно 95% выпускаемых процессорных устройств принадлежат именно к классу микроконтроллеров, обеспечивая управление широчайшей номенклатурой современных изделий.

 

Варианты применения софт-процессоров в системах цифровой обработки сигналов и встраиваемых приложениях

Исходя из характеристик ПЛИС, следует обратить внимание на два крупных класса процессоров — процессоры для устройств цифровой обработки сигналов и процессоры для встраиваемых применений.

Известно, что характеристики схем на базе ПЛИС оказываются хуже, чем для аналогичных по технологическому процессу специализированных микросхем. Поэтому нецелесообразно пытаться воспроизвести существующие процессоры без заметной переработки архитектуры системы в целом для более эффективного использования особенностей ПЛИС. К таким особенностям относятся:

  • большое количество аппаратных блоков «умножение с накоплением», способных обеспечить суммарную производительность от единиц GMAC/с до TMAC/с;
  • возможность реализации параллельно работающих вычислительных структур и аппаратных ускорителей цифровых интерфейсов.

Для систем цифровой обработки сигналов можно применить софт-процессор согласно схеме, показанной на рис. 8.

Применение процессора в составе системы цифровой обработки сигналов

Рис. 8. Применение процессора в составе системы цифровой обработки сигналов

В ней процессор не является главным узлом обработки потока данных. Вместо этого основная производительность обеспечивается узлами, собранными на основе компонентов DSP48, а процессор решает вспомогательные задачи — настройку, калибровку и мониторинг работы, а также организацию интерфейса с оператором и внешними микросхемами. Поэтому от управляющего процессора системы ЦОС не требуется высокой производительности вычислений, а основной акцент можно сделать на более тесную интеграцию с модулями цифровой обработки сигналов.

Надо обратить особенное внимание, что в задачах ЦОС крайне важно обеспечение постоянства интервала дискретизации по времени t. Подавляющее большинство алгоритмов ЦОС построено в предположении, что этот интервал является постоянным. В то же время, если только в процессоре не предприняты специальные меры, будут выполняться задачи обработки интерфейсов, прерываний, а при наличии кэш-памяти возможны также промахи (cache miss) при доступе к данным. Поэтому для систем цифровой обработки сигналов сложно добиться сохранения потактовой точности интервала дискретизации по времени, если только речь не идет о медленных процессах, для которых можно использовать один из системных таймеров.

Применение аппаратных обработчиков на базе программируемых ячеек и блоков DSP ПЛИС полностью решает описанную проблему. Такие блоки обеспечивают потактную предсказуемость поведения, а добавление процессора позволяет решать множество задач по изменению параметров фильтрации на программном уровне.

Во встраиваемых системах также можно указать области предпочтительного применения софт-процессора. В приложениях с большим количеством протекающих процессов разнородного характера часто приходится организовывать работу микроконтроллера вокруг обработчиков прерываний. Линейное исполнение основного алгоритма, условно представленного в виде шагов 1–3, сочетается с обработкой запросов на прерывания от разнообразных внешних датчиков и периферийных устройств самого микроконтроллера. Для программиста такое поведение может в конечном итоге стать неудобным для сопровождения, к тому же одновременный приход нескольких запросов на прерывания способен привести к неопределенной или даже аварийной ситуации. На рис. 9 показан возможный переход от проекта, основанного на подпрограммах, к проекту, активно использующему сопроцессоры.

Применение многопроцессорной системы для параллельной обработки задач во встраиваемом оборудовании

Рис. 9. Применение многопроцессорной системы для параллельной обработки задач во встраиваемом оборудовании

При таком подходе вспомогательные задачи, требующие интенсивных вычислений, полностью передаются сопроцессорам. Центральный процессор, как и в случае систем цифровой обработки сигналов, выполняет в основном функции управления, мониторинга и организации внешних интерфейсов.

Другой возможный вариант добавления сопроцессоров — организация гетерогенной вычислительной структуры для комплекса задач с различными требованиями к производительности и типам операций обработки на каждом этапе. Пример такого подхода показан на рис. 10.

Применение ускорителей в сочетании со специализированным управляющим процессором

Рис. 10. Применение ускорителей в сочетании со специализированным управляющим процессором

Представляется, что набор операций Оп1–Оп3 содержит существенно различающиеся действия, поэтому для каждой стадии обработки предназначен собственный тип ускорителя.

 

Порядок проектирования процессора

В настоящее время выявлены следующие тенденции в разработке процессоров и систем на кристалле (СнК) [1].

1. Увеличение логического объема устройств

Современные технологические процессы, начиная со 130‑нм, могут реализовать устройства более чем с 100 тыс. эквивалентных вентилей/мм2 (а более современный 28‑нм — 3–4 млн вентилей/мм2). Соответственно, микросхемы, относящиеся к недорогим устройствам (площадью до 50 мм2), содержат миллионы эквивалентных вентилей. Высокая плотность компонентов на полупроводниковом кристалле стимулирует реализацию со стороны системных инженеров множества функций, не ограничивая их только самыми необходимыми в данной сфере применения. Подобная избыточность ставит дополнительные задачи по обеспечению интеграции компонентов для инженеров‑разработчиков.

2. Возрастающая сложность разработки

Граница емкости эффективно реализуемой системы в настоящее время оценивается как 100–500 тыс. эквивалентных логических вентилей. При увеличении объема сверх этих пределов технические решения, реализуемые автоматическими средствами синтеза и размещения, становятся неэффективными. В то же время микросхемы, выполненные для технологических норм 0,13 мкм и глубже, могут содержать миллионы вентилей.

3. Возрастающая сложность верификации

Сложность разрабатываемой системы увеличивается непропорционально росту ее логического объема ввиду повышения количества взаимосвязей. Существуют проекты, в которых затраты на верификацию на системном уровне составляют 70% и более общих расходов на разработку.

4. Высокая стоимость исправления ошибок

С переходом к новым технологическим нормам регулярно увеличивается стоимость разработки, которая имеет наиболее характерное выражение в цене комплекта фотошаблонов. Эта стоимость имеет тенденцию к экспоненциальному росту: по данным исследовательской группы The Information Network, комплект фотошаблонов для 65‑нм технологического процесса в среднем в 1,8 раза дороже, чем для 90‑нм, а для 45‑нм — в 2,2 раза дороже, нежели для 65‑нм. Однако, кроме стоимости комплекта фотошаблонов, в стоимость разработки и исправления ошибок входят безвозвратные инженерные затраты (NRE, nonrecurring engineering), которые могут оказаться гораздо выше стоимости фотошаблонов. Помимо того, в условиях высокой конкуренции задержка выпуска продукции приводит к утрате части рынка и финансовым потерям. В общей сложности, стоимость цикла разработки достигает миллионов долларов для современных технологических процессов. Тем не менее необходимо обратить внимание на предлагаемые сегодня варианты изготовления тестовых пластин по совмещенному подходу (MPW, Multi Project Wafer), когда на одной пластине располагается множество фрагментов, заказанных различными организациями. В этом случае стоимость заказа заметно снижается и может начинаться от нескольких миллионов рублей (цена в значительной мере зависит от множества факторов).

5. Поздняя интеграция аппаратного и программного обеспечения

Подавляющее большинство систем на базе процессоров имеет достаточно большой объем программного обеспечения, являющегося неотъемлемой частью обеспечения функциональности системы. Интеграция программного обеспечения обычно представляет собой завершающую стадию процесса разработки и часто становится причиной снижения характеристик изделия относительно ожидаемых из-за возникновения непредвиденных ситуаций и несоответствия параметров разработанного программного обеспечения предварительным оценкам. Поздняя проверка ПО рассматривается как источник повышенного риска при разработке продуктов, включающих аппаратное и программное обеспечение.

6. Изменения стандартов и требований потребителей

В процессе разработки изделия может произойти изменение общепринятых стандартов, соблюдение которых принципиально для целого ряда областей, таких как коммуникационные протоколы, обработка звука и видео, криптография. Причем требуется не только обеспечение совместимости с существующими стандартами, но и поддержка новых вариантов.

Таким образом, с точки зрения проектировщика микросхемы существует множество причин сделать поведение этого дорогостоящего и сложного продукта гораздо более гибким — например, с помощью встроенного в микросхему процессорного ядра. Это позволит не только устранять недоработки, программно перенастраивая внутренние узлы, но и адаптировать микросхему к вновь появляющимся требованиям потребителей, загружая новые протоколы работы. Важно, что микросхема может содержать процессор, но при этом позиционироваться на рынке как контроллер сложного устройства, коммуникационная микросхема и т. п. Иными словами, наличие процессора в ее составе является внутренним делом компании-производителя, которая таким образом облегчает процесс создания, делает его менее рискованным и позволяющим привлечь к данной деятельности не только схемотехников, но и программистов.

 

Этапы проектирования процессора

Основные этапы проектирования процессора показаны на рис. 11.

Основные этапы проектирования процессора

Рис. 11. Основные этапы проектирования процессора

Этот рисунок не ставит целью детально продемонстрировать маршрут проектирования, а обращает внимание на то, что при проектировании процессора существует минимум три крупных этапа, требующих привлечения специалистов соответствующего направления: программистов, схемотехников, инженеров‑топологов.

Системная модель

Системная модель представляет собой верхний, наиболее абстрактный уровень проектирования процессора. Здесь основное внимание уделяется обобщенной модели процессора, как ее видит программист. Инструментом проектирования является компилятор языка высокого уровня, с помощью которого разрабатывается эмулятор процессора — программа, имитирующая поведение процессора на уровне, обычно доступном для наблюдения программисту: содержимое регистров, памяти, состояние периферийных устройств. Работа процессора описывается с помощью обычных переменных и операторов выбранного языка программирования, причем переменные выступают в качестве моделей регистров и памяти. Таким образом, вместо проектирования устройства, способного сложить содержимое двух регистров, достаточно написать оператор, складывающий значения двух переменных. При этом предполагается, что впоследствии можно спроектировать устройство, выполняющее такую операцию.

Системная модель отличается высокой скоростью работы, гибкостью процесса проектирования и простотой внесения изменений, содержит риски получения такого описания, которое впоследствии не сможет быть реализовано в цифровой схеме, или же полученная схема окажется технически неэффективной. Системная модель предназначена не только для проверки функционирования основных компонентов процессора, но и для выполнения ранней интеграции программного и аппаратного обеспечения.

RTL-представление

RTL-представление (Register Transfer Level — уровень регистровых передач) подразумевает представление цифрового устройства в виде схемы соединения регистров и комбинаторной логики. Этот уровень предназначен для работы инженеров‑схемотехников, создающих описание принципиальной электрической схемы процессора с использованием языков описания аппаратуры.

Топология микросхемы

Топология микросхемы является предметом разработки специализированных дизайн-центров. В данном случае широкому кругу инженеров трудно включиться в этот процесс, поскольку результатом работы дизайн-центра становится информация о размещении отдельных компонентов полупроводникового кристалла. Как правило, подобная информация представляется в специализированном формате GDSII и требует дорогостоящих и сложных в освоении САПР в сочетании с библиотеками компонентов, предоставляемыми конкретными полупроводниковыми фабриками.

 

Основные элементы цифрового устройства

Элементы цифровых схем можно разделить на два больших класса: комбинационные и синхронные. Основные компоненты рассмотрены далее. Микросхемы программируемой логики существенно упрощают процесс создания комбинационных схем, поскольку любая схема задается ее таблицей истинности (LUT, Look-Up Table). Такие таблицы физически реализованы в ПЛИС, поэтому разработчику не стоит беспокоиться о сложности схемы и ее низкоуровневой оптимизации. Необходимо только следить, чтобы общее число входов схемы не стало слишком большим. На рис. 12 показано представление схемы из логических вентилей в виде таблицы истинности. Независимо от сложности схемы, LUT современных ПЛИС способны реализовать ее в одном элементе, если число входов не превышает 6. Также за счет вспомогательных ресурсов логических ячеек в ряде случаев возможен синтез 7‑ и 8‑входовых функций, однако на реализуемые таким образом логические выражения накладываются ограничения.

Комбинационная схема и ее представление в виде таблицы истинности

Рис. 12. Комбинационная схема и ее представление в виде таблицы истинности

Второй базовый компонент — триггер. Эти устройства тоже присутствуют в составе программируемых логических ячеек современных ПЛИС. Графическое изображение триггера и временные диаграммы его работы показаны на рис. 13.

Графическое изображение и временная диаграмма работы D‐триггера

Рис. 13. Графическое изображение и временная диаграмма работы D‐триггера

Соединяя комбинаторную логику и триггеры, можно получить схему, представленную на уровне регистровых передач (RTL, Register Transfer Level). Пример такой схемы дан на рис. 14.

Синхронная цифровая схема на уровне регистровых передач

Рис. 14. Синхронная цифровая схема на уровне регистровых передач

Овалами отмечены некоторые выражения, реализованные в комбинационной логике.

Синхронная схема обладает следующими признаками:

  • один тактовый сигнал, один перепад (все триггеры используют только фронт или только спад тактового сигнала);
  • используются D‑триггеры (не защелки);
  • рекомендованы регистры на выходах блоков;
  • используются сигналы «разрешение счета» вместо управления тактовым сигналом;
  • используются схемы синхронизации для асинхронных сигналов.

Не используются:

  • тактовые сигналы, полученные с помощью логических вентилей, комбинирования разрядов счетчиков или делением частоты с помощью триггеров логических ячеек;
  • локальные асинхронные сигналы сброса/установки.

 

От конечного автомата к процессору

Многие программисты и инженеры, использующие в повседневной деятельности процессоры, безусловно, знакомы с их основными компонентами — регистрами, арифметико-логическими устройствами, контроллерами шины и периферийных модулей и т. п. Однако не всегда очевидны особенности их взаимодействия и практические шаги, с помощью которых можно получить работоспособную на практике цифровую схему.

Важным этапом на пути к проектированию процессора является понятие конечного автомата (КА, также FSM — Finite State Machine). Под конечным автоматом подразумевается схема, число внутренних состояний которой конечно. Она может формировать одинаковые выходные сигналы при нахождении в нескольких состояниях, однако обратное не гарантируется. Схематично конечный автомат изображен на рис. 15.

Конечный автомат

Рис. 15. Конечный автомат

Здесь все переменные состояния сгруппированы в регистре REG. Узлы, показанные в виде овалов, содержат некоторую комбинаторную логику, чья конкретная схема в данном случае не существенна. Важнее то, что рисунок демонстрирует порядок работы КА — на каждом новом такте группы регистров REG принимает какое-то другое состояние, зависящее от предыдущего состояния и набора входных сигналов.

В качестве простого примера можно рассмотреть конечный автомат, управляющий светофором. Схема действия светофора хорошо известна, а смена цветов выполняется строго в одном и том же режиме. Поэтому для него можно использовать простейший КА с линейным порядком смены состояний. Далее показан листинг на языке описания аппаратуры VHDL, поясняющий схему управления цветами светофора.

Автомат работает следующим образом. Переменная состояния st (от state — «состояние») изменяется линейно в пределах 0–23, формируя таким образом 24 состояния светофора. В состояниях 0–9 горит красный сигнал, далее добавляется желтый на состояния 10–11. Состояния 12–17 соответствуют горящему зеленому, далее в течение 4 состояний формируется его мигание. Завершающие состояния 22–23 соответствуют включенному желтому сигналу.

Временные диаграммы работы такого КА показаны на рис. 16. Можно пронаблюдать поведение выходных сигналов red, yellow, green и убедиться, что они соответствуют хорошо известному порядку переключения цветов светофора.

Временные диаграммы работы конечного автомата

Рис. 16. Временные диаграммы работы конечного автомата

Простота данного примера служит единственной цели — сопоставить поведение выходных сигналов и их описание в КА. Можно убедиться, что описание целиком укладывается в единственный оператор case. При необходимости нетрудно изменить порядок работы, добавить или убрать состояния, ввести дополнительные сигналы (например, запрос на включение пешеходного светофора). Регулярность описания КА и простота его изменения и сопровождения весьма полезны на практике и позволяют не только быстро реализовать схему с нужным поведением, но и оперативно отслеживать ее корректность, вносить изменения и проводить моделирование и отладку.

Рассмотрение работы конечного автомата выявляет важную особенность — для изменения формы выходных сигналов требуется изменение его схемы. С учетом высокой стоимости изготовления заказных микросхем практически нереально создавать конечные автоматы с жестко заданным порядком работы для решения каждой частной задачи. В то же время видно, что формирование выходных сигналов осуществляется довольно регулярным способом — на основе анализа состояния автомата. Сделать КА более гибкой можно, если добавить таблицу с правилами перехода между состояниями, как показано на рис. 17.

Конечный автомат с таблицей переходов между состояниями

Рис. 17. Конечный автомат с таблицей переходов между состояниями

Приведенный пример работы светофора легко модифицировать, если привязывать состояния сигналов светофора не к номеру состояния, а к коду, записанному в таблице. Последовательный перебор адресов таблицы, начиная с 0, будет читать содержимое памяти, которое можно произвольно менять в процессе работы схемы. Тогда длительность удержания цветов, количество миганий зеленого цвета и прочие параметры светофора корректируются простым изменением содержимого таблицы.

Показанная на рис. 17 схема очень близка к процессору. Вообразим, что таблица переходов представляет собой память программы. Входной сигнал является адресом этой памяти, а содержимое (данные) — номером состояния, в которое должен перейти КА. Остальная часть конечного автомата должна быть разработана таким образом, чтобы по коду команды вносить изменения в регистры конечного автомата. Этот подход позволяет изменять логику работы КА в определенных пределах.

Следующий шаг — разработка простого процессорного ядра. Оно будет содержать основные компоненты, которые привычно видеть в процессоре: память программ, управляющее устройство, регистры и арифметико-логическое устройство.

 

Процессорное ядро в виде простого конечного автомата

Рассмотрим порядок проектирования простого процессорного ядра, при котором можно наглядно проследить порядок проектирования и основания для принятия тех или иных решений. Проект процессора определяется следующими важнейшими составляющими:

  1. Архитектура системы команд (АСК, также Instruction Set Architec-ture, ISA). На этом уровне описываются допустимые для процессора команды, насколько они видны программисту. Для описания АСК используются и программные модели процессора, определяющие набор регистров процессора, их разрядность, операции с ними, особенности и т. д.
  2. Микроархитектура (аппаратная архитектура), описывающая порядок работы отдельных узлов процессора и их взаимодействие.

Для простейшего варианта, отображающего порядок проектирования, достаточно использовать столь же доступную программную архитектуру, которая не будет содержать всего многообразия регистров, привычных для программистов, однако продемонстрирует минимальный набор ресурсов, достаточный для запуска основных операций. Регистровая модель примера показана на рис. 18.

Регистровая модель примера процессора

Рис. 18. Регистровая модель примера процессора

Данная модель содержит всего два регистра общего назначения, определенных как RegA и RegB. Эти регистры будут использованы для выполнения основных арифметических и логических действий.

Также в составе модели показаны системные регистры. Это PC (Program Counter), который хранит адрес команды процессора, и регистр RetA для хранения адреса возврата из подпрограммы. Хорошо известно, что хранение адресов возврата должно производиться в специальной структуре данных — стеке возвратов, что обеспечивает возможность вложенных вызовов (кроме того, стек предназначен и для размещения параметров подпрограмм). Тем не менее для простого примера достаточно и одного регистра, поскольку реализация доступа к стеку в памяти усложнит пример.

Для узлов, использованных на рис. 19, можно выявить важную особенность. Среди действий процессора имеется команда перехода, которая, вообще говоря, может быть запрограммирована в произвольный момент времени.

Структурная схема примера процессора

Рис. 19. Структурная схема примера процессора

Однако без чтения команды непонятно, является ли она командой перехода, поэтому определить следующий адрес для выполнения невозможно. Далее будут рассмотрены варианты конвейеризованной микроархитектуры, но для простоты примем, что каждая команда процессора будет выполняться за два такта (рис. 20).

Временная диаграмма операций, выполняемых процессором для различных тактов

Рис. 20. Временная диаграмма операций, выполняемых процессором для различных тактов

На первом такте процессор читает команду из ячейки памяти программ по адресу PC. На втором такте, имея в своем распоряжении код команды, на его основе можно определить, какой результат и в какой регистр записывать, а также адрес следующей команды.

Так же как и для программной модели, в примере использован максимально простой подход, призванный продемонстрировать основные задачи, решаемые при реализации процессора, и служить отправной точкой для последующих модификаций, превращающих данную схему в более распространенные сегодня микроархитектуры.

Теперь перейдем к основным приемам кодирования процессного модуля на языке описания аппаратуры VHDL. Предполагается использование САПР Xilinx, например ISE или Vivado. В первом случае разработчики могут обратиться к дешевым ПЛИС семейства Spartan‑6, которые не поддерживаются в более современной САПР Vivado. В обоих случаях применяются САПР, имеющие вариант бесплатной лицензии и обеспечивающие полный маршрут проектирования от ввода исходного текста до программирования ПЛИС. Первые этапы проектирования целесообразнее фокусировать на поведенческом моделировании, использующем описание на уровне регистровых передач для построения диаграмм изменения сигналов цифрового устройства.

В листинге 1 приведено описание интерфейса примера процессора и объявление его основных ресурсов, доступных в регистровой модели для программиста.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity fsm is
Port ( clk : in  STD_LOGIC;
reset : in  STD_LOGIC;
red : out  STD_LOGIC;
yellow : out  STD_LOGIC;
green : out  STD_LOGIC);
end fsm;
 
architecture Behavioral of fsm is
 
signal st : integer range 0 to 23 := 0;
 
begin
 
process(clk)
begin
  if rising_edge(clk) then
if reset = '1' then st <= 0; else
                        case st is
                                    when 0 to 9 => red <= '1';
                                                yellow <= '0';
                                                green <= '0';
                                    st <= st + 1;
when 10 to 11 => yellow <= '1';
                                                st <= st + 1;
                        when 12 to 17 => red <= '0'; yellow <= '0';
green <= '1';
st <= st + 1;
when 18 => green <= '0';
                                    st <= st + 1;
when 19 => green <= '1';
                                    st <= st + 1;
when 20 => green <= '0';
                                    st <= st + 1;
when 21 => green <= '1';
                                    st <= st + 1;
                        when 22 => yellow <= '1';
                                    green <= '0';   
st <= st + 1;
when 23 => st <= 0;
                        when others => null;
              end case;
             end if;
  end if;
end process;
 
end Behavioral;

Раздел generic в объявлении задает два параметра, которые удобно иметь в подобном настраиваемом виде для проекта, — размер памяти программ и размер памяти данных. Вынесение этих параметров в раздел generic позволяет изменить их впоследствии. Нужно учесть, что в простом примере размеры памяти не являются произвольно изменяемыми, поскольку ряд особенностей архитектуры пока не позволяет превысить размер в 256 ячеек. Вот почему такие параметры носят в основном демонстрационный характер и обращают внимание на то, что глобальные параметры процессорного ядра могут регулироваться с помощью объявлений в разделе generic.

В разделе port, кроме очевидных сигналов clk и reset, объявлена дополнительная группа сигналов, обеспечивающая интерфейс программирования памяти команд. Это простейший интерфейс, состоящий из шины адреса, шины данных и сигнала разрешения записи we_cmd. Объявление такого интерфейса, кроме практической цели программирования процессора, носит и некий утилитарный характер. Дело в том, что, если содержимое памяти программ будет фиксированным, при определенных условиях синтезатор в САПР может попытаться оптимизировать схему с учетом того, что процессор должен выполнять одну-единственную неизменяемую программу. Лавинообразная оптимизация способна привести к тому, что какие-то важные узлы будут просто исключены из проекта, поскольку записанная в память программа их не использует. Очевидно, этот эффект существенно уменьшит размер процессора по сравнению с действительным и внесет явные искажения в оценку характеристик полнофункционального ядра.

Добавление интерфейса программирования не позволит синтезатору заменить память программ на ПЗУ (или даже на единственный регистр, хранящий 0), поэтому подобная неоправданная оптимизация не произойдет.

В листинге 2 модули памяти описаны похожим образом, с применением отдельных типов TProgram и TDataMem.

entity simple_core is
generic (PROGRAMSIZE : integer := 256;
                                    DATASIZE : integer := 256);
Port ( clk : in  STD_LOGIC;
reset : in  STD_LOGIC;
-- интерфейс программирования памяти команд
addr_in : in  STD_LOGIC_VECTOR (7 downto 0);
cmd_in : in  STD_LOGIC_VECTOR (7 downto 0);
we_cmd : in  STD_LOGIC;
-- интерфейс процессора
addr : out  STD_LOGIC_VECTOR (7 downto 0);
data : out  STD_LOGIC_VECTOR (7 downto 0);
din : in  STD_LOGIC_VECTOR (7 downto 0);
wrio : out  STD_LOGIC);
end simple_core;
 
architecture Behavioral of simple_core is
 
type TProgram is array(0 to PROGRAMSIZE - 1) of integer range 0 to 255;
shared variable Program : TProgram := (others => 0);
 
type TDataMem is array(0 to DATASIZE - 1) of std_logic_vector(7 downto 0);
shared variable DataMem : TDatamem  := (others => (others => '0'));
 
signal st : integer range 0 to 1; -- фаза команды процессора
signal cmd : integer range 0 to 255; -- сигнал команды
 
-- регистры
signal RegA, RegB : std_logic_vector(7 downto 0) := (others => '0');
signal pc : integer range 0 to PROGRAMSIZE - 1;
signal RetA : integer range 0 to DATASIZE - 1 := DATASIZE - 1;
 
-- коды команд оформляются в виде констант
constant cmdNOP : integer := 0;

Для реализации собственно модулей памяти создается по одному экземпляру данных типов, которые объявляются не как signal, а как shared variable. Таков рекомендуемый стиль описания, разрешающий использование полезной особенности — модифицирования ячеек памяти в нескольких блоках process. Это недопустимо для объектов типа signal, однако поскольку память является двухпортовой, для нее возможна ситуация, когда в проекте используются оба порта и работа с ними описывается в отдельных блоках process. С точки зрения требований VHDL для этого требуется объект типа shared variable.

В листинге 3 описывается поведение процессора.

-- этот процесс описывает работу памяти программ.
-- Кроме интерфейса программирования, основная работа памяти описана строкой
-- cmd <= Program(pc);
-- Таким образом, модуль памяти программ работает по фронту тактового сигнала
-- и помещает на выход содержимое ячейки,
-- адресуемое регистром PC — Program Counter
process(clk)
begin
  if rising_edge(clk) then
    if we_cmd = '1' then
               Program(to_integer(unsigned(addr_in))) := to_integer(unsigned(cmd_in));
             end if;
             cmd <= Program(pc);
  end if;
end process;
 
-- память данных также работает по фронту тактового сигнала
-- регистр RegA всегда содержит данные для записи
-- регистр RegB всегда содержит адрес памяти
process(clk)
begin
  if rising_edge(clk) then
    if we_mem = '1' then
               DataMem(to_integer(unsigned(RegB))) := RegA;
             end if;
             memr <= DataMem(to_integer(unsigned(RegB)));
  end if;
end process;
 
-- сигнал we_mem должен быть объявлен как std_logic
-- этот сигнал формируется комбинаторной логикой, если процессор находится
-- в стадии исполнения команды (st = 1) и код команды соответствует ЗАПИСИ
we_mem <= '1' when cmd = cmdSTORE and st = 1 else '0';
 
-- специальное правило — иногда разряды (5 downto 0) команды содержат литерал
cmd_lit <= std_logic_vector(to_unsigned(cmd, 6));
 
-- основной цикл работы процессора
 
process(clk)
begin
  if rising_edge(clk) then
case st is
-- стадия «выборка». На этой стадии работает только память программ
when 0 => st <= 1;
-- на стадии «исполнение» код команды уже актуален.
-- можно вернуться на стадию «выборка»
-- и одновременно выполнить действия, соответствующие прочитанной команде
               when 1 => st <= 0;
                 case cmd is
                        when cmdNOP => pc <= pc + 1;
                        when cmdAB    => pc <= pc + 1; RegA <= RegB;
when cmdBA              => pc <= pc + 1; RegB <= RegA;
                        when cmdSWAP  => pc <= pc + 1; RegA <= RegB; RegB <= RegA;
 
-- несколько сложно выглядит сложение и вычитание с применением
-- библиотеки numeric.std. Необходимо явно указать преобразование регистров
-- к беззнаковому целочисленному формату to_integer(to_unsigned(..))
-- затем сложить/вычесть получившиеся числа, а к результату применить
-- преобразование std_logic_vector(<value>, <разрядность>)
                        when cmdPLUS  => pc <= pc + 1;
RegA <= std_logic_vector(to_unsigned(to_integer(unsigned(RegA)) + to_integer(unsigned(RegB)), RegA'length));
                        when cmdMINUS => pc <= pc + 1; RegA <= std_logic_vector(to_unsigned(to_integer(unsigned(RegA)) - to_integer(unsigned(RegB)), RegA'length));
-- логические выражения выглядят проще
                        when cmdAND   => pc <= pc + 1; RegA <= RegA and RegB;
                        when cmdOR    => pc <= pc + 1; RegA <= RegA or RegB;
                        when cmdXOR   => pc <= pc + 1; RegA <= RegA xor RegB;
                         when cmdSHR   => pc <= pc + 1; RegA <= '0' & RegA (7 downto 1);
                        when cmdSHL   => pc <= pc + 1; RegA <= RegA(6 downto 0) & '0';
 
-- чтение памяти разбито на две фазы. Перед этим, на стадии «выборка», регистр
-- RegB был безусловно использован в качестве адреса для чтения
-- таким образом, память данных была прочитана «на всякий случай»
-- Это упрощенный подход работы с памятью и он будет изменен
-- в более практичных микроархитектурах
                        when cmdREAD  => pc <= pc + 1; RegA <= memr;
 
-- изменение порядка выполнения команд
-- JMPZ — условный переход, по адресу, загруженному в регистр RegB,
-- если в регистре RegA содержится 0
-- JMP — безусловный переход по адресу, загруженному в регистр RegB
-- CALL — вызов подпрограммы по адресу, загруженному в регистр RegB
-- RET — возврат из подпрограммы
                        when cmdJMPZ  => if to_integer(unsigned(RegA)) = 0 then
pc <= to_integer(unsigned(RegB)); else pc <= pc + 1;
end if;
                        when cmdJMP  => pc <= to_integer(unsigned(RegB));
                        when cmdCALL  => pc <= to_integer(unsigned(RegB)); RetA <= pc + 1;
                        when cmdRET   => pc <= RetA;
                       
-- работа с внешними устройствами
when cmdINPORT => pc <= pc + 1; RegA <= din;
 
-- загрузка непосредственных значений (литералов) в регистры
-- поскольку разрядность регистров равна разрядности команды,
-- загрузить число полностью невозможно
-- поэтому число загружается сдвигом — справа «вдвигаются» 6 младших
-- разрядов команды, т.е.
-- 10xxxxxxx — вдвигание xxxxxx в RegA
-- 11xxxxxxx — вдвигание xxxxxx в RegB
                         when 128 to 191 => RegA <= RegA(1 downto 0) & cmd_lit; pc <= pc + 1;
                         when 192 to 255 => RegB <= RegB(1 downto 0) & cmd_lit; pc <= pc + 1;
                       
when others => pc <= pc + 1;
                        end case; -- завершение оператора case для обработки команд
               when others => null;
    end case; -- завершение оператора case для обработки состояний процессора
  end if;
 
end process;
 
-- сигнал «разрешение записи» для внешних устройств формируется
-- комбинаторной логикой. Для этого требуется, чтобы процессор был
-- в стадии «выполнение» и код команды соответствовал записи в порт ВВ
wrio <= '1' when cmd = cmdOUTPORT and st = 1 else '0';

В обоих листингах полные списки констант с командами и вспомогательные сигналы не приведены для сокращения объема публикации. Назначение и формат их описания очевидны и могут быть свободно воспроизведены разработчиками.

Работу процессора можно проверить в комплексном виде с помощью так называемого системного теста. Если узлы процессора, в частности память и АЛУ, проверять по отдельности (так называемые юнит-тесты), то вопрос работоспособности ядра в целом остается открытым. Показательнее способ, когда создается комплексная модель, проверяющая весь процесс выполнения тестовой программы (рис. 21).

Результаты моделирования простого теста

Рис. 21. Результаты моделирования простого теста

Разработка такой модели оказывается проще, чем отдельные тесты для узлов процессора. Для нее достаточно заполнить память программ процессора и подать тактовый сигнал. Если используется САПР ISE, генерация текста, описывающего внешний тактовый генератор для сигнала clk, будет произведена автоматически при выполнении мастера создания нового теста на VHDL. В описание процессора необходимо внести изменения по примеру, показанному в листинге 4.

shared variable Program : TProgram := (
  0 => 130,  -- RegA = 2
  1 => 194, -- RegB = 2
  2 => cmdPLUS,
  3 => 192, -- RegB = 0, обнуление старших разрядов
  4 => 202,  -- RegB = 10
  5 => cmdCALL,
  6 => 192, -- RegB = 0, обнуление старших разрядов
  7 => 192, -- RegB = 0
  8 => cmdJMP, -- переход к адресу 0
  10 => cmdRET,
others => 0);

Здесь память программ инициализируется тестовым примером. В простом случае проверяется сложение регистров RegA и RegB и вызов подпрограммы по адресу 10, которая сразу же возвращает управление.

Подобный процессор крайне прост, и его характеристики в плане тактовой частоты и объема используемых ресурсов выглядят привлекательно. Однако он вряд ли может быть применен в серьезных практических целях. Не рассматривая вопросы его программной поддержки, укажем направления, по которым можно усовершенствовать представленную микроархитектуру.

  1. Регистровая модель выбрана крайне простой. Кроме того, что используются только два регистра общего назначения, они имеют и жестко привязанные к ним вспомогательные функции — например, хранение адреса для работы с памятью и переходов в RegB, хранение данных в RegA. Все команды имеют формат RegA = Operation (RegA, RegB). Это требует изменения.
  2. Двухтактный конвейер имеет очевидное улучшение — во время выполнения команды вполне можно читать следующую команду, предполагая, что процессор не изменит линейный порядок выполнения. Большинство используемых процессорных архитектур работают по подобной схеме, когда команды продвигаются по конвейеру из синхронных узлов. Длина конвейера может быть больше 2, и в современных процессорах используются от 3–5 до 10 и более стадий. Далее будет рассмотрено проектирование некоторых конвейеризованных микроархитектур.
  3. Управление выполнением программы ограничено одним вариантом безусловного перехода и одноуровневым вызовом подпрограмм.
  4. Выбрана простая архитектура системы команд. Реализация более развитой регистровой модели и поддержки различных режимов адресации памяти потребует планирования формата команды и подходов к ее декодированию.

Все перечисленные пункты не представляются недостижимыми для реализации. В то же время они имеют широкий спектр возможных решений, к тому же микроархитектура и архитектура системы команд обычно влияют друг на друга, и рекомендуется рассматривать их согласованно. Такой анализ предполагается в последующих публикациях.

 

Заключение

Данная статья позволяет оценить актуальность самостоятельной разработки процессорных ядер. Поскольку проектирование процессорных устройств представляет собой огромную область, которую невозможно сколько-нибудь подробно описать в рамках одной статьи (или даже серии статей), в настоящей публикации основной акцент сделан на практические разъяснения того, каким образом собственное процессорное ядро может быть полезно для практической работы с ПЛИС.

В следующей статье будут рассмотрены основные микроархитектуры процессоров, пригодные к практическому прототипированию на базе ПЛИС, и их описание на языке VHDL.

Продолжение статьи.

Литература
  1. Rowen C. Engineering the Complex SOC. Fast, Flexible Design with Configurable Processors. Prentice Hall, 2004.
  2. Nurmi J. Processor Design. System-on-Chip Computing for ASIC and FPGAs. Springer, 2007.
  3. Паттерсон Д., Хеннесси Дж. Архитектура компьютера и проектирование компьютерных систем. Классика computer science. Изд. 4‑е. СПб.: Питер, 2012.
  4. Новожилов О. П. Основы микропроцессорной техники. Учебное пособие в двух томах. М.: РадиоСофт, 2014.
  5. Тарасов И. Е. Проектирование конфигурируемых процессоров на базе ПЛИС // Компоненты и технологии. 2006. № 2–4.
  6. xilinx.com

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *