реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Проблемы при проектировании приёмника последовательного интерфейса, Коррекция частот
MIX@
сообщение Jan 21 2009, 22:58
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 53
Регистрация: 21-01-09
Пользователь №: 43 756



Доброго времени суток!

Делаю свой первый конфигурируемый приёмник асинхронного последовательного протокола. Конфигурация подразумевает возможность
программного задания скорости приёма.

Соответсвенно, что есть -
есть некоторая частота осциллятора и есть значения частот семплирования линии, рассчитанные
как скорость приёма (baud) умноженная на 64. Множитель 64 взял для более точного распознавания стартового перепада.

Скажем, baud = 115200 Гц => baud*64 = 7 372 800 Гц
Пусть частота осциллятора равна 40 МГц, тогда для получения baud*64 получаем коэффициент деления 5,42.
Тут и начинаются проблемы - если взять, например, 5-ку, то возникает погрешность...
Такая ситуация складывается с любыми значениями baud => нужно корректировать частоту, чтобы избежать рассогласования приёмника и передатчика и сделать это максимально прозрачно для всех остальных компонентов блока приёмника.
Единственный вариант, который пришёл мне в голову - вынести это в блок семплирования линии.

В чём суть, более подробно: рассчитанный коэффициент деления даёт нам в аккурат частоту в 1/64 baud,
но поскольку приходится его округлять, то новый коэффициент уже не будет отмерять ровно по 1/64 baud, т.е.
нужно рассчитать какова новая частота семплирования и подогнать под значение нашего множителя.
Проще говоря: при значении 5 - значение множителя будет 69, а не 64. Для baud 57600 - 63, а не 64 и т.д.
Только для 9600 получилось в аккурат 64 wink.gif
Но хочется, чтобы управляющий автомат так и работал с одним коэффициентом (64), чтобы его ещё больше не усложнять.

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

Вот пример verilog-кода, демонстрирующий сказанное:

Код
case (baud_num)
    1: begin
        value <= value + 1;  // baud = 9600
        inner_cnt <= 0;
       end
    default: begin    //baud = 115200
        inner_cnt <= inner_cnt + 1;
        value <= (inner_cnt == 12 ||
            inner_cnt == 24 ||      //Такое условие сделал, чтобы более равномерно
            inner_cnt == 36 ||      // провести коррекцию в статистическом смысле
            inner_cnt == 48 ||
            inner_cnt == 60) ? value : value + 1;
        end
endcase


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

Заранее благодарю за советы.
Go to the top of the page
 
+Quote Post
SSerge
сообщение Jan 22 2009, 01:13
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Вот делили бы на 8 или на 16 вместо 64 и никаких проблем бы не было. Во многих контроллерах UART так и работает, с 16 или 8 клоками на бит. И не жужжит.
Если же очень хочется, есть куча вариантов.
1. Почитать как устроен UART у MSP430 и попробовать догадаться как это реализовано.
2. Сразу после кварца поставить хитрый делитель наподобие 155ИЕ8, далее - как обычно. В прежние времена это было весьма распространённым решением, удавалось достаточно точно подогнать битовую скорость при любой (из разумных) частоте кварца.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
DmitryR
сообщение Jan 22 2009, 07:11
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 535
Регистрация: 20-02-05
Из: Siegen
Пользователь №: 2 770



Выбор раздела подсказывает, что вы используете FPGA. Так вот, там есть PLL, которые умеют умножать входную частоту на дробь (M/N), и эту дробь можно перепрограммировать во время работы.
Go to the top of the page
 
+Quote Post
Builder
сообщение Jan 22 2009, 07:58
Сообщение #4


iBuilder©
****

Группа: Свой
Сообщений: 519
Регистрация: 14-07-04
Из: Минск
Пользователь №: 322



Цитата(MIX@ @ Jan 22 2009, 02:58) *
И всё бы ничего - если бы данное решение занимало малое количество логических элементов, так нет...
Может быть, есть какие-то другие способы решить данную проблему, при этом более экономно расходуя ресурсы?

Если не передумаете использовать деление на 64, как Вам советовали, ещё вариант - использовать для деления
метод оценочной функции, получится типа того, как в алгоритме брезенхема делается, при отрисовке линии.

Получится делитель, с автоматическим учётом округлений. Вот только сколько ресурсов будет - надо пробовать, но
скорее всего меньше, чем Ваш вариант.
Go to the top of the page
 
+Quote Post
EvgenyNik
сообщение Jan 22 2009, 13:10
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 597
Регистрация: 24-05-06
Из: г. Чебоксары
Пользователь №: 17 402



PLL бы Вас выручил, это да. Но цифра 64, действительно, вызывает некоторое недоумение.
Если нет PLL, то я бы взял кварц на 18.432 МГц, поделил на 10 и получил бы частоту, которая в 16 раз больше 115200 и так далее с нормальными кратностями.
Если цифра 64 не даёт покоя wink.gif , то можно сделать деление 18.432 МГц в 2.5 раза на несложной логике, но смысла в этом нет.


--------------------
Почему разработчики систем повышенной надёжности плохо справляются с простыми проектами? :)
Go to the top of the page
 
+Quote Post
Mig&L
сообщение Jan 22 2009, 13:34
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 107
Регистрация: 1-07-07
Пользователь №: 28 823



Взляните на оригинальный пример Interface RS-232 на http://www.fpga4fun.com/SerialInterface2.html
Go to the top of the page
 
+Quote Post
sazh
сообщение Jan 22 2009, 15:22
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 435
Регистрация: 6-10-04
Из: Петербург
Пользователь №: 804



Цитата(MIX@ @ Jan 22 2009, 01:58) *
Скажем, baud = 115200 Гц => baud*64 = 7 372 800 Гц
Пусть частота осциллятора равна 40 МГц, тогда для получения baud*64 получаем коэффициент деления 5,42.
Тут и начинаются проблемы - если взять, например, 5-ку, то возникает погрешность...


А на что влияет эта погрешность? 25 нс туда сюда от середины стартового бита. А до стопового бита 250 нс набежит. За пределы бита на всей посылке никуда не денется.
Не нужен вам промежуточный коэффициент деления 64. Достаточно два параметра. Частота осцилятора (любая системная) и частота несущей baud.

http://electronix.ru/forum/index.php?showt...mp;#entry425957
Go to the top of the page
 
+Quote Post
MIX@
сообщение Jan 23 2009, 04:19
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 53
Регистрация: 21-01-09
Пользователь №: 43 756



Благодарю за советы!
Забыл сказать, что работаю я с учебным стендом на базе FPGA серии Cyclone, в принципе, возможность для ввода внешнего синхросигнала там есть, но не хочется заморачиваться. А PLL использовать не хочется из-за накладываемых ограничений по портируемости - проект прежде всего учебный.

Думаю, оптимальным будет предложенный Mig&L вариант:
Цитата
FPGA baud generator

It is desirable that the 2000000 be a power of two. Obviously 2000000 is not a power of two. So we change the ratio. Instead of the ratio "2000000/115200", let's use "1024/59" = 17.356. That's very close to our ideal ratio, and makes an efficient FPGA implementation.// 10 bits for the accumulator ([9:0]), and one extra bit for the accumulator carry-out ([10])
Код
reg [10:0] acc;   // 11 bits total!

always @(posedge clk)
  acc <= acc[9:0] + 59; // use only 10 bits from the previous result, but save the full 11 bits

wire BaudTick = acc[10]; // so that the 11th bit is the carry-out



Using our 2MHz clock, "BaudTick" is asserted 115234 times a second, a 0.03% error from the ideal 115200.


А с множителем 64 я, наверное, действительно загнул - возьму 16. Слышал, что меньше 16 брать не рекомендуется, в принципе - большой % ошибок будет, сам не проверял. Вот и решил взять с запасом, благо частоты осциллятора позволяют smile.gif

Ещё возникает вопрос: непосредственно перед сдвигающим регистром приёмника всегда ставят некий "синхронизатор" из двух d-триггеров.
Заявляются следующие два аргумента:
1) позволяет избежать "срабатывания" приёмника от случайной помехи на линии
2) служит для синхронизации частоты передатчика и приёмника.
Первый аргумент мне понятен, а вот второй нет - за счёт чего? Не уж-то это что-то вроде укороченного варианта преамбулы в Ethernet'е?

Сообщение отредактировал MIX@ - Jan 23 2009, 04:21
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 13:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01447 секунд с 7
ELECTRONIX ©2004-2016