
Однажды мне не спалось ночью и я залип на сайтах про паяльники. Возникло желание купить и сразу появились вопросы: на сколько ватт? Не больше 30? А почему большинство на 60-80 ватт? 60/40 олово свинец? А почему куча паяльных станций идут в комплекте с lead-free проводами припоя? Канифоль сейчас внутри проволоки? А почему есть и проволока припоя без канифоли? Бронзовую мочалку для очистки? А почему столько комплектов с и белой и бронзовой?
Вспомнил и повод, чтобы научиться паять. Когда-то Руслан Тихонов, руководитель кружка из Москвы, говорил мне что хочет сделать простые упражнения на платах ПЛИС для школьников. Как часть триады "микросхемы малой степени интеграции - ПЛИС - Ардуино". По этому поводу я купил самую дешевую плату с CPLD Altera MAX II (ныне это Intel FPGA), но обнаружил что у нее не припаян переходник.
Я выставил вопросы про паяльники на Фейсбук и после оживленной дискуссии мой приятель Денис Никитин вызвался научить меня паять как полагается. Денис работает проектировщиком печатных плат(*) в компании Zoox, ныне часть компании Amazon. Zoox делает беспилотные автомобили, то есть Денис на передовом рубеже паятельного прогресса. Я заснял мастер-класс от Дениса на видео:
(*) Точное описание позиции Дениса: тех лид, Staff Electrical Engineer. Денис отвечает за процесс разработки электронных модулей, включая архитектуру, принципиальные схемы, печатные платы, выбор компонентов и программы испытаний. По словам Дениса: "Паяем мы на этапе проектирования/прототипирования. Потом конечно машины на заво��е паяют."
Часть 1. Пайка
Часть 2. Плата ПЛИС, которую мы паяли
Что же из себя представляет плата, которую паяли мы вместе Денисом? Это самая базовая плата ПЛИС, которая бывает, и при этом на ней можно делать полезные упражнения, например познакомить школьников с проектированием цифровых схем на уровне регистровых передач с использованием языка описания аппаратуры SystemVerilog.
Вот сравните как работает макетка с микросхемами малой степени интеграции и плата с ПЛИС. Реализация сдвигового регистра на макетной плате с помощью микросхемы малой степени интеграции CMOS 4015:
Реализация двоичного счетчика на плате ПЛИС:
Внешне выглядит похоже, но первое - технология 1968 года, а второе - технология 2022 года: схема синтезирована из кода на языке описания аппаратуры SystemVerilog с помощью программы Intel Quartus Prime Lite Edition Design Software Version 22.1 (скачать для Linux и для Windows ):
Код для синтеза двоичного счетчика:

Вот как выглядит синтезируемая схема сдвигового регистра в Intel Quartus:

Часть 3. Связь рассыпухи, ПЛИС и Ардуино
Насчет микросхем малой степени интеграции у многих руководителей кружков есть сомнения: "ой, а зачем давать детям технологию 1968 года, это же остатки мамонта?" - спросят некоторые из них и прибавят: "Детям нужно Ардуино и Расберри Пай!"
А затем, что на микросхемах малой степени интеграции максимально наглядно видна работа базовых элементов интегральных схем: И / ИЛИ / НЕ, D-триггеров, мультиплексоров, декодеров и т. д. - всего, из чего состоят в том числе микроконтроллеры на платах Ардуино. Например, функцию D-триггера:
Никакое количество программирования Ардуино не заменит это знание, примерно так же как самые хорошие навыки по вождению автомашины не приблизят к навыкам по проектированию ее двигателя.

Другое дело, что за навыки по сборке на макетке микросхем малой степени интеграции вам не будут платить зарплату. И вот тут на помощь и приходит ПЛИС - именно ПЛИС прокладывает мостик между старыми и современными технологиями.
Когда вы синтезируете цифровые схемы и программируете их в ПЛИС, вы используете тот же язык проектирования Verilog, который использует и проектировщик микроконтроллера AVR на Ардуино, сидя в своем офисе в Колорадо Спрингс, и проектировщик микропроцессорного ядра ARM в Расберри Пай, сидя в своем офисе в Кембридже.

UPD: то, что Atmel куплен Microchip я знаю, но AVR могут продолжать поддерживать по старому адресу.
Часть 4. Главная технология проектирования микросхем в последние 30 лет
Немного про отличие процесса программирования от процесса проектирования микросхемы с помощью синтеза из языка описания аппаратуры (это стандартная методология проектирования микросх��м последние 30 с лишним лет). Программирование - это превращение кода в цепочку инструкций, которые хранятся в памяти и которые оттуда вытаскивает и переваривает процессор:

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

Все вместе и становится аппаратно-программным комплексом, который и представляет из себя Ардуино:

Часть 5. Природа ПЛИС
"Стоп!" - скажут некоторые читатели. "Но ведь микросхема выпекается на фабрике, а вы говорите что схема в ней потом меняется. Как это может быть?"
Пояснение: схема меняется в ПЛИС, а не обычном микроконтроллере Ардуино, который является вариантом микросхем ASIC (Application-Specific Integrated Circuits). ASIC строится из рядов фиксированных ячеек (так называемых standard cells). Их функция задается "при рождении". Одна ячейка - всегда И, другая - всегда D-триггер.
А вот функцию ячейки в ПЛИС можно менять - в ПЛИС находится "универсальная ячейка", гораздо крупнее, чем ячейка в ASIC. Она соединяется со специальной памятью, и биты в этой памяти определяют, через специальные переключатели / мультиплексоры, является ли ячейка И, ИЛИ, D-триггером или еще чем-то - уже на вашем столе, а не на фабрике.
Это не симулятор процессора в софтвере (в России симуляторы на уровне инструкций называются "эмуляторами", но это мы обсудим в другом посте). Симулятор процессора в софтвере - это программа, цепочка инструкций, а здесь конфигурация матрицы ячеек.
Из ячеек ПЛИС можно построить и аналог микропроцессорного ядра в Ардуино, но он будет дороже, с более низкой тактовой частотой и будет потреблять больше электроэнергии, чем фиксированная микросхема. Такова плата за гибкость.

Часть 6. Отступление о временах и нравах
Да, из ячеек ПЛИС можно строить даже процессор! Это тот самый "процессор в памяти", в существование которого 10 лет назад не верили топ-блоггеры Андрей Нифедов и Алекс Экслер. Они вместе высмеивали кружок электроники в Иркутске, хотя через лабы на платах ПЛИС прошли в свое время все современные проектировщики айфонов и микросхем в Теслах, это стандартная часть курса MIT 6.111. (Кружок в Иркутске мог использовать не ПЛИС, а GAL, но это детали, это все равно реконфигурируемая логика)
Учитывая, что Нифедов - бывший оператор станка с ЧПУ, а Экслер - обозреватель гаджетов, это было удивительно и поучительно! Особенно тысячи безумных комментов под их постами от людей, которые наверное думают, что раз они научилились тыкать пальцем в телефон, то что-то понимают как обучать будущих проектировщиков системы на кристалле (System on Chip - SoC) телефонов.

Часть 7. Пакет для обучения школьников с платами ПЛИС
Если какой-нибудь руководитель кружка хочет такое у себя внедрить, я создал проект на сайте GitFlic.ru под названием Пайка, ПЛИС и Линукс или FPGA Soldering Camp. Его описание "Исходники, презентации, задания и примеры для летнего лагеря по пайке, микросхемам ПЛИС и синтезу цифровых схем из кода на верилоге под Линуксом".

То есть идея в том, что школьники совершают своего рода многоборье, которое состоит из:
Работы с паяльником - 1 день.
Работы с макетными платами и микросхемами малой степени интеграции - 2 дня, потом им надоедает.
Синтеза цифровых схем на ПЛИС с простой платой - от 2-3 дня.
Работы с более сложной платой ПЛИС и например разработки простого однотактового процессора. Или интерфейса простой платы ПЛИС с Ардуино, если руководитель кружка хочет идти в эту сторону.
Все это делается под Линуксом, чтобы привыкали. Все разработчики микросхем для Тесл и Айфонов делают синтез и моделирование под Линуксом просто потому что они используют Synopsys Design Compiler и Cadence Genus и Innovus, у которых нет версий ни под Windows, ни под Макинтошем, только под Linux.
Впрочем, если вам очень не нравится Linux, пакет работает и под Windows (так как у Intel FPGA Quartus есть версия и под Linux, и под Windows).

Часть 8. Предыдущий опыт семинаров для школьников с микросхемами малой степени интеграции и ПЛИС
Вообще, я опробовал лагерь такого рода несколько лет назад на Новосибирской Летней Школе Юных Программистов и в других местах (Киев, Москва, Зеленоград). Смотрите мои другие статьи на Хабре или на silicon-russia.com.

Вот одно из видео оттуда, с восьмикласником Арсением Чегодаевым:
Часть 9. Как скачать пакет и текущие примеры в нем
Пакет можно или клонировать с помощью Git, или скачать релиз одного из двух видов пакета:
Пакет для использования со скриптами, написаными на баше. Со скриптами работать быстрее, но для начинающих GUI может быть удобнее в освоении.
В пакет входят следующие примеры:
01_and_or_not_de_morgan - обычные И, ИЛИ, НЕТ, правила де Моргана на SystemVerilog:
assign out_c1 = ~ (~ in_a & ~ in_b);
assign out_c2 = in_a | in_b; // Here is where De Mongan's Laws come in02_xor_bitwise_concat_and_parity - операции с исключающим ИЛИ на SystemVerilog.
Аналог такого примера на микросхемах малой степени интеграции выглядит так:
03_add_signed_and_unsigned - сумматор со знаком и без знака
С микросхемами малой степени интеграции (CMOS 4008) аналог выглядит так:

04_mux - реализации мультиплексора на SystemVerilog пятью разными способами:
// Five different implementations
assign mux = sel ? a : b;
assign mux2 = (sel & a) | (~ sel & b);
wire [1:0] ab = { a, b };
assign mux3 = ab [sel];
always_comb
if (sel)
mux4 = a;
else
mux4 = b;
always_comb
case (sel)
1'b1: mux5 = a;
1'b0: mux5 = b;
endcase
05_binary_counter - уже показал в начале статьи. Вот его аналог с подсоединенной микросхемой-драйвером для семисегментного индикатора. Семисегментный индикатор можно подсоединить и к ПЛИС тоже:
06_shift_register - сдвиговый регистр, уже показал в начале статьи
Четыре способа реализации декодера на SystemVerilog
module top
(
input [2:0] in_n,
output [7:0] out_n
);
wire [2:0] in = ~ in_n;
logic [7:0] out;
assign out_n = ~ out;
// Implementation 1: tedious
assign out [0] = ~ in [2] & ~ in [1] & ~ in [0];
assign out [1] = ~ in [2] & ~ in [1] & in [0];
assign out [2] = ~ in [2] & in [1] & ~ in [0];
assign out [3] = ~ in [2] & in [1] & in [0];
assign out [4] = in [2] & ~ in [1] & ~ in [0];
assign out [5] = in [2] & ~ in [1] & in [0];
assign out [6] = in [2] & in [1] & ~ in [0];
assign out [7] = in [2] & in [1] & in [0];
// Implementation 2: case
always_comb
case (in)
3'b000: out = 8'b00000001;
3'b001: out = 8'b00000010;
3'b010: out = 8'b00000100;
3'b011: out = 8'b00001000;
3'b100: out = 8'b00010000;
3'b101: out = 8'b00100000;
3'b110: out = 8'b01000000;
3'b111: out = 8'b10000000;
endcase
// Implementation 3: shift
assign out = 8'b00000001 << in;
// Implementation 4: index
always_comb
begin
out = '0;
out [in] = 1'b1;
endАналогичный декодер на микросхемах малой степени интеграции выглядит так:
Приоритетный энкодер на SystemVerilog четырьмя способами
module top
(
input [3:0] in_n,
output [7:0] out_n
);
wire [3:0] in = ~ in_n;
logic [1:0] out0, out1, out2, out3;
assign out_n = ~ { out0, out1, out2, out3 };
// Implementation 1. Priority encoder using a chain of "ifs"
always_comb
if (in [0]) out0 = 2'd0;
else if (in [1]) out0 = 2'd1;
else if (in [2]) out0 = 2'd2;
else if (in [3]) out0 = 2'd3;
else out0 = 2'd0;
// Implementation 2. Priority encoder using casez
always_comb
casez (in)
4'b???1: out1 = 2'd0;
4'b??10: out1 = 2'd1;
4'b?100: out1 = 2'd2;
4'b1000: out1 = 2'd3;
default: out1 = 2'd0;
endcase
// Implementation 3: Combination of priority arbiter
// and encoder without priority
localparam w = 4;
wire [w - 1:0] c = { ~ in [w - 2:0] & c [w - 2:0], 1'b1 };
wire [w - 1:0] g = in & c;
always_comb
unique case (g)
4'b0001: out2 = 2'd0;
4'b0010: out2 = 2'd1;
4'b0100: out2 = 2'd2;
4'b1000: out2 = 2'd3;
default: out2 = 2'd0;
endcase
/*
// A variation of Implementation 3: Using unusual case of "case"
always_comb
unique case (1'b1)
g [0]: out2 = 2'd0;
g [1]: out2 = 2'd1;
g [2]: out2 = 2'd2;
g [3]: out2 = 2'd3;
default: out2 = 2'd0;
endcase
*/
// A note on obsolete practice:
//
// Before the SystemVerilog construct "unique case"
// got supported by the synthesis tools,
// the designers were using pseudo-comment "synopsys parallel_case":
//
// SystemVerilog : unique case (1'b1)
// Verilog 2001 : case (1'b1) // synopsys parallel_case
// Implementation 4: Using "for" loop
always_comb
begin
out3 = '0;
for (int i = 0; i < w; i ++)
begin
if (in [i])
begin
out3 = 2' (i);
break;
end
end
end
endmodule
Приоритетный энкодер на микросхемах малой степени интеграции, вместе с микросхемой-драйвером семисегментного индикатора выглядит так:
Числа Фибоначчи, которые выводятся медленно, не на частоте 50 MHz
module top
(
input clk,
input rst_n,
output [7:0] led
);
wire rst = ~ rst_n;
//------------------------------------------------------------------------
logic [24:0] cnt;
always_ff @ (posedge clk)
if (rst)
cnt <= '0;
else
cnt <= cnt + 1'd1;
wire enable = (cnt == '0);
//------------------------------------------------------------------------
logic [7:0] num, num2;
assign led = ~ num;
// Note you have to press reset button to initialize the design
always_ff @ (posedge clk)
if (rst)
{ num, num2 } <= { 8'd1, 8'd1 };
else if (enable)
{ num, num2 } <= { num2, num + num2 };
endmodule
10_round_robin_arbiter - а вот это уже пример не школьный, а студенческий. Арбитр-мельница, популярный вопрос на интервью в электронные компании для джуниора. Пять реализаций по мотивам статьи Matt Weber. Arbiters: Design Ideas and Coding Styles. SNUG Boston 2001.
Часть 10. Можно ли выучить все это на программном симуляторе?
Две проблемы:
Во-первых, на SystemVerilog можно написать код, который будет работать в симуляторе, но не будет синтезироваться в схему, так называемый несинтезируемый код, который пишется для тестов и моделей.
Во-вторых, даже если код синтезируется, он может глючить на плате, например из-за так называемых гонок (race condition). Чтобы они не происходили, нужно соблюдать правила методологии, в частности не использовать блокирующие присваивания для переменных, которые превращаются в D-триггеры, например "a" внутри:
always @ (posedge clk) a = b;
always @ (posedge clk) c = a;В-третьих, код может симулироваться, но глючить на плате из-за метастабильного состояния, дребезга и нарушения тайминга внутри такта. Конечно, можно обязать ученика пропускать код через статический анализ тайминга одновременно с симуляцией, но без глючащей платы это выглядит как придирчивость преподавателя, а не реальное требование. Реальное железо лучше научит!
Часть 11. Что означают дополнительные файлы (причем на языке Tcl ?) в пакете?
Кстати, раз уж мы заговорили о нарушении тайминга и других таких параметрах. Преподавателю во время показа этих примеров ученикам, помимо кода на верилоге также нужно показать код на языке Tcl (знать его не обязательно) в двух файлах - top.qsf и top.sdc. Первый привязывает логические порты блока к физическим ножкам микросхемы.
Выглядит файл top.qsf так:
set_global_assignment -name DEVICE EPM240T100I5
set_global_assignment -name NUM_PARALLEL_PROCESSORS 4
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY .
set_global_assignment -name TOP_LEVEL_ENTITY top
set_global_assignment -name SEARCH_PATH ..
set_global_assignment -name SYSTEMVERILOG_FILE top.sv
set_location_assignment PIN_72 -to in_n[3]
set_location_assignment PIN_73 -to in_n[2]
set_location_assignment PIN_70 -to in_n[1]
set_location_assignment PIN_71 -to in_n[0]
set_location_assignment PIN_56 -to out_n[7]
set_location_assignment PIN_57 -to out_n[6]
set_location_assignment PIN_54 -to out_n[5]
set_location_assignment PIN_55 -to out_n[4]
set_location_assignment PIN_52 -to out_n[3]
set_location_assignment PIN_53 -to out_n[2]
set_location_assignment PIN_50 -to out_n[1]
set_location_assignment PIN_51 -to out_n[0]
Второй файл, top.sdc, задает тактовые сигналы и говорит тулу для синтеза, что задержки на сигналах между внешним миром и D-триггерами анализировать не нужно. В какой-то момент обучения, например когда школьник захочет умножать или делить большие числа и обнаружит, что плата глючит, можно будет объяснить значение строчки в этом файле, которая говорит, что комбинационная логика внутри схемы обязана устаканиваться максимум за 20 наносекунд (1 / 50 MHz) иначе логику нужно разносить в несколько тактов:
Файл top.sdc выглядит так:
create_clock -period "50.0 MHz" [get_ports clk]
derive_clock_uncertainty
set_false_path -from [get_ports rst_n] -to [all_clocks]
set_false_path -from [get_ports {key[*]}] -to [all_clocks]
set_false_path -from * -to [get_ports {led[*]}]
Главный файл проекта, top.qpf, может оставаться пустым - Quartus хранит в нем всякий мусор типа даты и своей версии. Все реальные установки Quartus берет из .qsf и .sdc.
Разнообразные тьюториалы от Altera и Intel показывают, как связывать порты и ножки в GUI мышкой, но я так никогда не делаю - сначала вы можете просто использовать файлы выше, а когда вам понадобиться их менять, вы можете просто поменять текст, например добавить еще одну ножку. Все ножки перечислены в fpga-soldering-camp/boards/epm240_red/00_template/top.qsf
Часть 12. Установка Quartus под Линукс
Quartus ставится под Linux без особых сюрпризов. Скачать его можно отсюда. После инсталляции, когда вы его запустите и дойдете вот до этого места, нужно нажать "Run":

Я пробовал Quartus под Lubuntu, ALT Linux Образование, Simply Linux, Astra Linux, Ред ОС, ROSA Linux и Green Linux. Он везде работает, но инсталлятор путается в создании иконки на рабочем столе в русских дистрибутивах.
Вы можете создать иконку руками, заведите вот такой файл в "/home/$USER/Рабочий стол" (вместо "panchul" поставьте своего юзера):
[Desktop Entry]
Type=Application
Version=0.9.4
Name=Quartus (Quartus Prime 21.1) Lite Edition
Comment=Quartus (Quartus Prime 21.1)
Icon=/home/panchul/intelFPGA_lite/21.1/quartus/adm/quartusii.png
Exec=/home/panchul/intelFPGA_lite/21.1/quartus/bin/quartus --64bit
Terminal=false
Path=/home/panchul/gitflic/fpga-soldering-camp/boards/epm240_redПеред тем, как вы попытаетесь сконфигурировать плату, вам нужно записать в директорию /etc/udev/rules.d файл с правилами для программатора USB Blaster. Самый простой способ это сделать - это просто кликнуть в скрипт под названием ВЫПОЛНИ_МЕНЯ_ПРИ_РАБОТЕ_ПОД_ЛИНУКСОМ_ПЕРЕД_ПЕРВЫМ_ЗАПУСКОМ_КВАРТУСА.bash и потом ввести пароль. Этот файл находится сразу внутри директории разархивированного пакета fpga-soldering-camp_20230108_gui_oriented.zip. Правда вы должны быть в списке пользователей, которые имеют право сделать sudo. Проконсультируйтесь со знакомым линуксоидом, если вы не в курсе этого вопроса. Потом вы будете работать внутри GUI Quartus и вопросы администрирования Линукса теоретически вас больше не затронут:


Когда войдете в GUI, кликайте не на "File | Open", а на "File | Open Project" - эту ошибку делают все, даже я, после многих лет работы с квартусом. Потом действуйте по какой-нибудь инструкции в интернете, на худой конец попросите помощи в телеграм-канале DigitalDesignSchool или FPGA-Systems.ru или на вебсайте Марсоход. Общая идея - Compile Design, Program Design, нажмите на checkbox, Start. Если не получается Start, нажмите Hardware Setup и кликните на USB Blaster.
Если программатор зависает, повтыкайте-повытыкайте, повходите-повыходите из квартуса, поперезагружайте. В Интеле эту часть продукта пишут не самые аккуратные программисты (самых аккуратных переманили в Гугл неподалеку), но после некоторого массажирования оно работает.
Если вы скачали версию пакета для использования со скриптами, fpga-soldering-camp_20230108_script_oriented.zip, то вы наверное можете разобраться как она работает без меня. Если кратко - вы просто заходите в директорию каждого примера и запускаете скрипт ./03_synthesize_for_fpga.bash . Скрипт создает временную директорию run для всех файлов, которые генерит Quartus, выполняет синтез, размещение, трассировку и конфигурацию ПЛИС. Вы только читаете текстовые отчеты о тайминге и ресурсах и смотрите на работу платы.
Часть 13. Установка Quartus под Windows
Если вы очень не любите Linux и хотите использовать пакет под Windows, вы можете это сделать. К сожалению, у вас может возникнуть проблема с Windows 11, который не любит старые неподписанные драйверы для USB Blaster. Но на Windows 10 все скорее всего будет работать после того как вы обновите драйвер. Драйвер находится прямо в дистрибутиве квартуса:

Вы также можете использовать версию пакета fpga-soldering-camp со скриптами, но тогда вам нужно установить Git для Windows, который включает в себя bash и все необходимые программы. При установке Git под Windows стоит поставить вот такую опцию.

Заключение
В заключение я хочу сказать, что в России есть платы Марсоход, которые полностью подходят для тех же целей, что и красная платка, которую я использовал для этого пакета. Просто красная платка для меня дешевле и мне ее проще заказать.
Информация о том, где купить платы, переходники и т.д. есть в README.md файле в пакете и в репозитории https://gitflic.ru/project/yuri-panchul/fpga-soldering-camp . Если вы хотите помочь в разработке примеров, вы можете завести аккаунт на gitflic.ru , клонировать репозиторию и сообщать мне о вашем прогрессе.