Category: техника

Category was added automatically. Read all entries about "техника".

QuatCore

16-битный полудуплексный UART

Ну, то есть на линии RS485 ничего не меняется: точно так же идут стартовый бит, 8 бит данных и стоповый бит. Но "внутренний интерфейс" меняется, он заточен под 16-битный процессор и 16-битный "протокольный контроллер МКО" (которому пока что вместо настоящего МКО/Mil-Std 1553 подсовывают UART). На передачу запускается 16 бит за раз, и на приём приходит сразу два байта. А если один байт пришёл, а потом возникла длиннющая пауза, то "возвращаемся в исходное состояние". Таким образом, если штатно отправлять чётное количество байт, то один раз возникшая ошибка не собьёт нам все последующие сообщения.

Один раз это уже делали отдельно для передатчика (раз, два), а затем и приёмника, теперь хотим таким же способом модифицировать своих "сиамских близнецов" - приёмопередатчик для полудуплексной работы.

Collapse )

Эта хреновина синтезируется ровно в 50 ЛЭ (когда тактовая 25 МГц, скорость передачи 921600 бод), и максимально допустимая частота составляет 81,97 МГц - неплохо.

Осталось поглядеть - а оно вообще работает?

Продолжение следует...
QuatCore

CRC и полудуплексный UART - часть 2

В первой части мы чуть доработали приёмопередатчик, чтобы он "дружил" с модулем CRC, а также написали сам этот модуль, проверили всё это на передачу - работает.

Теперь надо посмотреть, как оно будет работать на приём. Задача модуля: "самостоятельно" посчитать CRC от входящего сообщения, затем получить на вход переданный CRC (в конце сообщения) и убедиться, что они совпадают, в противном случае выдать ошибку.

Ещё разок покажем результаты симуляции с прошлого раза, там видна и работа приёмника:
TXwithDataBitEarly.png

Collapse )

Неплохо: работу CRC на приёме проверили, всё хорошо. И совмещённый модуль из CRC и приёмопередатчика тоже нарисовали, аж на 54 ЛЭ, он тоже работает.

Осталось совсем немного по информационному обмену: расширить этот приёмопередатчик UART до 16 бит, а потом соединить с "протокольным контроллером МКО".
QuatCore

О выборе самого подходящего CRC-кода

Каюсь, что в вопросе выбора полинома для CRC я исходил из "моды": взял попросту самый популярный из CRC-16, под названием CCITT, 0x1021. Другие названия (в зависимости от выбора начального значения, инверсии битов на входе и на выходе): AUG-CCITT, GENIBUS, MCRF4XX, RIELLO, TMS37157, CRC-A, KERMIT, X-25 и X-MODEM, и это только то, что знает crccalc.com.

Сейчас решил всё-таки поискать, а в чём же, собственно, разница, и какой было бы лучше всего выбрать мне для поставленной задачи: МКО (Mil-Std 1553) со своими проверками чётности, от 1 до 32 слов данных (каждое слово 16 бит), ошибки предполагаются случайными и довольно редкими (вероятность 10-7).

Бешеную активность в этом направлении (исследование CRC) развил Филипп Купман (https://users.ece.cmu.edu/~koopman/crc/). Информации очень много, она "утрамбована", вроде бы наконец разобрался, что с ней делать.

Основная идея: выбрать такой код, который для твоего размера сообщения даст наибольшую возможную дистанцию Хэмминга, т.е позволит ГАРАНТИРОВАННО обнаружить как можно больше неправильных битов.

Collapse )

В общем, мне повезло: ровно в моём случае этот полином CCITT действительно хорошо подходит. Для более коротких сообщений или для более длинных лучше подошли бы другие. А здесь мы имеем гарантированное обнаружение до 3 ошибок, а также любого их нечётного количества, и вероятность 99,997% обнаружить 4 ошибки.
I like trains

Решение Trolley problem в Грузии и Москве

Одно время, в ожидании, что "вот-вот повсюду будут ездить беспилотные автомобили", очень популярна стала Trolley problem, она же "проблема вагонетки". Едет вагонетка, а на путях 5 человек. Но ты стоишь перед стрелкой, и можешь перевести её, тогда вагонетка переедет на другой путь и задавит лишь 1 человека. Что делать: переводить стрелку или нет? Вроде как, по арифметике, 1 смерть лучше чем 5 смертей. Но если ты "ничего не трогал" - то к тебе и вопросов никаких, а если взял и перевёл - то выходит, сознательно убил того 1 человека, без твоих действий он бы не погиб. И, дескать, пока компьютер не осознает ценности человеческой жизни и всю глубину этой дилеммы - за руль его сажать нельзя!

Но у нас эту проблему давным-давно решили. Сначала в Грузии, согласно анекдоту:

- Вот едешь ты по горной дороге, а её перебегают красивый девушка и некрасивый старый женщина. Кого давить будем?
- Ну, старую женщину, она своё уже отжила...
- Дурак, ТОРМОЗ надо давить, ТОРМОЗ!

И по своему велосипедному опыту, полностью подтверждаю! В любой непонятной ситуации жми на тормоз! Сразу переводишь свою кинетическую энергию в тепло, и ситуация моментально становится не такой опасной. Чего-то там прикидывать, манёвры закладывать, особенно когда речь о неожиданно откуда-то выскочивших пешеходах или собаках - гиблое дело. Они сами будут непредсказуемо передвигаться, и угадать их поведение практически невозможно. А вот тормоз никогда не подводил :)

А потом и в Москве...

Собянин: а я всегда знал, что троллейбусы опасны. Не благодарите!
QuatCore

CRC и полудуплексный UART

Апологеты "модели OSI" скажут, что генерация и проверка CRC (Cyclic Redundancy Codes) - это уже канальный уровень, а не физический, и мешать их между собой не стоит. Дескать, физический уровень - это когда говоришь "передай вот этот байт" - и самому передатчику должно быть пофиг, что это за байт такой, частью чего он является. А всей остальной системе должно быть пофиг, как именно этот байт передаётся - хоть оптикой, хоть медяшкой, хоть по радио.

Но если уж я заранее знаю, что у меня будет на физическом уровне (поначалу, для "обкатки", RS485, позже - МКО, он же ГОСТ Р 52070-2003, он же Mil-Std 1553), и у меня была возможность, исходя из этого, придумать конкретный вид применяемого CRC, то более "тесное" проникновение одного в другое позволяет заметно упростить проект.

Смысл в том, что наиболее простая реализация CRC - когда мы подаём по одному биту за раз, поэтому если уж во время передачи данных они всё равно должны "сериализоваться" - то почему бы этот поток бит и не пустить на CRC. Да и мультиплексировать один бит (поставить ли его из "обычного" сдвигового регистра, или из CRC) получается не так затратно, чем 8-битную шину, а тем более 16-битную.

Сейчас попробуем "прикрутить" к приёмопередатчику, написанному в прошлый раз, генератор CRC, рассмотренный здесь, хотя его тоже придётся несколько причесать.

Для начала раскомментируем выражение isDataBit:
assign isDataBit = (State[3] | State[0])&(~isStopState)&ce;	


И ещё разок смотрим работу передатчика:


Collapse )

Ладно, начало неплохое, при передаче CRC ведёт себя прилично. Воспользовались "недокументированным оператором верилога" &~& и ужаснулись возможностям по обфускации кода, которые он открывает :)

Теперь осталось посмотреть работу CRC на приёме, а потом сделать "схему", работающую и на приём, и на передачу.
QuatCore

Полудуплексный приёмопередатчик UART, 3 года спустя :)

Когда я только взялся за ПЛИС 3 года назад, соорудил передатчик UART на 27 ЛЭ (если делитель частоты на 8 бит), или 28 ЛЭ, если st=1 во время передачи предыдущего байта не должен перезапустить передачу, а просто должен игнорироваться.

Год назад вернулся к этому делу, и, как ни странно, меньше этот модуль не стал, при том же 8-битном делителе частоты получилось 30 ЛЭ, зато выход в кои-то веки стал регистровым, а не комбинаторным, гарантируя, что в линию не пойдёт высокочастотный "мусор" в некоторых местах (а он реально мешал передаче на 921 600 бод, и всё исправилось, когда выход стал напрямую с регистра). И в целом схема стала чрезвычайно "скоростной", даже на нашей медленной ПЛИС 5576ХС4Т и максимальном делении частоты с 80 МГц до 300 бод, предельная частота указывается в 96,15 МГц. (чем толще делитель частоты - тем ниже становится его предельная частота, особенно, если использовать компаратор для счёта "не до конца", и не защёлкивать его выход в регистр, прежде чем сбросить). Ну и нехорошая багофича, когда при первом же включении этот модуль начинает передавать, правда, сплошные единицы, была исправлена. В принципе, можно попытаться пару ЛЭ отыграть назад, если тактовая частота невелика, а потому делать схему "скоростной" не требуется, но есть риск, что в крупных проектах это усложнит жизнь фиттеру. А так он этот несчастный UART может "по остаточному принципу" впихнуть куда угодно, "размазать тонким слоем" по всему кристаллу :)

Похожая история с приёмником UART на 33 ЛЭ (3 года назад), и столько же (при делителе в 8 бит) занимает куда более новый приёмник UART для QuatCore.

Но тогда, 3 года назад, я ещё одного монстра сделал, полудуплексный приёмопередатчик, это "сиамские близнецы" из приёмника и передатчика, использующие общий делитель частоты, сдвиговый регистр и конечный автомат, что оправданно, если одновременный приём и передача невозможны. А именно так и есть на RS485! За счёт этого "совместного использования" ресурсов получилось сделать его размер 46 ЛЭ (при 8-битном делителе), что несколько меньше, чем 60 ЛЭ, которые получались при двух отдельных модулях.

Впрочем, мне этот модуль много крови попил, и я к нему не возращался, ДО СЕГОДНЯШНЕГО ДНЯ.

А сейчас стало интересно ещё разок попробовать его сделать, причём с "заделом" под CRC, и посмотреть, что из этого получится...

Collapse )

Неплохое начало: побили свой собственный рекорд в 46 ЛЭ (при 8-битном делителе), теперь всё то же самое умещается в 39 ЛЭ, имеет предельную частоту 100 МГц, регистровый выход (без "комбинаторных" помех). А когда тактовая частота 25 МГц и скорость передачи 921 600 бод, и вовсе 36 ЛЭ. А убрать выходы FrameError и LineBreak - будет 32 ЛЭ (!)

Теперь попробовать подсоединить CRC, и достроить с 8 до 16 бит. Но это уже в понедельник.
QuatCore

"МКО через UART", часть 8 - CRC

Наличие контрольной суммы CRC (Cyclic Redundancy Code) также не является частью ГОСТ 52070-2003, это дополнительное требование конкретно в нашем протоколе информационного обмена.

На самом деле, можно было и какую-нибудь другую контрольную сумму впихнуть, но мне захотелось CRC, именно исходя из лёгкости его реализации на ПЛИС. Как ни странно, при аппаратной реализации он куда приятнее, чем какая-нибудь "сумма слов по модулю, близкому к 65536" (Fletcher, Adler), или "сумма слов с битом переноса, прибавляемым к младшему разряду" (контрольная сумма заголовка IPv4), и даже самой простой 16-битной контрольной сумме (когда все слова складываются, и берутся только 16 бит результата) CRC даст фору, оказываясь вдвое компактнее!

Впрочем, эти преимущества ещё надо суметь реализовать, для чего генерацию и проверку CRC засунуть в непосредственной близости от приёмопередатчика, где биты будут идти один за другим, притом в правильном порядке...

Для протокола я нарисовал такую хреновину:


Collapse )

Продолжение следует... Вообще, мне очень хочется сделать совмещённый модуль на приём и передачу, специально для RS485. Когда-то давно я такое делал, но маленьким был, надо попробовать ещё разок, и теперь на 16 бит и с "заделом" под CRC.
QuatCore

"МКО через UART", часть 7 1/2 - проверка заголовков ПОПРОЩЕ

Что-то я не доволен тем, что получилось в прошлый раз. С одной стороны, работает, и есть определённая "гордость" в том, что мы на ходу, весьма малой кровью перевели 5-битный подадрес в 16-битный код Рида-Мюллера. С другой - радость омрачил квартус, выдав странный баг. Потом он ушёл, но "осадочек остался".
И ещё одна возможная проблема: в той логике сопоставления заголовков массивов подадресам содержался изъян в лице сообщения "СЫРЫЕ ДАННЫЕ ДЛЯ СТЕРЕОРЕЖИМА", которые один прибор передаёт другому. Поскольку разные подадреса на приём и на передачу, то и заголовки получались разными, а надо было выбрать какой-то один. И я, не сильно задумываясь, вписал тот, что соответствует подадресу при передаче. И тогда такая "жёсткая" логика его бы забраковала, проверяя подадрес приёма. Вообще, не поздно это дело поменять, там вообще в протоколе было обозначено, что сообщение содержит "наши служебные данные", которые мы вправе поменять, но обязательно поставим всех в известность.
Ну и в целом у меня осталось впечатление, что можно было сделать гораздо проще, если свою гордость пока что отодвинуть и просто свериться с содержимым оперативной памяти.

Ведь у нас всё содержимое памяти автоматически инициализируется нужными нам значениями при включении ПЛИС, почему бы этим не воспользоваться! В тех "сегментах", что мы отвели на ПРИЁМ, самым первым значением положим ПРАВИЛЬНЫЙ заголовок соответствующего массива.

И тогда нужно заставить наш протокольный контроллер запросить это значение из памяти, сравнить его с первым полученным словом данных, причём ни в коем случае не перезаписывать это значение, отключить MemWrReq. И тогда золотой ключик у нас в кармане...

Collapse )

Любопытно! На этапе синтеза мы действительно сэкономили аж 4 ЛЭ, но потом приходит фиттер и впихивает лишних 16 ЛЭ, делая эту реализацию ещё толще, чем была! Конечно, фиттер вещь непредсказуемая, сегодня впихал, а завтра, в общей схеме (с процессором, DMA, видеопроцессором и пр.) - обойдётся, но здесь я могу его понять, схема стала более связной, чем была. Раньше приёмник и передатчик почти что жили своей жизнью, можно было их разнести по разные стороны, теперь же между ними вставился 16-битный компаратор, а эти ПЛИС, 5576ХС4Т (функциональный аналог Flex10k) имеют недостаточно мощные интерконнекторы, толстые шины ему тяжело даются.

Так что придётся оставить два варианта, а там уж выбрать по обстоятельствам. Зато буриданов осёл во мне доволен: рассмотрели оба варианта и всё съели!

На очереди по-прежнему генерация и проверка CRC. Ох, подлянка меня ждёт!
QuatCore

"МКО через UART", часть 7, проверка заголовков массивов

В части 5 мы выполнили проверку командного слова, на соответствие полей "подадрес" и "приём/передача" - далеко не все их комбинации разрешены, и если пришло что-то не то, выставляем признак "ошибка в сообщении", слова данных не посылаем, а принимаемые слова данных никуда не записываем. На самом деле ещё зачастую проверяют, чтобы количество слов данных на приём/передачу соответствовало заранее оговоренному для каждого подадреса. Но мы пока что прописали в протоколе, что запрашивать можно любое количество. Знаешь, что на дальней дистанции с хорошей точностью только "активные" углы и дальность - запрашиваешь поменьше слов, только с ними. Подошли поближе и "появился" кватернион взаимной ориентации - запрашиваешь ещё на 4 слова больше. А если решили-таки выполнить фильтр Калмана по всей науке и нужна ещё ковариационная матрица шума измерений (см. прокрустово ложе 16 бит) - запрашиваешь ВСЕ СКОЛЬКО ЕСТЬ! В микросхеме 1895ВА2Т можно для каждого подадреса, отдельно на приём и на передачу, задать все возможные количества слов, которые допустимо передавать, ещё и отдельно на групповые сообщения и отдельно на "индивидуальные", хотя ГОСТ просит интерпретировать их одинаково.

Далее, если мы принимаем информацию (полётное задание, конфигурация мишени и пр.), надо проверить первое слово данных. Это уже не ГОСТ 52070-2003, а конкретно наш "протокол информационного обмена", где представители РКК Энергия решили ещё подстраховаться и предварять каждый массив данных "заголовком", уникальным для каждого подадреса.

Потом уже я, чтобы выпендриться, ввёл здесь коды Рида-Мюллера, позволяющие выбрать 32 различных 16-битных слова (каждое - на свой подадрес) таким образом, что они будут отличаться друг от друга МИНИМУМ на 8 бит!

Collapse )

Что ж, проверка работает. Квартус подложил очередную свинью, точнее, Шрёдинбага (или это Гейзенбаг?), не знаю, как именно, но сейчас этой проблемы нет.

На самом деле, я думал и о более простом методе проверки заголовков, где мы не пытаемся самостоятельно генерировать коды Рида-Мюллера, а просто сверяться с ячейкой памяти. Может, если будет охота, опробую и его.

А тем временем протокол информационного обмена практически реализован. Остаётся проверка и генерация CRC, и, может быть, автоматическая (без участия процессора) выдача дампа памяти и изображения...

"МКО через UART", часть 6, синхронизация (с СД)

Пора заняться командами управления (КУ). "Для общего образования" выпишем их все, чуть обсудим - и потом выполним ровно ту, которая нужна в моём приборчике.

Collapse )

Принцип, как обрабатывать команды управления, надеюсь, понятен. Через некоторое время ещё реализуем команду "Установить ОУ в исходное состояние". Но прежде хочу разобраться с заголовками массивов и CRC.