Junior FPGA Design Engineer: как стать?
Всем привет!
Иногда начинающие разработчики не очень хорошо представляют, какую литературу надо читать для серьезного изучения того или иного языка.
Разработка под FPGA — это не просто какой-то язык. Это очень объемная область, с огромным количеством подводных камней и нюансов.
В этой статье вы найдете:
- список тем, которые должен освоить начинающий разработчик под FPGA
- рекомендуемую литературу по каждой из тем
- набор тестовых вопросов и лабораторных работ
- классические ошибки новичков (и советы по исправлению)
Что надо знать и уметь
Цифровая схемотехника
Необходимо:
- знать базовые цифровые узлы (логические элементы И/ИЛИ/НЕ, шифраторы, мультиплексоры, суммматоры и пр.)
Литература:
- David Harris, Sarah Harris. «Digital Design and Computer Architecture» — очень большая книга, рассказывающия от азовов до верхов. Есть версия на русском языке. Я просмотрел русскую версию: читается очень быстро и легко.
- Угрюмов Е.П. «Цифровая схемотехника» — классический
советскийучебник, со всеми вытекающими последствиями (некоторые темы объяснены слишком сложно, и нельзя сразу понять нужна ли тебе эта информация сейчас или можно её пропустить). Я читал более старое издание, возможно в издании от 2010 года всё изменилось в лучшую сторону, не смотрел.
Тестовые вопросы:
- Чем цифровая схемотехника отличается от аналоговой?
- Какие есть базовые цифровые узлы? В каких из них выход зависит только от входа?
- Что такое мультиплексор? Нарисуйте схему мультиплексора 4 в 1 из примитивных элементов И/ИЛИ/НЕ.
- Постройте таблицу истинности для выражения: X = A or ( B and C ) or D.
Синтаксис HDL-языка
Сюда входит:
- знание синтезируемых конструкций (синтаксиса) HDL-языка
- знание, как описывать базовые цифровые узлы с помощью HDL-языка
- понимание во что (со стороны базовых цифровых узлов) превращается тот или иной кусок HDL-кода
- умение писать на HDL-языке для получения нужного поведения
В качестве HDL-языка я рекомендую сначала изучить самые базовые конструкции Verilog‘a, а затем переключится на SystemVerilog.
Литература:
- Pong P. Chu. «FPGA prototyping by Verilog examples» — расписывается Verilog, начиная с азов. Подробно разбирается синтаксис и есть огромное количество примеров, как простых (счетчики), так и уровнем повыше (UART и VGA).
- Иосиф Каршенбойм. «Краткий курс HDL» — классический курс на русском языке.
- http://www.asic-world.com/ — сайт с кучей примеров как по Verilog, так и по SystemVerilog.
- David Harris, Sarah Harris. «Digital Design and Computer Architecture» (см. выше)
- Stuart Sutherland. «SystemVerilog for Design» — книга про различия Verilog и SystemVerilog. Для чтения необходимы базовые знания Verilog’a. Рекомендуется к прочтению для понимания, какие удобства были внесены в новом стандарте.
Тестовые вопросы:
- Чем блокирующие присваивание отличается от неблокирующего? Когда стоит применять одно, когда другое?
- Есть ли разница между следующими тремя описаниями? Если да, то в чём она проявляется?
// code 1: assign a = b + c; // code 2: always @( b or c ) begin a = b + c; end // code 3: always @( * ) begin a = b + c; end
Тестовые задания:
1. Нарисуйте схему из базовых цифровых узлов для следующего кода:
module test( input clk_i, input a_i, input [2:0] b_i, output reg x_o ); reg [7:0] cnt = 8'd0; reg [7:0] cnt2; wire c; reg d; always @( posedge clk_i ) cnt <= cnt + 1'd1; always @(*) begin cnt2 = cnt + 1'd1; end assign c = ( cnt < 8'd5 ) && ( a_i == 1'b0 ); always @( posedge clk_i ) begin d <= c; x_o <= c ? ( d ) : ( cnt2[ b_i ] ); end endmodule
2. Нарисуйте поведение схемы из п.1 (т.е. состояния всех «переменных») при следующих входных воздействиях:
Времянки нарисованы с помощью онлайн-редактора WaveDrom.
3. Напишите модуль для управления светофором, который будет зажигать красный, желтый и зеленый фонари во всем известной последовательности: красный, красный и желтый, зеленый, зеленый моргает, желтый, красный. Параметры, задающие время горения фонарей светофора и период мигания зеленого фонаря являются параметрами модуля. Время задается в количестве тактов синхросигнала clk_i.
Интерфейс модуля:
module traffic_light( // cинхроимпульс input clk_i, // асинхронный сброс input rst_i, // если 1, то горит соответствующий цвет, если 0 — то он не горит output red_o, output yellow_o, output green_o );
Симулирование и верификация HDL-кода
Необходимо:
- знать несинтезируемые конструкции Verilog’a и SystemVerilog’a
- уметь написать простой тестбенч, запустить его в симуляторе (например, ModelSim)
- понимать, как должен быть устроен «идеальный» тестбенч
Литература:
- http://testbench.in/ — огромное количество примеров верификации с использованием Verilog’a и SystemVerilog’a.
- Chris Spear. «SystemVerilog for Verification» — хорошая, большая книга о верификации с помощью SystemVerilog. Читается легко, можно найти ответы на многие вопросы.
Видеоуроки:
Тестовые вопросы:
- Чем function отличается от task?
- Представим, что Вы написали максимально простую HDL-модель 5-стадийного RISC-процессора. Как будете её верифицировать? (Вопрос повышенной сложности).
- Чем различается queue от mailbox (типы данных в языке SystemVerilog)?
- Чем отличается функциональная симуляция от временной? Когда какую необходимо использовать?
FPGA
Необходимо:
- знать из каких базовых элементов состоит FPGA
- понимать как происходит workflow разработки под FPGA
- интуитивно представлять какие операции для FPGA дешевые, а какие дорогие (по частоте и ресурсам)
Я работаю с чипами Altera, поэтому здесь и дальше название семейств и утилит будет от этого вендора. Если вы знаете аналогичную литературу для Xilinx — напишите её в комментариях.
Литература:
- Andrew Moore. «FPGAs for Dummies» — рассказ про FPGA на очень высокоуровневом (маркетинговом) языке. Можно глянуть одним глазом.
- Altera Cyclone III Handbook — даташит на относительно старое семейство FPGA фирмы Altera.
- Steve Kilts. «Advanced FPGA Design» — класcная книга, раскрывает много нюансов разработки.
Видеоуроки:
- Altera. «Basics of Programmable Logic: FPGA Architecture»
- David L. Jones (EEVblog). «What Is An FPGA?» — шикарное видео с рассказом, что такое FPGA.
Тестовые вопросы:
- Чем отличается FPGA от ASIC? Из каких блоков состоит (или может состоять) FPGA?
- Попробуйте очертить круг задач, для которых хорошо (экономически целесообразно) использовать FPGA, а для каких MCU и CPU?
- Какие аппаратные блоки вы знаете? Для чего они используются? (Под аппаратными блоками здесь имеется в виду Hard IP).
- В семействе Y используется LUT с тремя входами и одним выходом. Какое минимальное количество LUT’ов надо для вычисления assign eq = ( a == b );, если a и b это 32-битные целые положительные числа? А если у LUT’a будет четыре (пять, шесть) входов?
- Необходимо создать одну-портовую память из 16 слов. Каждое слово шириной 100 бит. Сколько блоков M9K (9216 бит) будет занято? Считаем, что делаем проект под Cyclone III. (*)
В вопросах, обозначенных (*), разумеется, не надо помнить всё наизусть, а можно пользоваться даташитами.
Синхронный дизайн и всё, что связано с таймингами
Необходимо:
- знать принцип синхронного дизайна
- знать к каким отрицательным последствиям могут привести те или иные схемы
- иметь понятие о констрейнах
Литература:
- Steve Kilts. «Advanced FPGA Design» (см. выше).
- Altera. «Quartus Handbook» — глава Recommended Design Practices.
- Altera. «Understanding Metastability»
- nerudo. «Метастабильность триггера и межтактовая синхронизация»
Тестовые вопросы:
- Что такое timing constraints (констрейны)? Где они описываются и для чего нужны (для чего они используются)? Что будет, если их не описать?
- Что такое clock domain crossing? Как и когда надо его осуществлять?
- В чем разница между синхронным и асинхронным сбросом? Что будет если на вход синхронного сброса завести асинхронный сброс?
- Что такое latch (защелка, латч)? Какие последствия использования латча? Приведите пример кода, который создает латч.
- Что такое комбинационная петля? Какие последствия использования комбинационной петли?
- Что такое метастабильность? Как её достичь? Какие у неё есть плюсы и минусы?
- Что такое glitch (глитч)? Нужно ли с этим бороться? И если да, то где и как?
- Что такое setup time/hold time у D-триггера?
САПР
Необходимо:
- уметь создавать проект
- уметь описывать I/O пины и констрейны (хотя бы для простых ситуаций, без сложных I/O интерфейсов)
- знать какие есть отчеты о сборке, какая информация содержится в каждом из них
- уметь пользоваться инструментом для отладки на железе
- уметь пользоваться инструментом для анализа таймингов (STA)
- знать какие готовые IP-ядра/модули (FIFO, RAM, FFT, DDR, Ethernet и т.д.) предоставляет вендор и как их можно добавить в проект
Литература:
- Altera. «Quartus Handbook»
- Altera. «SignalTap II with Verilog Designs»
- Денис Шехалев. «Synopsys Design Constraint — язык задания временных ограничений на примере Altera TimeQuest» — хороший цикл статей на русском языке. см. также TimeQuest для чайников.
Видеоуроки:
- Altera. «The Quartus Prime Software: Foundation».
- Altera. «Using the Quartus Prime Software: An Introduction».
- Altera. «The Quartus II Software Interactive Tutorial».
- Altera. «TimeQuest Timing Analyzer»
Тестовые вопросы:
- Какие этапы сборки происходят от нажатия на кнопку «Собери проект полностью» до получения готового бинарного файла? Что происходит на каждом из этапов?
- Как посмотреть удалось ли САПР’у уложить проект в заданные ограничения (констрейны)?
Лекции и лабораторные
Я два семестра читал курс «Разработка под FPGA» для студентов старших курсов университетов Санкт-Петербурга. В курс входили как лекции, так и набор лабораторных работ. Лекции основывались на литературе, которую была перечислена выше.
План курса:
Введение:
- Что такое ПЛИС? Области применения.
- Обзор САПР ( Quartus ).
Изучение языка Verilog:
- Отличительне черты языков описания аппаратуры ( HDL ).
- Синтезируемые/несинтезируемые конструкции языка.
- Типы данных и способы их представления.
- Операции, блокирующие/неблокирующие операции присваивания
- Управляющие конструкции.
- Блоки описания узлов комбинационного типа.
- Блоки описания узлов последовательного типа.
- Структурное/поведенческое описание проекта.
- Параметризация.
- Реализация на Verilog базовых цифровых узлов.
Изучение несинтезируемых конструкций языка ( +SystemVerilog ):
- Применение несинтезируемых конструкций языка. Верификация. Testbench. Основные принципы создания testbench.
- Основные функциональные блоки testbench’ей.
- Типы данных. Блоки процедурного типа.
- Структуры данных для верификации ( массивы, очереди и т.д. ).
- Функции и tasks.
- Временная модель симуляции.
- Использование базовых принципов ООП для верификации.
- SystemVerilog Assertions.
- Создание testbench для базовых цифровых узлов.
- Обзор cуществующих методологий ( библиотек ) верификации.
Названия лекций (в 2015 году):
- Введение в FPGA.
- Внутреннее устройство FPGA.
- Введение в Verilog/SystemVerilog. Примеры описания различных типов логики.
- Синхронный дизайн. Создание простых тестбенчей.
- Описание FSM, массивов и структур в SystemVerilog. Память: создание с помощью Verilog и MegaWizard.
- Как работает DCFIFO. Static Timing Analysis. TimeQuest, constraints.
- Верификация: coverage, assertions, SystemVerilog interfaces
- Интерфейсы семейства Avalon. IP-Cores. Qsys.
- Верификация: SystemVerilog OOP, constrained-random tests.
К сожалению, это именно СЛАЙДЫ, которые мне помогали рассказывать лекции (не вся информация курса содержится на слайдах, некоторые я использовал как опору, а материал давался на доске).
Иногда будут видны картинки, которые никак не связаны с соседними (например, задания для тестов, которые давались на лекциях).
Лабораторные работы:
Классические ошибки
В этой части статьи я расскажу о типичных ошибках, которые допускают начинающие разработчики, и дам советы по их устранению.
Путаница в присваиваниях (блокирующие и неблокирующие)
Симптомы:
- вы не очень уверено ответили на вопрос о блокирующих и неблокирующих присваиваниях (см. выше)
- вы за собой замечаете, что в случайном порядке меняете «=» на «<=» (и наоборот), надеясь, что заработает
- симулятор показывает странные вещи, вы начинаете сомневаться, что понимаете как работает D-триггер
- результаты симуляции стабильно не совпадают с тем, что происходит на железе (где-то что-то плывет на такт)
Лечение:
- разобраться в материале по Verilog (см. литературу выше)
- если вы хотите, чтобы результат симуляции совпадал с тем, что будет синтезировано и воплощено на железе, то запомните простое правило: в блоках, где описывается комбинационная логика (always_comb, always @(*)) вы обязаны использовать только блокирующие присваивания (=). В блоках, которые описывают триггеры (always_ff, always @( posedge clk .. )) вы обязаны использовать только неблокирующие присваивания (<=).
Проблема в таймингах
Симптомы:
- результаты симуляции не совпадают с тем, что происходит на железе
- железо работает нестабильно: иногда явно видны помехи (например, на VGA)
- «я добавил сигналтап, и после этого схема перестала корректно работать, я убрал сигналтап и всё хорошо»
Лечение:
- прописать все необходимые констрейны, (как минимум используемую тактовую частоту (или частоты) в *.sdc файле), подключить этот файл в проект
- перекомпилировать проект. Зайти в TimeQuest и посмотреть, есть ли отрицательные слаки, и если есть, то дальше разбираться почему это происходи (возможно, достаточно покрутить настройки в Quartus’e, или придется переписывать куски код).
Если вы видите странности в SignalTap, то перепроверьте, синхронны ли те сигналы, которые вы снимаете с частотой «стробирования».
Не соблюдение принципов синхронного дизайна (асинхронщина)
Продолжение первого пункта, но я решил его выделить отдельно.
Симптомы аналогичные с предыдущим пунктом.
Почему-то многие любят делать вот так:
// BAD EXAMPLE ... input clk_i, ... logic [7:0] sec_cnt; logic [7:0] min_cnt; logic last_sec_value; assign last_sec_value = ( sec_cnt == 8'd59 ); always_ff @( posedge clk_i ) if( last_sec_value ) sec_cnt <= 'd0; else sec_cnt <= sec_cnt + 1'd1; always_ff @( posedge last_sec_value ) min_cnt <= min_cnt + 1'd1;
Т.е. в качестве входного сигнала на триггере min_cnt используется другой сигнал, чем синхроимпульс clk_i. Он формируется комбинационной логикой (выходом компаратора).
Или вот так:
// BAD EXAMPLE ... input clk_a_i, input clk_b_i, ... logic [7:0] cnt_a; logic [7:0] cnt_b; logic [7:0] sum; always_ff @( posedge clk_a_i ) cnt_a <= cnt_a + 1'd1; always_ff @( posedge clk_b_i ) cnt_b <= cnt_b + 1'd1; always_ff @( posedge clk_b_i ) sum <= cnt_a + cnt_b;
На вход триггера sum приходит выход комбинационной логики, вход у которой питается от разных тактовых сигналов.
Оба примера ошибочны, никогда так не делайте! Эти примеры — явное нарушение правил синхронного дизайна.
Я догадываюсь, что это всё идет из 2000х, когда чипы были маленькими и разработчики выживали как могли.
Скорее всего на маленьких частотах (типа 1 МГц) это прокатывало, но если вы собираетесь попасть в команду, которая делает серьезные вещи на топовых чипах, то за такие трюки можно легко вылететь со стажировки.
Лечение:
- пройтись по всему проекту, выписать (на бумажку) какой тактирующий клок (сигнал) используется для каждого триггера.
- понять как это число можно свести к минимальному количеству (в разумных пределах, разумеется), исправить код согласно правил синхронного дизайна.
- пройтись по всему проекту и внимательно отследить как происходит clock domain crossing (т.е. переход данных со одной частоту на другую). Исправить, если он происходит некорректно.
- выполнить все шаги из пункта «Проблема в таймингах».
Постоянная отладка на железе (игнорирование симуляции)
Вы допускаете эту ошибку, если разработка выглядит так:
- редактирование HDL-файла
- компиляция полного проекта
- прошивание бинарника на плату
- подключение с помощью SignalTap, просмотр нужных сигналов
- понимание ошибки, переход в п.1
Почему это плохо:
- с помощью SignalTap вы не можете посмотреть все-все-все сигналы, если у вас большой проект
- вы отнимаете своё время, или время работодателя, при компиляции полного проекта, т.к. это может занимать значительное время. На маленьких чипах, это занимает 5-10 минут, и можно типа забить и пойти в это время покурить/попить чай/поиграть в кикер, но на больших проектах это вам выйдет боком.
- нужна рабочая плата под рукой
- у вас нет уверенности, что изменения в коде рабочие и не сломают что-то другое
Лечение:
- написать тестбенч для всего проекта, либо для его частей
- добиться корректной работы в симуляции
- собрать проект, проверить на плате
Если что-то не заработает на железе, то:
- пройтись по пyнктам, обозначеным выше (тайминги и асинхронщина)
- если проблемы в таймингах нет, то пытаться понять при каких входных воздействиях это происходит
- подать эти воздействия в симуляции, убедиться, что проблема воспроизводится
- исправить ошибку в RTL-коде, проверить в симуляции и на железе
- обязательно: сделать вывод, почему предыдущий вариант симуляции не смог отловить эту ошибку
Нет правил разработки (+ код с запашком)
Симптомы:
- вы много времени тратите на чтение (разбор) кода, который написали вчера.
- вы часто пишите однотипный код (самые популярные клавиши на вашей клавиатуре это Ctrl+C и Ctrl+V)
- вы не можете разобраться в том коде, который написал коллега (если вы работаете вместе над одним модулем/IP-ядром), а он — в вашем.
Лечение:
- ознакомиться с литературой, которая рассказывает как надо писать хороший код, например, Макконнелл. «Совершенный код»
- разработать и описать правила разработки для команды. Или использовать готовые: NetFPGA, обсуждение на electronix #1, обсуждение на electronix #2, или тот, который использую я.
- отдайте свой код на ревью более опытным разработчикам. Об этом можно попросить на форуме electronix’a в соответствующем разделе. Разумеется, желательно, что-то более серьезное, чем моргание светодиодов, иначе вас просто не поймут :).
Заключение
Надеюсь, что в этой статье я раскрыл, что надо читать и знать для вхождения в мир разработки под FPGA.
Уверен, что если Вы:
- сможете легко отвечать на тестовые вопросы выше (без зазубривания, разумеется)
- решите правильно лабораторные работы
- избавитесь от «классических ошибок»
- оформите 1-2 проекта на гитхабе и проверите их на железе. (желательно, сложнее, чем моргание светодиодиков и часики).
то без проблем сможете претендовать на позицию джуниора в серьезной компании.
Разумеется, этот путь нельзя освоить за одни выходные. Может потребоваться месяц и не один, но этот путь надо пройти, если вы хотите перейти из студенченской FPGA-разработки в профессиональную.
Спасибо за внимание!
P.S. Оригинал статьи и последняя версия доступны тут.