Перейти к содержанию
    

Делитель частоты M/N без PLL

Здравствуйте. Конкретная задача:

Дано - на входе F_in = 1MHz асинхронная относительно системного клока (F_clk > 50MHz, можно изменять). Надо из нее получить F_out = 364kHz.

F_out должна быть синхронизирована с F_in, сдвиг по фазе не имеет значения (до должен быть const). Допускается растянуть или ужать период F_out для синхронизации c F_in. Главное требование - на 1000 периодов F_in должно получится 364 периода F_out и это соотношение должно поддерживаться сколь угодно длительное время.

PLL использовать не получается потому что у Cyclone IV Fmin = 5MHz для PLL.

Первое что приходит в голову "в лоб" - сделать генератор на 364kHz на счетчике из некоторой промежуточной частоты которою получить из PLL (например 93.189MHz/256).

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

Сразу признаюсь - я начинающий и безнадежно испорчен программированием, поэтому могу несознательно предлагать бред с точки зрения ПЛИС :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Дано - на входе F_in = 1MHz асинхронная относительно системного клока (F_clk > 50MHz, можно изменять). Надо из нее получить F_out = 364kHz.

F_out должна быть синхронизирована с F_in, сдвиг по фазе не имеет значения (до должен быть const). Допускается растянуть или ужать период F_out для синхронизации c F_in. Главное требование - на 1000 периодов F_in должно получится 364 периода F_out и это соотношение должно поддерживаться сколь угодно длительное время.

 

Может устроит простой дробный делитель на 1000/364 ?

Будет джитер в один период F_in,

но за 22750 (250*91) тактов F_in

на выходе будет ровно 8281 тактов F_out.

//
// Формирователь тактовой 364 из 1000
//
module F364from1000
(
    input Clk,            // Тактовая 1000
    output F364        // Тактовый сигнал с частотой 364
);

    reg [9:0]Div1000;        // Счетчик делитель на 1000/364
    reg Rg;            // Регистр для хранения предыдущего значения старшего бита счетчика

    wire Carry = (Rg && !Div1000[9]);    // Перенос из старшего разряда счетчика

    assign F364 = Div1000[9];

    always @(posedge Clk)
     begin
        Rg <= Div1000[9];

        Div1000 <= Div1000 + 10'd364 + (Carry? 10'd24 : 10'd0);
     end

endmodule

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может устроит простой дробный делитель на 1000/364 ?

Спасибо, попробую понять "на бумаге" как оно работает - думаю будет непрохое упражнение.

Хотя специфика задача такова что требуется именно соотношение 1000/364, так как это клоки последовательной передачи (типа SPI) вход-выход модуля, в котором из 1000 входных бит получается 364 выходных и их надо выдать за точно такое же время, за коротое приходят на вход 1000.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, попробую понять "на бумаге" как оно работает - думаю будет непрохое упражнение.

Хотя специфика задача такова что требуется именно соотношение 1000/364, так как это клоки последовательной передачи (типа SPI) вход-выход модуля, в котором из 1000 входных бит получается 364 выходных и их надо выдать за точно такое же время, за коротое приходят на вход 1000.

 

Извините, лопухнулся...

Выдрал этот делитель из одного из рабочих проектов,

подправив соотношения под Ваш случай, да не учел

что там использовалась удвоенная частота на выходе

счетчика.

Исправил код в своем первом сообщении.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Извините, лопухнулся...

Я правильно понял, что у вас из 1000 тактов тактовой частоты 364 вначале (или в конце) используются как F_out? Того ли хотел топикстартер?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я правильно понял, что у вас из 1000 тактов тактовой частоты 364 вначале (или в конце) используются как F_out? Того ли хотел топикстартер?

 

Нет, конечно...

Этот делитель выдает равномерно распределенные 364 такта

из входных 1000-и тактов. Но равномерность, естественно,

не идеальная, а имеет дрожания с размахом в один период входной частоты.

 

Если взять сигнал с нормального генератора на 364 кГц

и пропустить его через D-тригер, который тактируется 1-м МГц,

на выходе тригера будет точно такой же сигнал

как и с этого дробного делителя.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если поставить NCO, и из него взять старший разряд... Конечно из пушки по воробьям, но почему бы и нет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если поставить NCO, и из него взять старший разряд... Конечно из пушки по воробьям, но почему бы и нет?

Старший разряд счетчика? Ну как мне кажется идейно похоже на мое предложение в первом посте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, конечно...

Этот делитель выдает равномерно распределенные 364 такта

из входных 1000-и тактов. Но равномерность, естественно,

не идеальная, а имеет дрожания с размахом в один период входной частоты.

Я повозился с вашим примером. Кажется, упростил. Во всяком случае, сообразил, как он работает. Привожу код для 3-х импульсов из 10.

module f3fr10
( input bit clk,
  output bit f3 );
  bit [3:0] div;
  always @(posedge clk)
    {f3,div} = div + (f3? (16-10):3);
endmodule

Если вычитать, а не складывать, наверное, еще проще будет выглядеть описание.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Привожу код для 3-х импульсов из 10.

Если расписать состояния бита f3 и значения счетчика Div

для пары десятков входных импульсов, то видно,

что не получается 3 из 10:

 

 N        f3        Div
-        --        ---
0.        0        0
1.        0        3
2.        0        6
3.        0        9
4.        0        12
5.        0        15
6.        1        2
7.        1        6
8.        1        10
9.        1        14
10.        0        2
11.        0        5
12.        0        8
13.        0        11
14.        0        14
15.        1        1
16.        1        5
17.        1        9
18.        1        13
19.        0        1
20.        0        4
21.        0        7

 

 

Если вычитать, а не складывать, наверное, еще проще будет выглядеть описание.

 

Вряд ли что нибудь изменится...

 

Нужно сформировать сигнал переполнения счетчика,

для однократной коррекции его значения на +4 (16 - 10)

У меня для этого использовался тригер Rg,

запоминающий предыдущее значение старшего

бита счетчика и собственно сигнал переполнения - Carry.

Ну и инкремент на +3 надо делать на каждом такте, а у Вас

он почему то не делается при f3 == 1.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С числом я просчитался, но не с принципом. Вот правильный код и временные диаграммы.

module f3fr10
( input bit clk,
  output bit f3 );
  bit [3:0] div;
  always @(posedge clk)
    {f3,div} = div + (f3? (10-1):3);
endmodule

 

post-10362-1299784645_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А такая сумасшедшая идея:

Наименьшее общее кратное(1000, 364) = 91000.

Сделать генератор на 91MHz. Делением на 91 получаем 1MHz которые в DPLL (самописной) синхронизируем с входным 1MHz. Делим те же 91MHz (уже синхронизированные) на 250 и получаем точно 364kHz.

Будет работать или Остапа понесло? :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С числом я просчитался, но не с принципом. Вот правильный код и временные диаграммы.

Я тоже просчитался, почему то восприняд f3 как 5-й разряд

счетчика, не сообразил, что это более простой способ получить

бит переноса счетчика.

Спасибо за более изящный вариант.

 

 

 

Наименьшее общее кратное(1000, 364) = 91000.

Сделать генератор на 91MHz. Делением на 91 получаем 1MHz которые в DPLL (самописной) синхронизируем с входным 1MHz. Делим те же 91MHz (уже синхронизированные) на 250 и получаем точно 364kHz.

Будет работать или Остапа понесло? :)

Работать будет, только можно проще. Если вернуться к Вашей исходной задаче,

где входным сигналом является строб с частотой 1 кГц, то имеет смысл сделать DPLL

для получения 364 кГц, синхронные с этим стробом:

- Сделать генератор на 46592 кHz (364 * 128).

- С помощью делителя на 128 получить 364кГц (Делитель должен иметь цепи коррекции на +/- 1).

- Дальше делите 364кГц до 1 кГц, и уже этот сигнал подстраиваете под входной строб,

используя цепи коррекции делителя на 128.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за более изящный вариант.

Выкладываю универсальный проект, основанный на идее Shamil

module MfromN
#(parameter M = 4,  // количество выходных импульсов
            N = 17)  // период последовательности
(input bit clk,  // тактовая частота
  output bit fm);  // выходные импульсы

  localparam X = ((1<<$clog2(N)) - N + M);
  bit [$clog2(N)-1:0] cnt; // счетчик
  always @(posedge clk)
    {fm,cnt} = cnt + (fm? X:M);
endmodule

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Выкладываю универсальный проект

Весьма полезный модуль получился, спасибо, пригодится...

Надо только оговорить, что число M должно быть меньше

или равно половине N, иначе выходной сигнал можно будет

использовать только как импульсы разрешения счета по

входному клоку.

 

P.S. А идея не моя...

Это самый обычный аккумлятор фазы, на основе которого делаются

генераторы управляемые кодом (NCO). В них, обычно, не заморачиваются

коррекцией периода счета до N, а за счет большой разрядности сводят

погрешность к минимуму.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...