akorud 0 9 марта, 2011 Опубликовано 9 марта, 2011 · Жалоба Здравствуйте. Конкретная задача: Дано - на входе 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 на этом интервале. Сразу признаюсь - я начинающий и безнадежно испорчен программированием, поэтому могу несознательно предлагать бред с точки зрения ПЛИС :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shamil 2 9 марта, 2011 Опубликовано 9 марта, 2011 · Жалоба Дано - на входе 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
akorud 0 9 марта, 2011 Опубликовано 9 марта, 2011 · Жалоба Может устроит простой дробный делитель на 1000/364 ? Спасибо, попробую понять "на бумаге" как оно работает - думаю будет непрохое упражнение. Хотя специфика задача такова что требуется именно соотношение 1000/364, так как это клоки последовательной передачи (типа SPI) вход-выход модуля, в котором из 1000 входных бит получается 364 выходных и их надо выдать за точно такое же время, за коротое приходят на вход 1000. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shamil 2 9 марта, 2011 Опубликовано 9 марта, 2011 · Жалоба Спасибо, попробую понять "на бумаге" как оно работает - думаю будет непрохое упражнение. Хотя специфика задача такова что требуется именно соотношение 1000/364, так как это клоки последовательной передачи (типа SPI) вход-выход модуля, в котором из 1000 входных бит получается 364 выходных и их надо выдать за точно такое же время, за коротое приходят на вход 1000. Извините, лопухнулся... Выдрал этот делитель из одного из рабочих проектов, подправив соотношения под Ваш случай, да не учел что там использовалась удвоенная частота на выходе счетчика. Исправил код в своем первом сообщении. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 марта, 2011 Опубликовано 9 марта, 2011 · Жалоба Извините, лопухнулся... Я правильно понял, что у вас из 1000 тактов тактовой частоты 364 вначале (или в конце) используются как F_out? Того ли хотел топикстартер? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shamil 2 9 марта, 2011 Опубликовано 9 марта, 2011 · Жалоба Я правильно понял, что у вас из 1000 тактов тактовой частоты 364 вначале (или в конце) используются как F_out? Того ли хотел топикстартер? Нет, конечно... Этот делитель выдает равномерно распределенные 364 такта из входных 1000-и тактов. Но равномерность, естественно, не идеальная, а имеет дрожания с размахом в один период входной частоты. Если взять сигнал с нормального генератора на 364 кГц и пропустить его через D-тригер, который тактируется 1-м МГц, на выходе тригера будет точно такой же сигнал как и с этого дробного делителя. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
eugen_pcad_ru 0 9 марта, 2011 Опубликовано 9 марта, 2011 · Жалоба А если поставить NCO, и из него взять старший разряд... Конечно из пушки по воробьям, но почему бы и нет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
akorud 0 10 марта, 2011 Опубликовано 10 марта, 2011 · Жалоба А если поставить NCO, и из него взять старший разряд... Конечно из пушки по воробьям, но почему бы и нет? Старший разряд счетчика? Ну как мне кажется идейно похоже на мое предложение в первом посте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 марта, 2011 Опубликовано 10 марта, 2011 · Жалоба Нет, конечно... Этот делитель выдает равномерно распределенные 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 Если вычитать, а не складывать, наверное, еще проще будет выглядеть описание. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shamil 2 10 марта, 2011 Опубликовано 10 марта, 2011 · Жалоба Привожу код для 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 марта, 2011 Опубликовано 10 марта, 2011 · Жалоба С числом я просчитался, но не с принципом. Вот правильный код и временные диаграммы. module f3fr10 ( input bit clk, output bit f3 ); bit [3:0] div; always @(posedge clk) {f3,div} = div + (f3? (10-1):3); endmodule Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
akorud 0 10 марта, 2011 Опубликовано 10 марта, 2011 · Жалоба А такая сумасшедшая идея: Наименьшее общее кратное(1000, 364) = 91000. Сделать генератор на 91MHz. Делением на 91 получаем 1MHz которые в DPLL (самописной) синхронизируем с входным 1MHz. Делим те же 91MHz (уже синхронизированные) на 250 и получаем точно 364kHz. Будет работать или Остапа понесло? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shamil 2 11 марта, 2011 Опубликовано 11 марта, 2011 · Жалоба С числом я просчитался, но не с принципом. Вот правильный код и временные диаграммы. Я тоже просчитался, почему то восприняд 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 11 марта, 2011 Опубликовано 11 марта, 2011 · Жалоба Спасибо за более изящный вариант. Выкладываю универсальный проект, основанный на идее 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shamil 2 11 марта, 2011 Опубликовано 11 марта, 2011 · Жалоба Выкладываю универсальный проект Весьма полезный модуль получился, спасибо, пригодится... Надо только оговорить, что число M должно быть меньше или равно половине N, иначе выходной сигнал можно будет использовать только как импульсы разрешения счета по входному клоку. P.S. А идея не моя... Это самый обычный аккумлятор фазы, на основе которого делаются генераторы управляемые кодом (NCO). В них, обычно, не заморачиваются коррекцией периода счета до N, а за счет большой разрядности сводят погрешность к минимуму. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться