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» — классический курс на русском языке.
- 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 (т.е. состояния всех «переменных») при следующих входных воздействиях:
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)
- понимать, как должен быть устроен «идеальный» тестбенч
Литература:
- 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 — напишите в личку или в комментариях — я обязательно добавлю её в статью.
Литература:
Видеоуроки:
Тестовые вопросы:
- Чем отличается 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. (*)
В вопросах, обозначенных (*), разумеется, не надо помнить всё наизусть, а можно пользоваться даташитами.
Синхронный дизайн и всё, что связано с таймингами
Необходимо:
- знать принцип синхронного дизайна
- знать к каким отрицательным последствиям могут привести те или иные схемы
- иметь понятие о констрейнах
Литература:
Тестовые вопросы:
- Что такое констрейны? Где они описываются и для чего нужны (для чего они используются)? Что будет, если их не описать?
- Что такое clock domain crossing? Как и когда надо его осуществлять?
- В чем разница между синхронным и асинхронным сбросом? Что будет если на вход синхронного сброса завести асинхронный сброс?
- Что такое latch (защелка, латч)? Какие последствия использования латча? Приведите пример кода, который создает латч.
- Что такое комбинационная петля? Какие последствия использования комбинационной петли?
- Что такое метастабильность? Как её достичь? Какие у неё есть плюсы и минусы?
- Что такое glitch (глитч)? Нужно ли с этим бороться? И если да, то где и как?
- Что такое setup time/hold time у D-триггера?
САПР
Необходимо:
- уметь создавать проект
- уметь описывать I/O пины и констрейны
- уметь пользоваться инструментом для отладки на железе
- уметь пользоваться инструментом для анализа таймингов
Литература:
Видеоуроки:
Лекции и лабораторные
Я два семестра читал курс «Разработка под 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.
Слайды к лекциям
Иногда будут видны картинки, которые никак не связаны с соседними (например, задания для тестов, которые давались на лекциях).
Лабораторные работы:
Классические ошибки
В этой части статьи я расскажу о типичных ошибках, которые допускают начинающие разработчики, и дам советы по их устранению.
Проблема в таймингах
Симптомы:
- результаты симуляции не совпадают с тем, что происходит на железе
- железо работает нестабильно: иногда явно видны помехи (например, на VGA)
- «я добавил сигналтап, и после этого схема перестала корректно работать, я убрал сигналтап и всё хорошо»
Лечение:
- прописать все необходимые констрейны, (как минимум используемую тактовую частоту (или частоты) в *.sdc файле), подключить этот файл в проект
- перекомпилировать проект. Зайти в TimeQuest и посмотреть, есть ли отрицательные слаки, и если есть, то дальше разбираться почему это происходи (возможно, достаточно покрутить настройки в Quartus’e, или придется переписывать куски код).
Если вы видите странности в SignalTap, то перепроверьте, синхронны ли те сигналы, которые вы снимаете с частотой «стробирования».
Не соблюдение принципов синхронного дизайна (асинхронщина)
Продолжение первого пункта, но я решил его выделить отдельно.
Симптомы аналогичные с предыдущим пунктом.
Почему-то многие любят делать вот так:
...
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. Он формируется комбинационной логикой (выходом компаратора).
Или вот так:
...
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.
Иногда мне в личке пишут:
Добрый день.
Я студент 3(4, 5) курса такого-то университета.
Мне нравится идея писать под FPGA (параллелизм, можешь делать что хочешь, бла-бла-бла) и нравится Java (делал простенькие приложения под Android). Хочу чем-то из этим заняться более-менее серьезно. Что советуете учить?
Чаще всего я им предлагаю глянуть две ссылочки (FPGA и JAVA) и самостоятельно сделать выводы.