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

 
 
> Проблемы при проектировании приёмника последовательного интерфейса, Коррекция частот
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
 
Start new topic
Ответов
sazh
сообщение Jan 22 2009, 15:22
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 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 - 21:03
Рейтинг@Mail.ru


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