субота, 15 серпня 2020 р.

Реалізація прийому в синхронному та асинхронному режимі на FPGA

У другій частині нашого циклу [1...3] ми навчили ПЛІС роботі з UART інтерфейсом і здавалося б на цьому можна було закрити питання організації зв'язку між нижнім та верхнім рівнями. Однак сам UART по суті надмірний, та й не завжди є необхідність (або можливість) використовувати драйвери інтерфейсів UART TTL/RS-232/RS-485. Наприклад, є менш «жорсткий» LVDS інтерфейс, який не менш схиблений, бо заснований на використанні диференціальної лінії передачі. Сучасні драйвери LVDS випускаються промисловістю як застосування на невеликі відстані (десятки сантиметрів), і на відстані до кількох сотень метрів. Адже нам ніщо не заважає підключити на вихід ПЛІС LVDS** [4] передавач, наприклад SN65LVDS31 [5], а на приймальній стороні LVDS приймач SN65LVDS32 [6] і працювати зі звичними TTL рівнями відразу по декількох каналах? Звісно ні...


* Диференціальний метод передачі використовується в LVDS, оскільки має меншу чутливість до загальних перешкод, ніж проста однопровідна схема. Застосування джерел сигналу з диференціальним струмовим виходом і приймачів з низькоомним диференціальним входом забезпечує мінімальні індуктивні наведення, оскільки інформація передається у формі струму, а ємнісне наведення мало, так як при хорошій симетрії лінії передачі вона є синфазною і пригнічується вхідним диференціальним приймачем. Додатковим захистом лінії є екранування.

Оскільки диференціальні технології, зокрема і LVDS, менш чутливі до шумів, то можливе використання менших перепадів напруги, до 350 мВ. що дозволяє порівняно з іншими способами передачі сигналів значно знизити споживану потужність. Наприклад, статична потужність, що розсіюється на навантажувальному резистори LVDS, становить всього 1.2 мВт, в порівнянні з 90 мВт, що розсіюються на навантажувальному резисторі інтерфейсу RS-422.

** Слід зазначити, що сучасні ПЛІС сімейства SPARTAN вже мають конфігуровані I/O в LVDS на борту.

Перш за все, що ми можемо спростити при формуванні пакетів даних на стороні, що передає, для спрощення прийому? Наприклад, позбутися розподілу на кадри (кадри) і передавати одну довгу послідовність (кодограму), стан IDLE прийняти за нульовий рівень. Для ідентифікації початку кодограми залишити старт-біт (St) високого рівня та біт нульового рівня (Sp). Довжину кодограми зробити динамічною. Безпосередньо формат модифікованої кодограми представлений на малюнку:


При цьому, склад кодограми включає:

  • St, Sp - стартова послідовність з двох бітів з рівнями логічної одиниці та нуля.
  • 0...N - динамічне поле даних.

Кодограма завжди починається і закінчується станом IDLE нульового рівня, тривалість якого визначає тайм-аут між посилками пакетів даних.

ПЗ та обладнання, що використовується

Для організації роботи нам знадобиться таке обладнання та програмне забезпечення:

  • Стендова макетна плата з ПЛІС із другого циклу [2].
  • 3-х вольтове джерело живлення потужністю від п'яти ват.
  • ПК із встановленою інструментальною системою проектування логічних матриць Xilinx  ISE Webpack або Xilinx ISE Design Suite 14 (або вище) [7].
  • Програматор JTAG, наприклад Xilinx JTAG Download Parallel Cable або Xilinx Platform Cable USB, підключений до JTAG-роз'єм програмування [8].
  • Осцилограф (будь-який для контролю та тестування проекту).

Створення проекту, прошивка

Запустивши САПР Xilinx, створимо новий проект та виберемо відповідну модель матриці. Після цього можемо увійти в схемотехнічний редактор, натиснувши третю кнопку на вкладці Design Entry менеджера проектів Project Manager і приступити до моделювання (див. малюнок).


Після закінчення моделювання перевіряємо та збираємо проект натискання кнопки «Implementation» у вікні Project Manager (див. малюнок).

Після збiрки проекту середа створить файл прошивки формату JED з сигнатурою матриці XC95288XL7-TQ144, який і потрібно буде прошити в CPLD (див. малюнок).


Реалізація прийому в синхронному та асинхронному режимах

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


Фізика роботи зсувного регістру не потребує додаткового пояснення та розглянута нами у матеріалі [9]. Відзначимо лише, що для роботи даного методу потрібна додаткова лінія тактування, що можна вважати недоліком при фізичному обмеженні кількості ліній. Ось тут і на перший план і висувається асинхронний режим прийому.

Для асинхронного режиму важливі такі фактори:

  1. Знання швидкості передачі даних, причому вона не повинна змінюватися (тобто бути постійною, згадайте, як важлива для UART правильна установка швидкості прийому, про це трохи далі).
  2. Наявність стартової та при необхідності стопової послідовності.

Крок 1. Засічка на кожному биті даних

Отже, як нам ідентифікувати дані без наявності додаткової лінії тактування, тобто. тоді коли ми не знаємо моменту надходження даних? Звичайно, можна було б просто рахувати перепади рівнів у вхідній послідовності, але СТОП! Хто сказав, що це не буде перепаду від перешкоди в лінії? Ось тут і знадобиться знання тривалості чи частоти передачі, тобто. тривалості одного біта.

Для наочності обмежимося довжиною прийнятої кодограми 8 розрядів і розглянемо її докладніше:


Насамперед, виходитимемо з того, що нам відомі:

  1. Тривалості розрядів у кодограмі вони постійні.
  2. Послідовність завжди починається стартовими бітами одиничного і нульового рівня, після чого йде поле даних з довільними рівнями.
  3. Поле даних відомої (заданої) довжини.

Тепер уявімо, що імпульсом запуску (стартом) для початку декодування буде одиничний рівень. А ідентифікацію рівнів здійснюватимемо, скажімо, десь посередині кожного розряду кодограми, тобто. відступати заданий інтервал від старту та робити засічку із збереженням логічного рівня. Наприкінці ж «передбачуваної послідовності» аналізувати стартові біти на наявність одиниці в нульовому биті та нуля в першому біті. Реалізація такого підходу представлена в наступному варіанті:


Робота схеми здійснюється наступним чином: по приходу одиничного рівня зі входу даних замикається RS-тригер, що дозволяє роботу лічильника тактової послідовності з тривалістю кожного розряду 54.25 нс (ті самі 18 МГц). Цих тактів на кожному розряді тривалістю 813.75 нс вміщується рівно 15. Таким чином, при тривалості кодограми в 8 біт, кількість тактів складе 15 * 8 = 120. Це дає можливість зупинити роботу лічильника по закінченні кодограми шляхом формування сигналу скидання RS-тригера по досягненні. Що буде заданим інтервалом для здійснення засічки для кожного розряду? Так, та кількість тактових імпульсів, тобто. 10-й, 25-й, 40-й, 55-й, 70-й, 85-й, 100-й та 115-й. Ці засічки здійснюють дешифратори станів лічильника та D-тригери (тригери засічок) на кожен розряд. Вихідні стани тригерів записуються у вихідний паралельний буфер синхронно за сигналом дешифрації стартової послідовності та закінчення рахунку лічильника, з цього ж сигналу здійснюється наступне скидання станів тригерів засічок.

Цей варіант має дві істотні недоліки:
  1. Засічка «посередині» кожного розряду не дає гарантії відсутності перешкоди в цей момент часу.
  2. Немає легкої масштабованості схеми дешифрації засічок (прийде городити на кожен розряд окрему схему дешифрації і ставити по тригеру).
Для вирішення першої проблеми плавно переходимо до другого кроку.

Крок 2. Декілька засічок на кожному биті даних «плаваючим вікном»

Ще в другій частині нашого циклу при розборі прийому UART кадру в VHDL реалізації ми прийняли як основу для фільтрації коротких за тривалістю перешкод у прийнятих даних - аналіз кожного біта протягом усього його інтервалу існування. Надалі ми логічно прийняли, що на основі буфера станів «біта-реципієнта» шляхом вибірки більшої кількості станів, що незмінилися, можна виділити біт з «правильним» рівнем для вихідного буфера. Ось і реалізуємо цю фішку. Погляньте ще раз на кодограму. У кожному розряді міститься 15 біт, нам необхідно робити кілька засічок на кожен розряд. Причому, бажано прив'язуватися до довжини кодограммы, тобто. реалізувати свого роду «плаваюче вікно» за вхідною послідовністю. Найбільш оптимально розбити аналіз кожного розряду по 5 інтервалів, причому кожен інтервал буде три такти нашого генератора з періодом T = 54.25 нс. А кожен 5-й інтервал є закінченням попереднього і початок наступного розрядів, тобто. перепад. Таким чином аналізувати нам слід лише 4 крапки з 5-ти засічок. Кожен третій такт нашого генератора від імпульсу запуску буде інтервальним і нам залишається тільки підраховувати кожен п'ятий інтервальний імпульс для того, щоб дізнатися, в який час слід починати аналізувати наступний розряд і так далі до нескінченності.

Ви запитаєте, як нам на основі даних про отримані рівні в чотирьох точках вибрати одне єдине рішення, що задовольняє більшості станів? Так, дуже просто. Логічна функція, що виконує подібну вибірку, так і називається – функцією більшості або функцією голосування. Так, так, відразу згадується мажоритна система виборів:). Елемент, що реалізує цю функцію і називається – мажоритарним**.
** Мажоритарний елемент (перемикач по більшості) – логічний елемент із класу порогових, з парним чи непарним числом входів та одним вихідним сигналом, значення якого збігається зі значенням на більшості входів. При парному числі входів більшістю вважається n/2+1 входів.

Таким чином, логічна функція працює за «принципом більшості», якщо на більшості входів буде сигнал логічної одиниці, то на виході схеми встановиться сигнал логічної одиниці, і навпаки, якщо на більшості входів буде сигнал логічного нуля, то і на виході встановиться логічний нуль. Реалізація функції для вхідних сигналів включає всі незбігаючі комбінації за схемою «І», виходи яких збираються за «OR» (див. таблицю).

Таблиця. Можливі комбінації для чотирьох входів мажоритарної функції


Реалізація мажоритарної логіки для чотирьох входів представлена нижче. Вона включає комбінацію з шести помножувачів по «І» і одного суматора по «OR».


Загальна схема запропонованого підходу з «плаваючим вікном» на 5 точок із чотирма засічками для мажоритарної ЛФ та без масштабування кодограми представлена на малюнку. Асинхронний прийом «Плаваюче вікно» на 5 точок з мажоритарною ЛФ та без масштабування кодограми:


Робота даного варіанту схеми повторює попередній з тією відмінністю, що масив засічок ми можемо робити необмежену кількість разів: на початку кодограми ми дозволяємо роботу лічильника на три такти, кожен вихідний імпульс даного лічильника є інтервальним для роботи наступного інтервального лічильника на 5. Вихідні стани кожні три такти на накопичувальний буфер зі схем дешифрації та чотирьох асинхронних D-тригерів. Вихідні сигнали цих чотирьох тригерів є вхідними для мажоритарної логіки (вагової функції) та вибору більшості станів входу протягом інтервалу існування кожного розряду. Далі весь процес повторюється. Скидання станів тригерів накопичувального буфера здійснюється сигналом 5 імпульсу інтервального лічильника, що є ознакою закінчення одного розряду кодограми. Таким чином, робота схеми «плаваючого вікна» здійснюватиметься доти, доки стоїть сигнал дозволу роботи лічильника тактів на три.

Крок 3. Декілька засічок на кожному биті даних «плаваючим вікном» та масштабування кодограми

Настала черга додавання масштабованості по довжині кодограми. Адже й справді, городити за схемою дешифрації та тригера на кожен «правильний» біт по виходу мажоритарної ЛФ – марнотратство. А лічильник для роботи цих схем дешифрації він там потрібен? Ні, і ось чому. Можливо ви не звернули увагу, але після другого кроку ми маємо всі передумови синхронної схеми прийому даних, розглянутої вище на малюнку. Вай, але звідки раптом взялися такти, з якими надходять розряди кодограми? Адже лінія, як і раніше, асинхронна. Правильно, лише дивіться – 5-й такт інтервального таймера не що інше, як ознакою закінчення надходження кожного розряду (не забуваємо, що ми чітка прив'язка до тривалості), тобто. синхронно з цим імпульсом до нас надходить рішення з виходу вагової функції. Ось вони наші такти. Таким чином, вихід вагової функції мажоритарного ЛФ достатньо підключити на вхід зсувного регістру, що тактується 5-м імпульсом інтервального таймера і на виході ми маємо паралельний код. Зверніть увагу, ні лічильника, ні схем дешифрації для засічок вже немає, все накопичення та подальше зсув даних здійснює регістр. А де ж легкість масштабування? Так ось, для формування приймального буфера більшої довжини достатньо поставити стільки зсувних регістрів, скільки потрібно, лише об'єднавши їх тактові входи, а входи наступних регістрів підключити на попередніх виходи. Початок кодограми детектувати за двома останніми бітами у старших розрядах регістрів, втім як і раніше. Ось і все. 

Асинхронний прийом. «Плаваюче вікно» на 5 точок з мажоритарною ЛФ та масштабуванням кодограми:



Загальні рекомендації щодо реалізації алгоритму:
  1. Усі лічильники та тригери асинхронні.
  2. При обміні даними динамічної довжини допустимо встановити тривалість таймууту між пакетами даних до одного біта, але з обов'язковою ознакою закінчення кодограми.
Ресурси
  1. Є. Бадло, С. Бадло. ПЛІС. Частина 1 або... Видалений прошивальник по мережі TCP-IP. - Радиолюбитель, Мінськ, 2013, №12, с.34
  2. Є. Бадло, С. Бадло. ПЛІС. Частина 2... Реалізація псевдо-UART. - Радиолюбитель, Мінськ, 2014, №2, с.45
  3. Є. Бадло, С. Бадло. ПЛІС. Частина 3... Цифрова фільтрація. Згладжування та боротьба з імпульсними перешкодами. - Радиолюбитель, Мінськ, 2014, №3, с.23
  4. DATA-SHEET. XAPP230 The LVDS I/O Standard v1.1 (11/99) http://www.xilinx.com/xapp/xapp230.pdf
  5. DATA-SHEET. LVDS драйвер передавача http://www.ti.com/lit/ds/symlink/sn65lvds31.pdf
  6. DATA-SHEET. LVDS драйвер приймача http://www.ti.com/lit/ds/symlink/sn65lvds32.pdf
  7. С. Бадло. JTAG.Xilinx програматор. - Радиолюбитель, Мінськ, 2008, № 7, с.38
  8. Є. Бадло, С. Бадло. Перетворювач інтерфейсів USB-RS-232 у задачах малої автоматизації. Частина 3... Розширюємо порт. - Радиолюбитель, Мінськ, 2014, №1, с.48