Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная.

Приветствую, уважаемые посетители сайта www.pikabu.ru. Продолжаю статью о том, как написать приёмник UART на ПЛИС. Напоминаю, что в прошлом посте я постарался вас познакомить с самыми основами этого протокола, и попытался максимально подробно описать алгоритм работы приёмника, который мы будет создавать в ПЛИС.

http://pikabu.ru/story/prostenkie_primeryi_na_plis_uart_chas...

В данном посте я покажу, как всё, что я рассказывал в прошлом посте, описать на языке VHDL, протестировать и разместить в ПЛИС. Поскольку ответа на мой вопрос о том, в каком виде вы хотели бы видеть, выкладываемый код, от вас не поступило – то я буду код выкладывать в виде изображений, как и планировал изначально. Других вариантов я не вижу. Нужны исходники – пишите. Мне лень заморачиваться с файловыми хранилищами.

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

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


Внимание! Достаточно большое количество разработчиков на FPGA предпочитают язык Verilog/SystemVerilog. Я же предпочитаю язык VHDL, на котором буду выкладывать все тексты схем. Поскольку, я не ставлю своей целью научить вас писать именно на VHDL, поэтому я не буду объяснять, почему у меня написано именно так, а не иначе. Если вы все же начнете изучать язык VHDL, то поймете тесты схем. Если же не поймете, то всегда можете задать вопрос мне, я всегда объясню. А начнете изучать Verilog – то все мои объяснения вам будут нафиг не нужны. Для удобства восприятия текста я убрал все «фишки», которые делают модули настраиваемыми. Некоторые вещи у меня описаны не самым рациональным способом. Связанно это с тем, что мне просто так удобнее работать с текстом. Так же для удобства восприятия текста я оставил максимально подробные комментарии. И так приступим


Прошлый пост закончился на том, что я описал, какие функциональные элементы нам необходимы для реализации нашего приёмника, а именно:

1. Синхронизатор с клоковым доменом

2. Счетчик, считающий от 0 до 15, для того, чтобы можно было определять длительность периода старт бита, стоп бита, битов данных.

3. Счётчик от 0 до 7, считающий, сколько бит приняли.

4. 3 разрядный регистр, для хранения 3 выборок в середине битового интерала, чтобы провести голосование.

5. Мажоритарный фильтр.

6. 8 разрядный регистр для хранения принимаемых бит данных.

7. Цифровой автомат, управляющий работой всех элементов.

СИНХРОНИЗАТОР

Для начала опишем модуль, или как правильно говорить на языке VHDL – компонент, который мы будем применять для того, чтобы синхронизировать входной асинхронный сигнал с частотой нашего клокового домена. Напомню что базовый синхронизатор- это обычный сдвиговый регистр. Я всегда выделяю его в отдельный модуль. Мне так проще работать. Вот его описание на языке VHDL:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Давайте посмотрим, как наш синхронизатор выглядит на технологической карте. Технологическая карта показывает как наша схема «ложится» в логические ячейки, которых в ПЛИС очень много. Собственно будут задействованы 3 триггера из логических ячеек, которые соединены между собой вот таким вот образом:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Как видите это то, что нам необходимо.

Давайте теперь взглянем на временные диаграммы его работы – времянки. Моделирование я провожу в программе Modelsim altera SE и применяю функциональное моделирование, по этой причине на диаграммах отсутствуют временные задержки сигналов.

Вот временные диаграммы функционирования нашего синхронизатора:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Как видите, ничего сложного нет. Приходит асинхронный сигнал ADATA. Передним фронтом частоты CLK он защелкивается в младший разряд регистра SHIFT_REG(0). Следующим фронтом в младший разряд регистра SHIFT_REG(0) защелкивается лог. 0, поскольку на линии ADATA у нас лог.0, а единичка, которая была записана ранее, передается в следующий разряд. Т.е SHIFT_REG(1). Данные как бы сдвигаются от младшего разряда к старшему разряду. Поэтому регистр и называется сдвиговым. Ваш КЭП. Красные линии означают, что в эти моменты времени состояния этих сигналов имеют неопределённость, или правильнее говорить в данный момент времени сигналы неинициализированны. Например, сразу после включения непонятно что храниться в регистре.

РЕГИСТР ХРАНЕНИЯ ВЫБОРОК

А теперь давайте опишем наш 3 разрядный регистр хранения выборок, которые будут оцениваться мажоритарным фильтром. Вот текст нашего регистра на VHDL:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Если обратите внимание, то вы увидите что это такой же сдвиговый регистр как и наш синхронизатор. Только выходом этого модуля является не старший разряд, а все разряды регистра. Вот во что он синтезируется:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Я думаю, что его времянки объяснять не надо:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

РЕГИСТР ХРАНЕНИЯ ДАННЫХ ПРИЁМА

А вот регистр хранения данных, чуть сложнее. У него добавляется управляющий вход ENA. Сигнал ENA –(от английского ENAble) сигнал, разрешающий или запрещающий работу регистра. Регистр работает только тогда, когда на этом входе есть лог.1. Если её нет, то регистр хранит данные, которые в него записали и игнорирует остальные сигналы. Вот его описание на VHDL:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Как видите, это практически такой же сдвиговый регистр. Разница в том, что он двигает данные слева направо. Т.е данные пишутся в старший разряд регистра SHIFT_REG(7) и потом сдвигаются в младшие разряды.


Внимание вопрос. Почему у меня регистр двигает данные слева направо. А не справа налево? Ответы можете оставить в комментариях.


А вот так он реализуется в логических ячейках ПЛИС:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

А вот его времянки:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Пока сигнал ENA = 0, регистр не изменяет свое состояние, независимо от состояний входа данных, и синхрочастоты.

Когда сигнал становится активным, т.е. ENA = 1, значит, работа регистра разрешается, и он ведёт себя как обычный сдвиговый регистр.

Сигнал снова стал неактивным, т.е. ENA = 0, значит, регистр хранит в себе данные, и не меняет своё состояния, и т.д…

СЧЁТЧИК БИТОВЫХ ИНТЕРВАЛОВ

Тут все совсем просто, это классический 4 разрядный счетчик с сигналом синхронного сброса. Вот его описание на VHDL:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Давайте взглянем, как он выглядит в RTL Viewer. RTL Viewer показывает, как выглядит наше описание в виде схемы. Обратите внимание, что данная схема имеет лишь косвенное отношение к реализации нашего описания в логических ячейках ПЛИС:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

А вот на технологической карте (то, что ложиться в логические ячейки ПЛИС) это выглядит так:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Программа сама минимизирует все логические, функции и то, в каком виде наш счётчик ложится в логические ячейки ПЛИС, решает софт для разработки. Для FPGA фирмы Altera Intel это Quartus. Эти алгоритмы закрыты для пользователей. Главное то, что счетчик работает, так как нам надо. А вот, кстати, как он работает:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Тут всё очевидно. Пока активен сигнал SCLR счетчик постоянно сбрасывается, поэтому его состояние 0. Сигнал SCLR перестал быть активным, счетчик начал считать. SCLR стал активным – счетчик сбросился. Когда счетчик досчитал до состояния, когда во всех разрядах единицы и следующим тактом у него произошло переполнение, и он снова стал считать с нуля. Поэтому на диаграммах вы видите, что после 15 счетчик считает с нуля.

СЧЕТЧИК ПРИНЯТЫХ БИТ

Он чуть сложнее чем обычный счетчик с синхронным сбросом, поскольку у этого счетчика есть вход ENA, т.е сигнал разрешения работы. Вот его описание на VHDL:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

То, как он выглядит на RTL Viewer я показывать не буду, нас всё равно это мало интересует. А вот диаграммы всё же покажу:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Работает он так же как и простой счетчик с синхронным сбросом. Только считает он только тогда, когда сигнал ENA активен, т.е. ENA = 1. Если же сигнал не активный, т.е. ENA = 0 то счетчик хранит своё состояние. Ваш КЭП.


На этом описание наших «кирпичиков» окончено. Мажоритарный фильтр, я опишу там же где и автомат. В итоге у нас есть библиотека из следующих элементов:

COUNTER_SCLR

COUNTER_ENA_SCLR

PARALEL_SHIFT_REG

PARALEL_SHIFT_REG_ENA

SYNC_TO_CLOCK_DOMAIN

Данные компоненты мы описали один раз, и они формируют нашу библиотеку. В наших проектах мы их можем использовать бесчисленное количество раз. Особенно если их сделать параметризированными…

Когда компонент имеет чёткое имя, отражающее суть его работы, то его проще найти в библиотеке файлов, особенно когда у вас библиотека состоит более чем из 100 таких вот элементов. По правильному названию элемента вы можете иметь представление об его функционировании. Это очень удобно, так как со временем забывается, что в этой библиотеке есть. А по «говорящим» именам все легко искать. Конечно все, что я говорю, это лишь мои собственные предпочтения, вы можете называть элементы как вам удобнее. Как я делаю, я рассказал, выбор за вами.


Вот теперь можно приступить к описанию приемника UART, где цифровой автомат управляет нашими модулями, или как правильно говорить в VHDL – компонентами.

Полностью показывать весь код я не буду, поскольку это почти 200 строк. Поскольку ключевым устройством является именно цифровой автомат, то я просто выложу только те куски кода, которые, так или иначе, нужны для понимания логики работы автомата.

Подключаем наши описанные «кирпичики» и описываем поведение мажоритарного фильтра:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост
Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Автомат мы описываем 3 процессами.

Первый процесс описывает, когда происходит смена состояния автомата:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Второй процесс описывает, то, как вычисляется следующее состояние, в которое должен переключиться автомат:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Последний процесс описывает то, как автомат управляет нашими счетчиками, регистрами:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Ну и теперь, самое вкусное. Как всё это выглядит времянках. Для проверки я написал простенький тест, который отправляет приемнику байт: «01010101», он же число 55 в шестнадцатеричной системе. Очевидно, что если наш приёмник написан правильно, то на выходе этого приемника, должно появиться  число, которое мы ему отправляли. Учтите, что принятое значение должно быть верным только в момент, когда приёмник говорит, что данные корректны т.е. сигнал DATA_VALID = 1. Вот времянка:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

И давайте посмотрим, как наш приёмник отработает корявый старт-бит:

Простенькие примеры на ПЛИС. UART. Часть 1. Заключительная. Плис, Fpga, Uart, Com, Разработка, Схемотехника, Программирование, Длиннопост

Внимание вопрос! Почему я счетчик обнуляю, когда он досчитал до 14?(все ответы есть на времянках)


На этом статью про разработку простейшего приёмника UART я закончил. К сожалению, видео работы приёмника я показать не смогу, поскольку у меня нечем снимать видео. Но в «железе» приёмник работает так, как я и задумывал. Придется вам поверить на слово.

В процессе объяснения вам могло показаться, что все это слишком сложно. На самом деле это не так. Всё очень и очень просто. Данный приёмник я написал за 1 вечер неторопливой работы. Гораздо больше времени заняло изучение протокола UART.


Так же, наверное, у многих возник вопрос, а зачем такие сложности, когда на Arduino можно взять готовую библиотеку, написать несколько строчек кода и всё будет работать? От части это так, на Arduino все делается проще, если есть готовая библиотека. А если её нет? А если она криво написана? А если….


В общем скажу так: проще, не значит лучше. Например мой приёмник занимает в ПЛИС всего 37 логических ячеек. А у меня этих ячеек в ПЛИС около 10 000. Теоретически я могу в ПЛИС запихать 270 таких приёмников, которые будут работать одновременно и независимо друг от друга. Правда это нафиг никому не нужно. Да и, как я в самом первом посте говорил, задачи у ПЛИС и микроконтроллеров разные.

Вы смотрите срез комментариев. Показать все
Автор поста оценил этот комментарий
А можешь исходник предоставить?
раскрыть ветку (5)
Автор поста оценил этот комментарий

Могу. Как буду за ПК скину. Куда скидывать ?

раскрыть ветку (4)
Автор поста оценил этот комментарий
Можешь прислать на почту? chernebkoanton@gmail.com
раскрыть ветку (3)
Автор поста оценил этот комментарий

Отправил таки.

Автор поста оценил этот комментарий

Могу конечно. Только тебя устроит чуть более навороченный вариант ? В нём у меня реализована возможность установки сколько бит будет в посылке.

Учебный вариант куда-то делся )

раскрыть ветку (1)
Автор поста оценил этот комментарий
Думаю да)
Вы смотрите срез комментариев. Чтобы написать комментарий, перейдите к общему списку