ПЛІС — мої перші кроки

Нещодавно я все-таки зробив свій перший крок до ПЛІС і закликав вас за собою. Моє фанатическое захоплення ПЛІС і ідея про те, що ПЛІС є найкращою платформою для створення будь-яких пристроїв придбала релігійний характер. Моя секта ПЛИСоводов проповідує повна відмова від мікроконтролерів, а особливо екстремістська гілка проповідує відмову не тільки від софт процесорів, але й взагалі від послідовних обчислень!

Як завжди, осягнення істин допомогло рішення реальних задач. У сьогоднішній проповіді я хотів би розповісти про випробування, які випадають на долю молодого ПЛИСовода. Долаючи випробування ми осягаємо істину. Але залишаються питання, на які я не знайшов відповідей. Тому я б дуже хотів, щоб брати-хабровчане — ПЛИСоводы з досвідом, взяли участь в обговоренні, простягнули руку допомоги своїм молодшим побратимам.

Ця стаття для новачків. У ній я опишу типові проблеми, питання, омани, помилки, які можуть з'явитися в самому початку навчання (тому що вони з'явилися у мене). Однак, контекст статті обмежений тим, що розробка ведеться на ПЛІС від Altera в середовищі Quartus на мові Verilog.


Важко жити нічого не роблячи, але ми не боїмося труднощів!

Одна з причин, по якій багато не починають вивчати Verilog ось прямо зараз — це відсутність реальної ПЛІС. Хтось не може замовити, бо дорого, а хтось тому, що не знає, що саме взяти (розглянуто питання вибору попередній статті). Комусь ПЛІС поки ще їде по пошті.

Але в своїх розробках я прийшов до того, що наявність реальної ПЛІС мені потрібно вже на фінальному етапі розробки, коли потрібно протестувати проект «в залізі». Мова про те, що більшу частину часу я проводжу в налагодження свого коду з допомогою симуляторів.

Тому моя порада: відсутність ПЛІС — це не привід сидіти склавши руки. Пишіть і отлаживайте модулі для ПЛІС в симуляторах!

Симулятор для Verilog

Отже, чим розважити себе нудними довгими робочими днями (якщо вони там є)? Звичайно ж освоеним ПЛІС! Але як же затягнути на роботу цілу середовище розробки від Altera, якщо вона важить 3 щомісячних робочих ліміту інтернету? Можна принести на флешці! Але якщо предметом вивчення є Verilog, то можна обмежитися блокнотом, компілятором IcarusVerilog, а результат дивитися в GTK Wave.

Спробувати прямо заразДля початку роботи в середовищі Windows, досить завантажити за посиланням http://bleyer.org/icarus/ файл iverilog-20130827_setup.exe (development snapshot) [11.2 MB]

Установка труднощів не викликає. Тепер трохи забіжимо вперед: створимо папку для проекту і в ній пару файлів з поки що не зрозумілим змістом:

Файл-модуль з кодом для тестування модулів — bench.v
`timescale 1ns / 100 ps

module testbench();

reg clk;

initial
begin
$display("start");

$dumpfile("test.vcd");
$dumpvars(0,testbench);

clk <= 0;
repeat (100) begin
#10;
clk <= 1;
#10;
clk <= 0; 
end

$display("finish");
end

У файлі bench.v описаний тестовий модуль testbench, в ньому створений тестовий джерело сигналу clk (меандр). Інші модулі будуть створюватися в окремих файлах, або логіку можна протестувати спочатку цей модуль, а потім винести в окремий модуль. Потім в модуль testbench будуть додаватися примірники цих модулів, де ми будемо подавати на їх входи тестові сигнали і отримувати з них результати. З модулів ми можемо будувати ієрархію, думаю це зрозуміло всім.

BAT Файл, який скомпилирует і просимулирует головний модуль, додавши інші модулі з поточної папки — makev.bat
iverilog-o test-I./ -y./ bench.v
vvp test
pause

Після запуску цього файлу ми побачимо на екрані текст, заданий в $display (це вивід зневадження), значення сигналів та регістрів схеми будуть перебувати у файлі test.vcd. Клікаємо по файлу і вибираємо програму для перегляду — GTKWave (в моєму випадку D:\iverilog\gtkwave\bin\gtkwave.exe). Ще пару кліків і ми побачимо наш clk.



Практично, кожен свій новий модуль я створюю в блокноті і отлаживаю IcarusVerilog. Наступним етапом після такої налагодження йде перевірка модулів в Quartus. Хоча в Quartus теж є свій симулятор, але я його використовую рідше. Причина в простоті оновлення коду та перегляду результату в IcarusVerilog: зберіг зміни у файлі, запустив BAT, натиснув кнопку «оновити» в GTKWave — все! В ModelSim для цього потрібно трохи більше рухів, але він теж не поганий, особливо на складних структур даних.

Після симуляції настає пора запуску Quartus. Але завантажувати прошивку в ПЛІС поки ще рано. Потрібно переконатися, що божественна обчислювальна машина правильно зрозуміла, яку схему ми хочемо отримати, виклавши свої думки у вигляді Verilog'а.

Різниця між симуляцією і роботою в реальному залозі

Перший час я, подібно сліпого кошеняти, бився головою об одвірки. Здавалося б правильний код, не працює зовсім, або працює не так, як думаєш. Або ось тільки що працював, а тепер раптово перестав!

Допитливий кошеня, починає шукати взаємозв'язок між своїми діями і результатом («голубине забобонами»).

Найбільша драма
Нижче буде список дивацтв, але спочатку найбільша драма, з якою я зіткнувся: не всі конструкції Verilog можуть бути синтезовані в залозі. Це пов'язано з тим, що на Verilog описується не тільки апаратна логіка, яка об'єднується в модулі і працює в залозі. На тому ж Verilog описуються тестові модулі, які об'єднують протестовані модулі, подають на їх входи тестові сигнали і в цілому існують тільки для перевірки на комп'ютері. Зміна значень сигналів у часі задається конструкціями, що містять знак "#" у тексті Verilog. Такий знак означає затримку в часі. У прикладі вище, саме так генерується сигнал CLK. І я грішним ділом думав, що таким же чином всередині цієї ПЛІС можна генерувати, наприклад, послідовність біт для відправки повідомлення по RS232. Адже на вхід ПЛІС поданий сигнал від генератора 50 МГц! Може бути вона якось на нього орієнтується. Як виявилося, я не єдиний, хто сподівався на чудо: 1, 2, 3, 4, 5. Реальність, як завжди, виявляється більш суворою: ПЛІС це набір логіки і тимчасова затримка в ній може з'явитися при використанні лічильника, значення якого збільшується тактами від генератора до заданої величини, або якось інакше (але завжди апаратно).

Список знайдених дивацтв
Дивовижні речі, однак, прочитання книг [1,2] проливає світло на цю бісовщину. Більш того, приходить благодать.

Якщо позначити reg, то не факт, що він буде створений
Як я прийшов до проблеми? Припустимо є один модуль, на вхід якого я повинен подавати значення (за типом параметра). У перспективі, цей параметр повинен буде змінюватися в часі в залежності від якихось зовнішніх подій. Тому значення зберігається в регістрі (reg). Але реалізація прийому зовнішніх подій поки не реалізована, тому я регістр не міняю, а просто ставлю йому початкове значення, яке надалі не змінюється.

//ставлю 8 бітний регістр
reg [7:0] val;

//ініціюю його значенням
initial val <= 8'd0240;

//wire до якого підключимо вихід з модуля
wire [7:0] out_data;

//невідомий модуль, називається bbox
//примірник цього модуля називається bb_01
//будемо вважати, що в модулі є вхідний порт in_data і вихідний out_data
//у вхідний порт подаємо значення з регістра val, а вихід підключаємо до wire - out_data
bbox bb_01(.in_data(val), .out_data(out_data));

Здавалося б, у чому підступ? В імперативних ЯП ми часто задаємо змінні констант і потім ні разу їх не змінюємо і все працює. Що ж ми бачимо в залозі?

По-перше, ми не бачимо регістра. По-друге, на вхід модуля подано 8'hFF замість 8'd0240! І цього вже достатньо для того, щоб схема запрацювала не так, як ми планували. Те, що регістра немає — це нормально. В Verilog можна описувати логіку різними способами, в той же час, синтезатор завжди оптимізує апаратну реалізацію. Навіть якщо написати блок always і в ньому працювати з регістрами, але при цьому вихідне значення завжди буде визначатися вхідними, то застосування регістра тут виявиться зайвим і синтезатор його не поставить. І навпаки, якщо при яких значеннях вхідних даних вихідне значення не змінюється, то тут ніяк не обійтися без регістра-засувки і синтезатор його створить. (Книга 1 стор. 88-89). Що з цього випливає? Якщо ми почнемо міняти значення регістра, наприклад, в залежності від натискання кнопок, то геристр вже буде створений і все буде працювати так, як потрібно. Якщо ж виявиться, що кнопки нічого не змінюють, то синтезатор його знову ж викине і знову все зламається. Що ж робити з константою? Потрібно подати її безпосередньо на вхід модуля:

bbox bb_01(.in_data(8'd0240), .out_data(out_data));

Тепер на вході модуля ми маємо правильне значення:


Залишається загадкою, чому при скороченні регістра, його значення в initial не підставляється на вхід модуля.

Розмірність wire краще ставити самому.
При розробці в середовищі Quartus, допускається не установлювати лінії wire заздалегідь. У цьому випадку вони будуть створені автоматично, але про це буде видано попередження (warning). Проблема полягає в тому, що розрядність wire буде 1-біт, а якщо порти будуть мати розрядність більше 1 біта, то значення не буде передано.

bbox bb_01(.in_data(8'd0240), .out_data(int_data));
other_bbox bb_02(.in_data(int_data), .out_data(out_data));

Попередження
Warning (10236): Verilog HDL Implicit Net warning at test.v(15): created implicit net for "int_data"

Результат:


Як бачимо, один біт підключений, а решта 7 біт виходять не підключені (NC). Щоб такої проблеми не було — потрібно створити wire самостійно. Не дарма компілятор IcarusVerilog видає не warning, а помилку, якщо wire не заданий заздалегідь.

wire [7:0] int_data;
bbox bb_01(.in_data(8'd0240), .out_data(int_data));
other_bbox bb_02(.in_data(int_data), .out_data(out_data));




Комп'ютер не буде лазити по модулям, дивитися, яка розрядність портів. До того ж, розрядність може виявитися різною, а на вхід модуля або з виходу беруться не всі біти, а якісь певні.

не Можна використовувати вихід логічної функції, як тактового сигналу
Іноді у проекті потрібно зменшити тактову частоту, або ввести тимчасову затримку в N тактів. Новачок може застосувати лічильник і додаткову схему визначення досягнення лічильником певного значення (схема порівняння). Однак, якщо безпосередньо використовувати вихід зі схеми порівняння як тактового, то можуть виникнути проблеми. Це пов'язано з тим, що логічній схемі потрібно деякий час для встановлення стабільного значення на виході. Ця затримка зміщує фронт сигналу, що проходить через різні частини логічної схеми щодо тактового, у результаті виходять гонки, метастабильность, асинхронщина. Навіть довелося одного разу почути репліку про це в якості критики ПЛИС: «з ПЛІС постійні проблеми — гонки сигналів».

Якщо прочитати хоча б парочку статей:
Метастабильность тригера і межтактовая синхронізація
Пару слів про конвеєрах в FPGA

то стає ясно, яким чином розробляються пристрої на ПЛІС: вся задача ділиться на апаратні блоки, а дані між ними рухаються по конвеерам, синхронно защелкиваясь в регістрах по тактовому сигналі. Таким чином, знаючи загальну тактову частоту, синтезатор розраховує максимальну частоту роботи всіх комбінаторних схем, визначає, укладається їх швидкість період до такту і робить висновок — буде або не буде працювати схема в ПЛІС. Все це відбувається на етапі синтезу. Якщо схеми вкладаються в параметри, то можна прошивати ПЛІС.

Для повного розуміння, варто прочитати Altera handbook на предмет «clock domains», а так само розібратися з тим, як задавати параметри розрахунку TimeQuest для проекту.

Таким чином, для розробників пристроїв на базі ПЛІС створені всі необхідні методології, і якщо їх дотримуватися, то проблем не буде.

А що, якщо я хочу піти проти системи?
Порядок розробки і поведінку синтезатора схем підводить нас до висновку про те, що ж таке ПЛІС на апаратному рівні. Це синхронні схеми. Тому, серед цілей синтезатора — вкластися у часові інтервали. Для цього він, наприклад, спрощує логічні вирази, викидає з синтезу частини схем, які не використовуються іншими схемами і не прив'язані до фізичних висновків ПЛІС. Асинхронні рішення і аналогові трюки не вітаються, тому що їх робота може бути непередбачуваною і залежати від чого завгодно (напруга, температура, техпроцес, партія, покоління ПЛІС), а тому не дає гарантованого, повторюваного, стерпного результату. А всім же потрібен стабільний результат і загальні підходи до проектування!

Але що ж робити, якщо ви не згодні з думкою синтезатора про те, що потрібно викидати незмінні регістри, скорочувати логічні схеми? Як бути, якщо хочете робити схеми з асинхронною логікою? Потрібна тонка настройка? А може бути ви хочете зібрати схему на основних компонентах ПЛІС? Легко! Спасибі розробникам Altera за таку можливість і докладну документацію!

Як це зробити? Можна спробувати графічний редактор схем. Ви, можливо, чули про те, що Quartus дозволяє малювати схеми? Можна самому вибрати стандартні блоки і з'єднати їх. Але це не рішення! Навіть намальована схема буде оптимізована синтезатором, якщо на це буде можливість.

В результаті ми приходимо до старої істини: якщо нічого не допомагає — прочитайте інструкцію. А саме «Altera Handbook» частина під назвою «Quartus II Synthesis Options».

Почнемо з того, що описуючи архітектуру на Verilog певним чином, можна отримати певний результат. Ось приклади коду для отримання синхронного і асинхронного RS-тригера:

//модуль синхронного RS-тригера
module rs(clk, r, s, q);
input wire clk, r,s;
output reg q;

завжди @(posedge clk) begin
if ® begin
q <= 0;
end else if (s) begin
q <= 1;
end
end

endmodule

В цьому випадку вийде синхронний тригер.


Якщо не брати до уваги тактовий сигнал і перемикатися в залежності від будь-яких змін r і s, то в результаті вийде елемент з асинхронною установной значень — засувка (latch).

//приклад модуль асинхронного RS-тригера
module ModuleTester(clk, r, s, q);
input wire clk, r,s;
output reg q;

завжди @(r або s) begin
if ® begin
q <= 0;
end else if (s) begin
q <= 1;
end
end

endmodule




Але можна піти ще далі і самому створити засувку з примітиву (примітиви доступні так само, як будь-який інший модуль Verilog):

module ModuleTester(clk, r, s, q);
input wire clk, r,s;
output reg q;

DLATCH lt(.q(q), .clrn(~r), .prn(~s));

endmodule


В результаті, весь «обвіс» на вході засувки, який синтезатор вважав за потрібне, зникне і ми отримаємо саме те, що хотіли:



Список існуючих примітивів можна подивитися на сайті Altera.

А тепер невеликий приклад про асинхронність і скорочення. Задумав я, приміром, зробити генератор за тим же принципом, як це було прийнято робити раніше, але тільки на ПЛІС:



Але для збільшення періоду я візьму 4 елемента, але тільки один з них буде з інверсією:

module ModuleTester(q);
output wire q;

wire a,b,c,d;

assign a = b;
assign b = c;
assign c = d;
assign d = ~a;

assign q = a;

endmodule


Але виходить скорочення (1 елемент, замість чотирьох). Що логічно. Але ми задумували лінію затримки.



Але якщо поставити синтезатору умова, що лінії a,b,c,d не скорочувати, то вийде те, що ми задумали. Для підказки синтезатору застосовуються директиви. Один із способів вказівки — це текст в коментарі:

module ModuleTester(q);
output wire q;

wire a,b,c,d /* synthesis keep */; 
// ^^^--- це директива для синтезатора

assign a = b;
assign b = c;
assign c = d;
assign d = ~a;

assign q = a;

endmodule

А ось і результат — ланцюжок з чотирьох елементів:


І це далеко не все! Залишу на радість самостійного вивчення: роботу з case і директиву для реалізації його в якості RAM/ROM або логічною схемою; роботу з вбудованими блоками пам'яті (RAM/ROM); вибір реалізації множення — апаратним помножувачі або логічною схемою.

Висновки

Цитуючи статті, хочу сказати, що «ПЛІС-и / FPGA — не процесори, «програмуючи» ПЛІС (заповнюючи конфігураційну пам'ять ПЛІС-а) ви створюєте електронну схему (хардвер), в той час як при програмуванні процесора (фіксованого хардвера) ви підсовуєте йому ланцюжок написаних в пам'ять послідовних інструкцій програми (софтвер)».

Причому, як би мені спочатку не хотілося сильно не прив'язуватися до конкретної залізяці, але іноді, щоб більш ефективно і економно використовувати ресурси, доводиться працювати на низькому рівні. Часто цього можна уникнути, якщо правильно розробляти синхронні схеми. Однак зовсім забути, що це залізо — не виходить.

Ще хочу сказати, що фанатизму і максималізму з часом поменшало. Спочатку я прагнув всі дії і розрахунки на ПЛІС виконувати за один такт, тому що ПЛІС це дозволяє. Однак, це потрібна далеко не завжди. Обчислювальні ядра софт процесорів мені поки не довелося використовувати, проте застосування state machines для роботи за певним алгоритмом — стало нормою. Обчислення за 1 такт, тимчасові затримки в кілька тактів через застосування конвеєрів — це норма.

Книги, які мені дуже допомогли

1. В. о. Соловйов — Основи мови проектування цифрової апаратури Verilog. 2014
2. Altera: Quartus II Handbook
3. Altera: Advanced Synthesis Cookbook
4. Altera: Designing with Low-Level Primitives

Статті по тематиці ПЛІС, Altera і Verilog

Новини ПЛІС індустрії
Microsoft переходить на процесори власної розробки
Intel збирається випустити серверні процесори Xeon з вбудованою FPGA
Intel планує викупити Altera
РБК:Intel купила виробника чіпів Altera за $16,7 млрд

Теорія
Розробка цифрових пристроїв на базі НВІС програмованої логіки
Коротеньке порівняння VHDL і Verilog на допомогу початківцям знайомство з ПЛІС

Апаратні особливості
Метастабильность тригера і межтактовая синхронізація
Часовий аналіз FPGA або як я освоювала Timequest
Пару слів про конвеєрах в FPGA
Verilog. Обгортки RAM і навіщо це потрібно
Проектування синхронних схем. Швидкий старт з Verilog HDL

Приклади
Робимо таймер або перший проект на ПЛІС
Годинник на ПЛІС із застосуванням Quartus II і трохи Verilog
Як я робив USB пристрій
Світломузика на базі ПЛІС
Програмування ПЛІС. Вивчення явища «брязкіт контактів» і метод позбавлення від нього(VHDL!)
Реалізація на Verilog цифрового БІХ-фільтра
Verilog. Цифровий фільтр на RAM
ПЛІС це просто або АЛУ своїми руками
VGA адаптер на ПЛІС Altera Cyclone III
Дослідження процесора і його функціональна симуляція
NES, реалізація на FPGA
Генерація відео математичної функцією на ПЛІС
Апаратний сортувальник чисел на verilog-е
Простий SDR приймач на ПЛІС
Автономний SDR приймач на ПЛІС
Погляд на 10G Ethernet з боку FPGA розробника
Простий передавач FM діапазону на основі ПЛІС
Робимо тетріс під FPGA
Minesweeper на FPGA
Робимо IBM PC на FPGA

PS

Спасибі всім, хто прочитав до цього місця. Сподіваюся, що з цією статтею принцип роботи і використання ПЛІС стане хоча б трохи ближче і зрозуміліше. А в якості прикладу застосування в реальному проекті, я готую до випуску на цьому тижні ще одну статтю.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.