Читаем ДНК ПЛИС (Часть 1)
Оглавление
Аннотация
Введение
Идентификатор и DNA кристалла
Модуль DNA_PORT
Считывание DNA
Режимы работы DNA_PORT
Разработка модуля для считывания DNA
Сборка проекта в IPIntegrator
Моделирование
Проверка в железе
Заключение (см. часть 2)
Домашнее задание (см. часть 2)
Библиографический список (см. часть 2)
Список тренингов (см. часть 2)
В этой статье рассмотрен аппаратный блок DNA_PORT ПЛИС Xilinx, который хранит уникальный номер FPGA, способный помочь Вам защитить Ваши проекты от копирования и вести учёт версий и отдельных копий прошивки. Использованный демонстрационный проект собран с помощью IP Integrator, который, начиная с версии Vivado 2017.1, поддерживает схемотехническое соединение модулей, написанных на SystemVerilog, Verilog и VHDL. Приведены полное описание модуля DNA_PORT, пошаговая инструкция по сборке проекта, результаты его поведенческого моделирования и аппаратной проверки, выполненной с помощью Logic Analyzer.
Не секрет, что в FPGA существуют некоторые аппаратные модули/регистры, которые могут быть однократно запрограммированы пользователем. Такие регистры в FPGA компании Xilinx носят название eFUSE. Среди этих eFUSE регистров есть и такой, который программируется непосредственно на фабрике при изготовлении и хранит уникальный номер конкретного кристалла. Широко известно, что конфигурация молекулы ДНК (DNA) является практически уникальным идентификатором любого живого организма. Потому, по аналогии, этот регистр своих FPGA компания Xilinx назвала «DNA». А аппаратный модуль, позволяющий считать DNA кристалла, был назван DNA_PORT.
Уникальность аппаратного блока DNA_PORT в том, что считанные им данные доступны не только через интерфейс JTAG, но и непосредственно для проекта, залитого в FPGA. Остальные eFUSE-регистры такой возможности не имеют: их содержимое может быть считано исключительно через JTAG.
Поскольку DNA – это уникальный номер FPGA (повтор возможен, но только у 32 микросхем во всем семействе, и при этом не внутри подсемейства), то он может быть применён для различного круга задач: от защиты проекта от копирования на другие кристаллы до помощи в понимании текущей версии прошивки.
Цель статьи – дать общее представление о модуле DNA_PORT.
Задачи, которые поставлены в этой статье:
1. Разработать модуль для чтения уникального DNA-номера FPGA.
2. Выполнить моделирование.
3. Провести имплементацию проекта.
4. Проверить корректность работы модуля в логическом анализаторе на реальном кристалле, установленном на имеющейся в нашем распоряжении макетной плате Arty Board.
При описании будем ориентироваться на 7-ое семейство FPGA Xilinx, поскольку на Arty Board установлена ПЛИС Artix-7, хотя и в других семействах тоже имеется DNA_PORT. За основу будут взяты следующие руководства пользователя [1, 2, 3].
В кристаллах 7-ого семейства компании Xilinx имеется специализированный аппаратный блок, хранящий уникальный 64-битный идентификатор (FUSE_DNA). Он может быть использован проектом для получения 57-битного значения DNA кристалла. Идентификатор хранится в энергонезависимой памяти и программируется однократно при производстве кристалла, а далее является неизменным. Этот номер является уникальным для каждого экземпляра FPGA 7 ого семейства. Однако внутри семейства – но не внутри подсемейства – возможно появление 32 экземпляров FPGA с одинаковым номером. Это означает, что внутри подсемейства Artix-7 не может быть двух FPGA, у которых совпадут DNA, но могут быть совпадения между, например, экземплярами Kintex-7 и Artix-7. Чтение полного 64-битного номера FPGA (FUSE_DNA) возможно только с помощью JTAG. При этом 57-битный DNA-номер, доступный для чтения прошивкой при помощи модуля DNA_PORT, расположен с 63 по 7 биты FUSE_DNA.
Аппаратный модуль DNA_PORT позволяет получить доступ к DNA-номеру кристалла. Различные варианты графического отображения соответствующего блока приведены на рисунке 1.
Рисунок 1 – Различные представления модуля DNA_PORT
Как видим, аппаратный модуль DNA_PORT имеет всего 5 портов:
• DIN – порт ввода пользовательских данных. Пользователи могут дополнять считываемый номер DNA своими данными, если это необходимо. См. далее схемы включения DNA_PORT.
• READ – порт команды чтения данных из постоянного регистра во временный, из которого данные могут быть считаны пользователем.
• SHIFT – порт команды выполнения сдвига DNA-номера. Временный регистр, доступный пользователю для чтения, представляет собой простой сдвиговый регистр.
• CLK – вход тактового сигнала.
• DOUT – выход данных со сдвигового регистра.
На рисунке 2 показано устройство и функционал модуля DNA_PORT.
Рисунок 2 – Функционал модуля DNA_PORT
Для того чтобы выполнить считывание DNA кристалла, необходимо выставить значение READ в «1» на один такт CLK, после чего DNA будет передан во временный сдвиговый регистр, который доступен для считывания пользователю. Для выполнения операции сдвига в сдвиговом регистре необходимо управлять входом SHIFT. Ниже приведена таблица с операциями, доступными для модуля DNA_PORT.
Рисунок 3 – Список допустимых операций модуля DNA_PORT
Одним достаточно важным ограничением является тактовая частота работы модуля DNA_PORT. Для того чтобы найти диапазон допустимых значений тактовой частоты работы модуля, необходимо обратиться к [3]. Согласно таблице на рисунке 4, максимальная рабочая частота чтения DNA для нашего кристалла на Arty Board составляет 100 МГц. Учтите эти ограничения, если вы будете использовать DNA_PORT: для других семейств значения могут отличаться.
Рисунок 4 – Значения максимальной рабочей частоты модуля DNA_PORT
Считываемое с помощью DNA_PORT уникальное значение DNA может быть расширено пользователем. Для этого используется одна из следующих трёх схем включения данного модуля:
1. Наиболее часто используемая простейшая схема включения: на вход DIN подаётся константа «0» или «1»:
Рисунок 5 – Схема включения модуля DNA_PORT с дополнением константой
2. Расширенная схема включения, в которой вход DIN и выход DOUT образуют обратную связь, неограниченно расширяя тем самым считываемое значение DNA его же циклическими копиями:
Рисунок 6 – Схема включения модуля DNA_PORT в режиме зацикливания
3. Расширенная схема включения, в которой считываемый номер DNA расширяется произвольными пользовательскими данными:
Рисунок 7 – Включение модуля DNA_PORT в режиме дополнения пользовательскими данными
Разработка модуля для считывания DNA
Поскольку аппаратный модуль DNA_PORT позволяет получить доступ к DNA, нам необходимо разработать модуль, который бы управлял им. Согласно таблице на рисунке 3, логика функционирования разрабатываемого модуля оказывается достаточно несложной, так что разумнее всего реализовать его в виде конечного автомата, последовательно проходящего следующие состояния:
1. Ожидание сигнала старта для считывания DNA.
2. Установка сигнала READ на один такт для записи DNA во временный сдвиговый регистр.
3. Управление сигналом SHIFT для сдвига значений и их записи.
4. Запись текущего значения в другой сдвиговый регистр для параллельной выдачи результата.
5. Установка сигнала DONE, сообщающего о завершении чтения DNA.
Модуль, реализующий конечный автомат и параллельную выдачу значения DNA, приведён в листинге 1. Реализовывать конечный автомат и последующее подключение модулей мы будем для схемы на рисунке 5.
СКАЧАТЬ ФАЙЛ ЛИСТИНГА
Листинг 1
Но для полноценной работы нам необходимы ещё 2 модуля:
1. Экземпляр непосредственно самого DNA_PORT.
2. Блок формирования и управления тактовой частотой.
Для добавления в код экземпляра модуля необходимо воспользоваться шаблонами для вставки, которые можно найти либо в [2], либо в подборке языковых шаблонов (Language Templates) Vivado:
Рисунок 8 – Доступ к шаблонам Vivado
Рисунок 9 – Шаблоны модуля DNA_PORT
Этот шаблон вставляется в модуль, который называется dna_port_wrapper. Его код приведён в листинге 2:
СКАЧАТЬ ФАЙЛ ЛИСТИНГА 2
Листинг 2
Сборка проекта в IP Integrator
Начиная с версии Vivado 2017.1 в IP Integrator (который мы использовали для сборки процессорной системы на базе Microblaze) появилась возможность выполнять подключение не только блоков IP, но и произвольных модулей, описанных на RTL-уровне. Для того, чтобы это сделать, создадим новый Block Design:
FlowNavigator →IP INTEGRATOR→Create Block Design:
Рисунок 10 – Меню для создания Block Design
Вводим имя Block Design: «dna_reader_top»
Рисунок 11 –Задание имени для BlockDesign
Для добавления модулей на рабочее поле, необходимо во вкладке Sources выбрать RTL-модуль, который мы хотим добавить, кликнуть правой кнопкой мыши и выбрать Add Module to Block Design:
Рисунок 12 –Вызов меню добавления RTL модуля в BlockDesign
После этого на рабочем поле Diagram появится выбранный модуль, с надписью «RTL» посерeдине:
Рисунок 13 –Экземпляр RTL-модуля dna_reader_fsm
Таким же образом добавляем модуль dna_port_wrapper:
Рисунок 14 – Экземпляр модуля dna_port_wrapper
Теперь добавляем модуль управления тактовой частотой и синхронизацией. Кликаем правой кнопкой в пустом месте на поле Diagram, нажимаем Add IP, в поле поиска вводим Clocking Wizard. Должен появиться следующий IP:
Рисунок 15 – IP-блок управления тактовой частотой и синхронизацией
Выполним настройку тактовых частот:
1. Дважды кликаем по символу clk_wiz_0.
2. Устанавливаем входную тактовую частоту 100 МГц.
Рисунок 16 – Настройка входной тактовой частоты
3. Устанавливаем выходную тактовую частоту во вкладке Output Clocks: clk_out1– 50МГц.
Рисунок 17 –Настройка выходной тактовой частоты
4. Пролистываем вниз и снимаем галочку для отключения входа reset
Рисунок 18 – Отключение входа reset
5. Нажимаем OK.
Поскольку мы реализуем включение по схеме с рисунка 5, необходимо добавить IP блок Constant и установить его значение в «0»:
Рисунок 19 – Установка значения IP блока constant в 0
Выполним подключение внешних выводов и соединение блоков. Сделаем вход clk_in1 модуля clk_wiz_0 внешним:
1. Кликаем правой кнопкой по символу clk_in1.
2. Выбираем Make External.
Рисунок 20 – Объявление порта clk_in1 внешним
После этого должен появиться порт clk_in1_0:
Рисунок 21 – Созданный внешний порт для clk_in1
Переименуйте clk_in1_0 в clk_in1. Это можно сделать в окне External Port Properties, доступном по нажатию на clk_in1_0.
Рисунок 22 – Переименование порта
Выполните аналогичные шаги для выводов istart, odna_ready и odna[63:0] модуля dna_reader_fsm_0, чтобы получился результат, как на рисунке 23 (для оптимизации рабочего пространства нажмите кнопку Regenerate Layout, доступную на панели инструментов):
Рисунок 23 – Объявление внешними нескольких портов проекта
Теперь мы можем выполнить подключение модулей. Окончательный вариант выглядит, как показано на рисунке 24:
Рисунок 24 – Схема соединения модулей
Для выполнения DRC в Block Design, нажмите на кнопку Validate Design. Если всё было выполнено корректно, появится сообщение, как на рисунке 25. Если же появились ошибки, внимательно прочитайте текст пояснений и постарайтесь исправить ошибки самостоятельно.
Рисунок 25 – проверка на Block Design на ошибки
Сохраните проект, нажав на кнопу Save:
Рисунок 26 – Cохранение результатов
Обратите внимание, что модули RTL пока что не появляются в иерархии Block Design. Необходимо создать обёртку для Block Design «dna_reader_top», кликнув по нему правой кнопкой мыши и выбрав Create HDL Wrapper:
Рисунок 27 – Создание обёртки для Block Design
После этого дерево иерархии проекта обновится.
Рисунок 28 – Окно иерархии проекта
Теперь пометим модуль dna_reader_top_wrapper в качестве модуля верхнего уровня – сделаем его собственно «топовым». Для этого кликаем по нему правой кнопкой мыши и выбираем Set as Top:
Рисунок 29 – Задание модуля верхнего уровня
Теперь иерархия проекта выглядит следующим образом:
Рисунок 30 – окно иерархии проекта
Как видите, для каждого RTL-модуля создаётся обёртка. Вы можете менять содержимое RTL-модулей, то есть редактировать их. Только не забывайте при этом делать обновление моделей в Block Design. Если содержимое RTL-модуля было изменено, появится соответствующее сообщение.
Наш проект собран, и теперь мы можем выполнить его моделирование (симуляцию). Если Вы обратили внимание, то при моделировании Вы можете указать значение, которое будет выдавать DNA_PORT. Для его модели оно является параметром.
Рисунок 31 – Значение DNA для моделирования
Код модуля тестирования (тестбенча) приведён в листинге 3:
СКАЧАТЬ ФАЙЛ ЛИСТИНГА 3
Листинг 3. Код тестбенча
Результаты моделирования приведены на рисунке 32.
Рисунок 32 – Результаты моделирования проекта
После удачного моделирования необходимо выполнить проверку модуля на аппаратном уровне – «в железе». Делать мы это будем с помощью логического анализатора Logic Analyzer. Но прежде, чем к этому приступить, нам необходимо сказать Vivado, какие цепи мы хотим наблюдать и отлаживать в логическом анализаторе. Нас будут интересовать istart, odna_ready и odna[63:0]. Чтобы их добавить в логический анализатор:
1. Выберите цепь.
2. Нажмите на ней правой кнопкой мыши.
3. Выберите из появившегося меню пункт Debug.
Рисунок 33 – Отмечаем цепи для отладки
Повторите эти действия для odna_ready и istart. Сохраните текущие изменения.
Однако, перед выполнением синтеза нам предстоит создать ещё один модуль верхнего уровня. Причина, по которой необходимо это сделать: сейчас у нас внешними (то есть теми, которые будут подключены к ножкам ПЛИС) являются 67 выводов модуля: iclk, istart, odna_ready и odna[63:0]. После синтеза и имплементации они должны быть физически подключены к ножкам ПЛИС – в противном случае мы не сможем получить файл прошивки. Но на Arty Board нет 67 свободных портов – да и они нам не нужны. Нам нужны только iclk и istart – поэтому мы создаём новый модуль, в котором наружу подключаем только эти два вывода. Листинг модуля top приведён ниже:
СКАЧАТЬ ФАЙЛ ЛИСТИНГА 4
Листниг 4. Код модуля top
Поскольку мы отметили сигналы для отладки, то они не будут выборшены в ходе оптимизации во время синтеза, и мы сможем наблюдать значения на них.
Запускаем синтез:
Рисунок 34 – Запуск синтеза проекта