Программируемая Логическая Интегральная Схема (ПЛИС) может реализовать произвольную логику, что угодно, от микропроцессора до генератора видеосигнала или майнера криптовалюты. ПЛИС состоит из множества логических блоков, каждый из которых обычно состоит из триггера и логической функции, а также из сети проводников, соединяющей логические блоки. Что делает ПЛИС особенной, это то, что она является программируемым аппаратным обеспечением, вы можете сконфигурировать каждый логический блок и соединения между ними. В результате вы можете построить сложную цифровую схему без физического соединения каждого логического элемента и триггера, что обошлось бы вам в стоимость разработки заказной интегральной схемы.
Фотография показывает один из 64 блоков микросхемы XC2064. Слои металлизации убраны, мы видим кремний и поликремниевые транзисторы, лежащие под металлизацией. По ссылке вы можете увидеть фото в большем масштабе: siliconpr0n.
ПЛИС была изобретена Россом Фрименом, сооснователем Xilinx в 1984 году, первой микросхемой ПЛИС была XC2064. Она была гораздо проще современных ПЛИС, содержала всего лишь 64 логических блока, по сравнению с тысячами и миллионами в современных FPGA, и её создание привело к появлению отрасли стоимостью в миллиарды долларов. XC2064 настолько важна, что вошла в Зал Славы Микросхем. Я провёл обратную разработку XC2064, и в этом посте я объясняю её внутреннюю структуру в общих чертах, и как она программируется потоком бит (bitstream).
Xilinx XC2064 — первая микросхема ПЛИС. Взято отсюда: siliconpr0n.
В настоящее время ПЛИС программируются на языках описания аппаратуры, таких, как Verilog или VHDL, но в то время Xilinx предоставляла собственное ПО для разработки, приложение MS-DOS под названием XACT, с немаленькой стоимостью $12000. XACT работало на более низком уровне, нежели современные инструменты: пользователь определял функцию каждого логического блока, как показано на скриншоте ниже, и соединения между логическими блоками.
XACT разводил соединения и генерировал файл конфигурации (битстрим), который загружался в ПЛИС.
Скриншот XACT. Две таблицы F и G реализуют уравнения, показанные внизу экрана, с картой Карно, показанной выше.
ПЛИС конфигурировалась с помощью битстрима, последовательности бит, имеющей проприетарный формат. Если вы посмотрите на битстрим XC2064 (ниже), то увидите загадочную смесь паттернов, которые повторяются нерегулярным образом и разбросаны по всему битстриму. Однако, изучение физических цепей ПЛИС открывает нам структуру данных битстрима и он может быть изучен.
Часть битстрима, сгенерированного XACT.
Как работает ПЛИС?
На приведённом ниже рисунке, взятом из оригинального патента на ПЛИС, показана базовая структура ПЛИС. В этой упрощённой ПЛИС всего 9 логических блоков (обозначены голубым), и 12 портов ввода-вывода. Сеть межсоединений соединяет компоненты вместе. Установкой переключателей (диагональные линии) на соединениях, логические блоки могут быть соединены между собой и с портами ввода-вывода. Каждый логический элемент может быть запрограммирован на требуемую логическую функцию. В результате, такой программируемый чип может реализовать любое устройство, которое поместится в доступный объём.
Патент на ПЛИС, логические блоки(LE) соединённые между собой.
Конфигурируемые логические блоки (CLB, Configurable Logic Block)
Несмотря на то, что на рисунке выше показаны 9 CLB, XC2064 имеет 64 CLB. На рисунке ниже показана структура CLB. CLB имеет 4 входа (A, B, C, D) и два выхода (X и Y). Между ними находится комбинационная логика, которая может быть запрограммирована на любую желаемую логическую функцию. Также CLB содержит триггер, наличие которого позволяет реализовать счётчики, регистры сдвига, конечные автоматы и другие схемы, сохраняющие состояние. Трапециями обозначены мультиплексоры, которые могут быть запрограммированы на прохождение сигнала с любого из входов. Мультиплексоры позволяют конфигурировать CLB под конкретную задачу, выбирая определённые сигналы для управления триггером и выходами.
Конфигурируемый логический блок в XC2064, взято отсюда: datasheet.
Возможно, вам интересно, как комбинационная логика реализует произвольные логические функции. Происходит ли выбор между набором элементов AND, OR, XOR и т. д.? Нет, используется хитрый трюк, называемый таблицей просмотра (lookup table, LUT), которая фактически является таблицей истинности для функции. Например, функция трёх переменных определяется таблицей из 8 строк. LUT содержит 8 бит памяти. Мы можем реализовать любую 3-входовую логическую функцию, сохраняя эти три бита.
Логические функции в ПЛИС XC2064 реализованы с помощью таблиц просмотра. Из документации.
Соединения
Следующий ключевой аспект ПЛИС, это соединения, которые могут быть запрограммированы на коммутацию CLB различными способами. Соединения устроены сложно, но грубое описание состоит в том, что есть сегменты вертикальных и горизонтальных связей между всеми CLB. Можно соединять CLB с горизонтальными и вертикальными линиями, и создавать произвольные соединения. Более сложный тип соединения, это «матрица переключателей». Каждая матрица имеет 8 выводов, которые могут соединяться друг с другом (почти) произвольным образом.
Рисунок внизу показывает структуру связей XC2064, которые обеспечивают соединения логических блоков (голубые) и линий ввода-вывода (жёлтые). Врезка показывает детали механизма соединения. Зелёные прямоугольники, это матрицы переключателей, имеющие 8 выводов, а маленькие квадратики, это программируемые точки соединений.
ПЛИС XC2064 имеет матрицу 8х8 CLB. Каждый CLB имеет название от AA до HH.
Соединение может коммутировать, например, выход блока DC с входом блока DE, как показано ниже. Красная линия показывает путь сигнала, а маленькие красные квадратики показывают активированные точки соединений. Выйдя из блока DC, сигнал направляется к первой точке соединений на 8-выводный переключатель (зелёный), который направляет его через две точки соединения и другой 8-входовый переключатель (неиспользуемые вертикальные и горизонтальные линии не показаны). Заметим, что соединение устроено достаточно сложно, даже такой короткий путь использует четыре точки соединения и два переключателя.
Пример разводки сигнала с выхода блока DC до блока DE.
Скриншот внизу показывает, как производится трассировка в программе XACT. Желтые линии показывают соединения между логическими блоками. По мере того, как количество сигналов увеличивается, становится сложно проводить соединения без конфликта между путями. Программа XACT производит автоматическую трассировку, но трассировка может быть также отредактирована вручную.
Скриншот программы XACT. Это программа MS-DOS, управление происходит с помощью клавиатуры и мыши.
Реализация
Дальше мы рассмотрим внутреннюю схему XC2064, проведя обратную разработку по фотографии кристалла. Предупреждаю, что это требует некоторого знакомства с XC2064.
Фото XC2064 под электронным микроскопом, с любезного разрешения John McMaster.
ПЛИС XC2018. Справа корпус удалён, видно кремниевый кристалл. На кристалле слабо виден рисунок плиток.
На фото ниже можно видеть сравнение кристалла XC2064 и XC2018. Кристаллы очень похожи, за исключением того, что больший чип имеет две дополнительных строки и два дополнительных столбца на кристалле.
Сравнение кристаллов XC2064 и XC2018. Изображения масштабированы так, что размеры плиток совпадают, я не знаю, как соотносятся физические размеры кристаллов. Фото кристаллов взяты с siliconpr0n.
Ниже приведено фото кристалла XC2064. Главная часть ПЛИС — это матрица блоков 8х8, каждый из них содержит логический блок и окружающие цепи. Хотя на схеме ПЛИС логические блоки (CLB) показаны как отдельные от соединительных схем сущности, в реальности это реализовано не так. На самом деле, каждый логический блок и его окружение реализованы в виде единого узла, плитки (tile). (Если быть точным, плитка включает в себя соединения вверху и слева от каждого CLB).
Схема размещения блоков на кристалле XC2064. Взято отсюда: siliconpr0n.
Расположенные вдоль сторон интегральной схемы, блоки ввода-вывода обеспечивают связь с внешним миром. Они подключены к выводам кристалла, которые показаны как маленькие зелёные квадратики, и подключены к выводам корпуса микросхемы. На кристалле есть буферы (зелёные): два вертикальных и два горизонтальных. Эти буферы усиливают сигнал, прошедший большое расстояние по микросхеме, и уменьшают задержку. Вертикальный регистр сдвига (розовый), и цепь выборки горизонтального столбца используются для загрузки битстрима в чип, как это будет показано ниже.
Внутри плитки
На рисунке внизу показана структура одной плитки XC2064, микросхема содержит 64 таких плитки, упакованных на одном кристалле. Около 40% каждой плитки занимают ячейки памяти (показаны зелёным цветом), которые хранят биты конфигурации. Верхняя треть (приблизительно) плитки содержит схемы соединений: две матрицы переключателей и некоторое количество отдельных переключателей линий связи. Ниже расположен логический блок. Главная часть логического блока — мультиплексор входов, триггер и таблица просмотра. Плитка соединяется с соседями через горизонтальные и вертикальные линии связи, а также она подсоединена к шинам питания и земли. Биты данных конфигурации попадают в ячейки памяти горизонтально, а вертикальные сигналы выбирают конкретный столбец для загрузки.
Одна плитка FPGA, показаны важные функциональные узлы
Транзисторы
ПЛИС реализована на КМОП (CMOS) логике, построенной из NMOS и PMOS транзисторов. Транзисторы выполняют в ПЛИС две основных роли. Во-первых, из их комбинаций складываются логические элементы. Во-вторых, транзисторы используются как переключатели, через которые проходит сигнал, например, для формирования связей между блоками. Транзистор, выполняющий эту роль, называется проходным. На рисунке ниже показана базовая структура МОП-транзистора. Два участка кремния легируются примесями для создания стока и истока. Между ними расположен затвор, включающий и выключающий транзистор, и управляющий током между стоком и истоком. Затвор изготовлен из специального типа кремния, называемого поликремнием, он изолирован от кремния под ним тонким слоем оксида. Над ним находятся два слоя металлизации, обеспечивающие соединения цепей.
Структура MOSFET
На фото кристалла мы можем наблюдать, как выглядит транзистор под микроскопом. Поликремниевый затвор — это змеистая линия между двумя легированными областями кремния. Круги — переходные отверстия, соединяющие кремний и металлический слой (который на этом фото удалён).
Транзистор MOSFET на кристалле ПЛИС
Битовый поток и память конфигурации
Конфигурационная информация в XC2064 сохраняется в ячейках конфигурационной памяти. ПЛИС не использует для этого блочную память, вместо этого конфигурационная память распределена по кристаллу в виде решётки 160х71, каждый бит размещён рядом с той цепью, которой он управляет. На рисунке внизу показан конфигурационный битстрим, загруженный в ПЛИС. Битстрим загружается в сдвиговый регистр, который идёт посередине чипа (розовый). Как только 71 бит загружен в сдвиговый регистр, цепь выборки столбца (голубая) выбирает нужный столбец памяти, и биты загружаются в столбец параллельно. Затем следующие 71 бит загружаются в сдвиговый регистр и выбирается следующий столбец слева. Процесс повторяется для всех 160 столбцов ПЛИС, и весь битстрим загружается в ПЛИС. Использование сдвигового регистра позволяет обойтись без объёмных цепей адресации памяти.
Как битстрим загружается в ПЛИС. Биты показаны условно, реальное хранилище бит гораздо более плотное. Три столбца справа уже загружены и происходит загрузка в четвёртый. Фото кристалла взято отсюда: siliconpr0n.
Важной вещью является то, что битстрим распределён по чипу в точности в том порядке, в котором биты следуют в файле: упаковка битов в битстриме соответствует их физическому размещению на чипе. Как будет показано ниже, каждый бит хранится в ПЛИС рядом с цепью, которой он управляет. таким образом, формат файла битстрима напрямую определяется размещением аппаратных цепей. Например, если существует промежуток между плитками, и в нём расположен буфер, такой же промежуток будет и в битстриме. Структура битстрима зависит не от абстракций программного обеспечения, таких, как поля в таблицах данных или блоки конфигурации. Понимание битстрима требует
Формат данных битстрима, из документации.
Каждый бит конфигурационной памяти реализован, как показано ниже. Каждая ячейка памяти состоит из двух инвертеров, соединённых в петлю. такая цепь имеет два стабильных состояния, и может хранить один бит: либо верхний инвертер находится в состоянии 1, а нижний в состоянии 0, либо наоборот. Для записи в ячейку, проходной транзистор слева активируется, пропуская сигнал. Сигнал на линии данных просто перетягивает инвертер, записывая необходимый бит. (Можно также считать конфигурационные данные, используя ту же цепь.) Выход Q и инвертированный Q управляют определённой функцией в ПЛИС, например, замыканием цепи межсоединения, извлечения бита из таблицы просмотра, или управления триггером. В большинстве случаев, используется только выход Q.
Остаётся под вопросом, есть ли в битстриме неиспользуемые биты. Вероятно, многие биты не используются. Например, каждая плитка имеет блок 18х18 бит, из которых 27 бит не используются. Просмотр кристалла показывает, что ячейки памяти, соответствующие неиспользованным битам, удалены полностью, и их место на кристалле использовано для других цепей. Фото кристалла внизу показывает 9 использованных бит и один пропущенный.
Ячейки памяти, показан промежуток, в котором одна ячейка пропущена. Взято с siliconpr0n.
Схема одного бита конфигурационной памяти, из документации.
На рисунке ниже показана физическая структура ячеек памяти. На фото слева показано 8 ячеек памяти, одна из которых выделена. Каждая горизонтальная линия данных подключена ко всем ячейкам памяти в ряду. Каждая линия выборки столбца выбирает все ячейки памяти в столбце, разрешая запись. На средней фотографии показаны участки кремния и поликремния для одной ячейки памяти. Слои металла были удалены для того, чтобы открыть находящиеся под ними транзисторы. Слои металлизации соединяют транзисторы, круги на фото, это соединения, переходные отверстия, между кремнием или поликремнием и металлом. Схема показывает, как пять транзисторов соединены, размещение элементов на схеме соответствует их размещению на фото. Две пары транзисторов формируют КМОП-инвертеры, проходной транзистор снизу слева обеспечивает доступ к ячейке.
Восемь бит конфигурационной памяти, четыре сверху и четыре снизу. Красный прямоугольник — один бит. Когда линия выборки столбца активирована, линия данных строки загружает данные в соответствующую ячейку. Увеличенное фото и схема показывают один бит конфигурационной памяти. Взято отсюда: siliconpr0n.
Мультиплексоры таблицы просмотра
Как объяснялось ранее, ПЛИС реализует произвольные логические функции, используя таблицы просмотра. На рисунке ниже показано, как реализована таблица просмотра в XC2064. Восемь значений слева сохраняются в восьми ячейках памяти. Четыре мультиплексора выбирают одну из каждой пары значений, в зависимости от значения на входе А, если А = 0, выбирается верхнее из значений, если А = 1, то нижнее. Затем, большой мультиплексор выбирает одно из четырёх значений, основываясь на сигналах В и С. Результатом будет определённое значение, в данном случае A XOR B XOR C. Мы можем сделать любую логическую функцию, если будем подставлять разные значения в таблицу.
Реализация XOR в таблице просмотра.
Каждый мультиплексор реализован с помощью проходных транзисторов. В зависимости от сигналов управления, один из проходных транзисторов активируется, пропуская данные со входа на выход. Рисунок внизу показывает часть цепи LUT, с мультиплексированием двух бит. Справа находятся две ячейки памяти. Каждый бит проходит через инвертер, усиливается, и проходит через проходные транзисторы мультиплексора в середине, выбирая один из этих бит.
Вид цепей, реализующих LUT. Взято с siliconpr0n.
Триггер
Каждый блок CLB содержит триггер, позволяющий ПЛИС реализовывать защёлки, конечные автоматы, и другие цепи, сохраняющие состояние. На рисунке снизу показана (несколько необычная) реализация триггера. Она использует следующую схему. Когда тактовый сигнал в нуле, первый мультиплексор пропускает данные на первую защёлку, которая запоминает значение. Бит инвертируется дважды, так как проходит через элементы OR, NAND и инвертер, и в результате остаётся тем же. далее, мультиплексор второй защёлки принимает бит с первой защёлки, когда тактовый сигнал поднимается в 1 (отметим, что тактовый сигнал инвертирован). Это значение является выходом триггера. Когда тактовый сигнал устанавливается в 0, вторичный мультиплексор замыкает петлю, защёлкивая бит. Таким образом, триггер чувствителен к фронту сигнала, защёлкивая значение на переднем фронте тактового сигнала. Линии установки и сброса устанавливают и сбрасывают триггер.
Реализация триггера. Стрелки показывают на первый мультиплексор и два элемента OR-NAND Фото кристалла взято отсюда: siliconpr0n.
Восьмивыводная матрица переключателя
Матрица переключателя является важным элементом межсоединений. Каждый переключатель имеет 8 выводов (по два на каждой стороне) и может соединять их почти как угодно. Сигналы могут разворачиваться, разделяться, пересекаться с большей гибкостью, чем в отдельных узлах межсоединений. На рисунке снизу показана часть сети межсоединений между четырьмя CLB (голубые). Переключающие матрицы (зелёные) могут соединяться в любых комбинациях соединений с правой стороны. Отметим, что каждый вывод может соединяться с другими выводами в количестве от 5 до 7 штук. Например, вывод 1 может быть соединён с выводом 3, но не с выводами 2 и 4. Это делает матрицу почти полной, с 20 возможными соединениями вместо 28.
Взято отсюда: Xilinx Programmable Gate Array Data Book, рис. 7b.
Переключающая матрица образована рядами проходных транзисторов, управляемых ячейками памяти над ними и под ними. Две стороны транзистора представляют собой два вывода переключающей матрицы, которые могут быть соединены транзистором. Таким образом, каждая матрица имеет 20 управляющих бит, две матрицы на плитку дают нам 40 бит на плитку. На фото внизу изображена одна ячейка памяти, подсоединённая к волнистому затвору проходного транзистора под ней. Этот транзистор обеспечивает соединение между выводом 5 и выводом 1. Таким образом, бит в битстриме, соответствующий этой ячейке памяти, управляет соединением между выводами 5 и 1. Аналогично, другие ячейки памяти и связанные с ними транзисторы управляют другими соединениями. Отметим также, что порядок этих соединений не следует какому-то определённому паттерну, в результате, соответствие между битами в битстриме и выводами переключателя выглядит случайным.
Реализация 8-выводной матрицы соединений. Области кремния обозначены номерами соответствующих им выводов. Слои металла, соединявшие соответствующие выводы с транзисторами, удалены. Взято с siliconpr0n.
Соединения входов
Входы CLB используют другую схему кодирования битстрима, которая объясняется его аппаратной реализацией. На рисунке ниже, восемь обведённых эллипсом узлов являются потенциальными входами в CLB под названием DD. Только один узел (максимум) может быть сконфигурирован как вход, так как подсоединение двух сигналов к одному входу может закоротить их вместе.
Выбор входа. Восемь входов, обведённых зелёным, являются потенциальными входами DD, только один из них может быть выбран.
Требуемый вход выбирается мультиплексором. Прямолинейным решением было бы использование 8-входового мультиплексора с тремя битами управления, выбирающими один из 8 сигналов. Другим прямолинейным решением было бы использование 8 проходных транзисторов, каждый со своим управляющим сигналом, один из которых выбирает требуемый сигнал. Однако, ПЛИС использует гибридный подход, который устраняет необходимость в декодере, необходимом в первом случае, но требует 5 управляющих сигналов вместо 8, требуемых при втором подходе.
ПЛИС использует мультиплексоры для выбора одного из восьми входов.
Схема на рисунке выше показывает двухуровневый мультиплексор, использованный в ПЛИС. На первой стадии активируется один из управляющих сигналов. На второй стадии выбирается верхний или нижний сигнал и подаётся на выход. Для примера, предположим, что управляющий сигнал B/F подан на первую стадию, и ABCD на вторую стадию, вход B будет единственным, который прошёл на выход. То есть, выбор одного из восьми входов требует 5 бит в битстриме и использует 5 ячеек памяти.
Заключение
XC2064 использует различные высокооптимизированные цепи для реализации логических блоков и соединения цепей. Эти цепи требуется плотно упаковать, чтобы они вошли на кристалл. Даже несмотря на это, XC2064 был очень большим чипом, больше, чем микропроцессор того времени, и его производство было сложным, он стоил сотни долларов. По сравнению с современными ПЛИС, XC2064 имеет абсурдно малое число ячеек, но даже это послужило началом революционно новой линейке продуктов.
Две концепции являются ключевыми для понимания битстрима XC2064. Первая — ПЛИС реализована на основе 64 плиток, повторяющихся блоков, которые комбинируют логические блоки и межсоединения. Несмотря на то, что ПЛИС описывается как нечто, имеющее логические блоки, окруженные межсоединениями, она реализована не так. Вторая концепция состоит в том, что битстрим не основан ни на каких абстракциях, он напрямую отображает двумерную упаковку ячеек памяти ПЛИС. Таким образом, битстрим имеет смысл только если вы рассматриваете физическую структуру ПЛИС.
Следующая таблица обобщает смысл каждого бита в плитке, в части битстрима размером 8×18. Каждая строка в таблице соответствует одному биту в битстриме, и показывает, какая часть ПЛИС управляется этим битом. Пустые строки соответствуют неиспользованным битам.
Первые два столбца таблицы соответствуют переключающей матрице. Есть две переключающие матрицы, обозначенные как #1 (красная) и #2 (зелёная) на рисунке ниже. 8 выходов матрицы #1 пронумерованы от 1 до 8 по часовой стрелке. Переключатель #2 пронумерован так же, но не хватило места для номеров. Например, "#2: 1-3" обозначает, что этот бит соединяет выводы 1 и 3 на переключателе #2. Следующий столбец определяет «ND», ненаправленные связи, прямоугольники ниже пурпурных цифр около переключательных матриц. каждый бит ND в таблице управляет соответствующим соединением ND.
Схема межсоединений показывает схему нумерации, которую я сделал для таблицы битстрима. Следующие две колонки описывают то, что я называю PIP соединения, сплошные прямоугольники, на линиях выше. Соединения с выхода Х (коричневые) управляются отдельными битами (Х1, Х2, С3), аналогично для соединения с выхода Y (желтый). Соединения к входу В (светло-пурпурный) устроены по-другому. Только одно из входных соединений может быть активно, и они кодируются множеством бит, с использованием мультиплексоров. Вход С (голубой), D (синий), и A (зелёный) похожи. Остальные столбцы в таблице описывают CLB, обратитесь к документации за подробностями. Биты управляют тактовым сигналом, установкой и линией сброса. Выходы X и Y могут быть выбраны из таблиц (LUT) F и G. Последние два столбца определяют LUT. Есть три входа для LUT F и три входа для LUT G, мультиплексоры управляют входами. Наконец, 8 бит для каждого LUT определяются, задавая выход для определённой комбинации трёх входов.
Я анонсировал свой последний пост в твиттере, так что подписывайтесь на kenshirriff. Также я имею RSS-фид. Благодарю John McMaster, Tim Ansell и Philip Freidin за дискуссии.
Автор: Владимир