пятница, 5 сентября 2014 г.

Реализация приема в синхронном и асинхронном режиме на ПЛИС

Во второй части нашего цикла [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.
** Cледует отметить, что современные ПЛИС семейства SPARTAN уже имеют конфигурируемые I/O в LVDS на борту.
Прежде всего, что мы можем упростить при формировании пакетов данных на передающей стороне для упрощения приема? К примеру, избавиться от деления на фреймы (кадры) и передавать одну длинную последовательность (кодограмму), состояние IDLE принять за нулевой уровень. Для идентификации начала кодограммы оставить старт-бит (St) высокого уровня и бит нулевого уровня (Sp). Длину кодограммы сделать динамической. Непосредственно формат модифицированной кодограммы представлен на рисунке:



Рис. Формат упрощенной кодограммы

При этом, состав кодограммы включает в себя:
  1. St, Sp – стартовая последовательность из двух битов с уровнями логической единицы и нуля.
  2. 0...N – динамическое поле данных.
  3. Кодограмма всегда начинается и заканчивается состоянием IDLE нулевого уровня, длительность которого определяет таймаут между посылками пакетов данных.
Используемое ПО и оборудование

Для организации работы нам понадобится следующее оборудование и программное обеспечение:
  1. Стендовая макетная плата c ПЛИС из второго цикла [2].
  2. 3-х вольтовый источник питания мощностью от пяти ватт.
  3. ПК с установленной инструментальной системой проектирования логических матриц Xilinx Foundation Series 3.1i/4.1i, ISE Webpack или Xilinx ISE Design Suite 14 (или выше) [7].
  4. Программатор JTAG, к примеру Xilinx JTAG Download Parallel Cable или Xilinx Platform Cable USB, подключенный к JTAG- разъему программирования [8].
  5. Осциллограф (любой для контроля и тестирования проекта).
Создание проекта, сборка и прошивка ПЛИС

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


Рис. Создание проекта в среде Xilinx

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


Рис. Сборка проекта (имплементация) в среде Xilinx

После сборки проекта среда создаст файл прошивки формата 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- триггера по достижении счетчиком состояния счета в 120 импульсов. Что будет являться заданным интервалом для осуществления засечки для каждого разряда? Да, то самое количество тактовых импульсов, т.е. 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 входов.
Таким образом, логическая функция работает по «принципу большинства», если на большинстве входов будет сигнал логической единицы, то на выходе схемы установится сигнал логической единицы, и наоборот, если на большинстве входов будет сигнал логического нуля, то и на выходе установитсялогический ноль. Реализация функции для входных сигналов включает в себя все несовпадающие комбинации по схеме «И», выходы которых собираются по «ИЛИ» (см. таблицу).

Таблица. Возможные комбинации для четырех входов мажоритарной функции

Реализация мажоритарной логики для четырех входов представлена на рисунке ниже. Она включает в себя комбинацию из шести умножителей по «И» и одного сумматора по «ИЛИ».

Рис. Реализация мажоритарной логики для четырех входов

Общая схема предложенного подхода с «плавающим окном» на 5 точек с четырьмя засечками для мажоритарной ЛФ  и без масштабирования кодограммы представлена на рисунке.

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

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

Шаг 3. Несколько засечек на каждом бите данных «плавающим окном» и масштабирование кодограммы

Настал черед добавления масштабируемости по длине кодограммы. Ведь и правда, городить по схеме дешифрации и триггеру на каждый «правильный» бит по выходу мажоритарной ЛФ – расточительство. А счетчик для работы этих схем дешифрации, он там нужен? Нет, и вот почему. Возможно вы не обратили внимание, но после второго шага мы по сути имеем все предпосылки синхронной схемы приема данных, рассмотреной выше на рисунке. Вай, но откуда вдруг взялись такты, синхронно с которыми поступают разряды кодограммы? Ведь линия по-прежнему асинхронная. Верно, только смотрите – 5-й такт интервального таймера является не чем иным, как признаком окончания поступления каждого разряда (не забываем, что у нас четкая привязка к длительности), т.е. синхронно с этим импульсом к нам поступает решение с выхода весовой функции. Вот они, наши такты. Таким образом, выход весовой функции мажоритарного ЛФ достаточно подключить на вход сдвигового регистра, тактируемого 5-м импульсом интервального таймера и на выходе мы сразу имеем параллельный код. Реализация подобного подхода представлена на рисунке ниже.

Обратите внимание, ни счетчика, ни схем дешифрации для засечек уже нет, все накопление и последующий сдвиг данных осуществляет регистр. А где же легкость масштабирования? Да вот же, для формирования приемного буфера большей длины достаточно поставить столько сдвиговых регистров, сколько потребуется, всего лишь объединив их тактовые входы, а входы последующих регистров подключить на выходы предыдущих. Начало кодограммы детектировать по двум последним битам в старших разрядах регистров, впрочем как и ранее. Вот и все.



Рис. Асинхронный прием. «Плавающее окно» на 5 точек с мажоритарной ЛФ и
масштабированием кодограммы

Общие рекомендации при реализации алгоритма
  1. Все счетчики и триггеры асинхронные.
  2. При обмене данными динамической длины допустимо установить длительность таймаута между пакетами данных вплоть до одного бита, но с обязательным признаком окончания кодограммы.
Лицензионное соглашение :)

Автор не несет никакой ответственности за возможную порчу оборудования или информации в результате неправомочного использования данного проекта или за "ваши кривые руки". Также он не дает никаких гарантий, явных или подразумеваемых, относительно корректности результатов и не несет ответственности за прямые или косвенные убытки, связанные с его использованием.

Послесловие

Видеотестирование проекта формирователя кодограммы вы можете посмотреть на нашем канале LaboratoryW на YouTube:


Спецификации и схемотехнические реализации рассмотренных модулей передатчика и приемника кодограммы в различных режимах в среде САПР Xilinx Foundation Series 4.1i (файл plis4_res.zip) вы можете загрузить с сайта нашего журнала http://radioliga.com (раздел «Программы»), а также с сайта разработчика [10]. Если тема представляет для вас интерес – пишите, задавайте вопросы.

Ресурсы
  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. 6. DATA-SHEET. LVDS драйвер приемника http://www.ti.com/lit/ds/symlink/sn65lvds32.pdf
  7. Xilinx download http://www.xilinx.com/support/download.html#download.html?&_suid=138996081380407635947911615178
  8. С. Бадло. JTAG.Xilinx программатор. – Радиолюбитель, Минск, 2008, №7, с.38
  9. Е. Бадло, С. Бадло. Преобразователь интерфейсов USB-RS-232 в задачах малой автоматизации. Часть 3 или... Расширяем порт. – Радиолюбитель, Минск, 2014, №1, с.48
  10. Ресурсы к проекту

Комментариев нет:

Отправить комментарий

В комментариях уважайте собеседника, внимательно читайте посты и не додумывайте. Просьбы и предложения из разряда: «можно ваш Skype/Viber/телефон», «напишите мне в vk/FB», а также другие им подобные — игнорируются. Выход новых версий ПО, внешняя ссылка, переставшая работать с течением времени и т.п. не является основанием для претензий. Желающие спокойно подискутировать и высказаться — Welcome. Желающие спонсировать блог — Donate. Нарушение этих простых правил ведет к бану и удалению комментариев без предупреждения.