tems-ya 0 November 21 Posted November 21 · Report post Добрый день! Возможно где-то уже обсуждалось и/или написано в букварях, но что-то прямо вот так поиском сразу по теме ничего не находится. В процессе подключения Ethernet контроллера W5500 к FPGA столкнулся с ситуацией, что данному чипу по феншую надо бы формировать ряд достаточно длинных задержек (конкретные величины указаны в заголовке темы). Никаких существенных требований к ним нет - это просто паузы, когда ничего не делаем, т.е. их точность может быть +-километр. Наши узкоглазые братья китайцы (ну или один брат, который писал код) не стали заморачиваться и поступили так: //Счетчик задержки 50 мс reg [23:0] Delay50_1; always @(posedge clk or negedge rst_n) if (!rst_n) Delay50_1 <= 24'd0; else if (Hardware_State == Hard_DELAY50) Delay50_1 <= Delay50_1 + 1'b1; //Счетчик задержки 200 мс reg [23:0] Delay200_1; always @(posedge clk or negedge rst_n) if (!rst_n) Delay200_1 <= 24'd0; else if (Hardware_State == Hard_DELAY200) Delay200_1 <= Delay200_1 + 1'b1; else Delay200_1 <= 24'd0; //Счетчик задержки 10 мс reg [23:0] Delay10_1; always @(posedge clk or negedge rst_n) if (!rst_n) Delay10_1 <= 24'd0; else if (W5500_INIT_State == W5500_INIT_DELAY10) Delay10_1 <= Delay10_1 + 1'b1; else Delay10_1 <= 24'd0; //Счетчик задержки 5 мс reg [23:0] Delay5_1; always @(posedge clk or negedge rst_n) if (!rst_n) Delay5_1 <= 24'd0; else if (SOCKET_CONN_State == SOCKET_CONN_DELAY5) Delay5_1 <= Delay5_1 + 1'b1; else Delay5_1 <= 24'd0; Как говорится от души, когда кремния много и его не жалко... Вот здесь https://www.fpga4fun.com/Counters1.html нашел предложение как можно счетчик немного поджать по ресурсам. В моем оформлении: //https://www.fpga4fun.com/Counters1.html `define SMOLL_RESURSES module FPGA_TOP #( parameter CNT_WITH = 19 //2^19 * 20ns = 10,48576 ms )( input clk ,//Clock 50MHz input rst_n ,//RESET output tick ); `ifdef SMOLL_RESURSES reg [CNT_WITH-1:0] cnt; wire [CNT_WITH:0] cnt_next = cnt + 1'b1; always @(posedge clk or negedge rst_n) if(!rst_n ) cnt <= 'd0; else cnt <= cnt_next[CNT_WITH-1:0]; assign tick = cnt_next[CNT_WITH]; `else reg [CNT_WITH:0] cnt; always @(posedge clk or negedge rst_n) if(!rst_n ) cnt <= 'd0; else cnt <= cnt + 1'b1; assign tick = &cnt; `endif endmodule Действительно, вместо Total logic elements - 27 Total registrs - 20 получаем Total logic elements - 20 Total registrs - 19 Вроде как не очень много всего 7 элементов, но с другой стороны, если счетчиков будет 4, то выигрыш уже 28, а если их разрядность будет больше, то разница становится еще заметнее. При условии, что весь проект занимает порядка 600-700 логических элементов тратить столько просто на пустое ожидание...Не то чтобы прямо критично, но как-то это мне кажется не очень красивым. Читал где-то здесь, обсуждение как путем хитрых манипуляций с последовательным записью/чтением в память и обратно тоже типа получалось получать задержки на сколько-то там...Но боюсь, что что вот так просто идя от идеи повторить не смогу Собственно вопрос к уважаемому сообществу, кто-как решает такого рода проблемы и приходилось ли кому заморачиваться с оптимизацией всего этого дела в плане занимаемых ресурсов. Может кто еще какие хитрые способы знает как можно добиться нужного эффекта или может поделиться своими соображениями и/или их реализацией. Буду благодарен. Спасибо. Quote Share this post Link to post Share on other sites More sharing options...
Alex11 7 November 21 Posted November 21 · Report post Первое, что приходит в голову - сделать один счетчик, ведь, как я понимаю, задержки реализуются не одновременно. И в добавок к нему управление - загрузка разных чисел в зависимости от пришедшего состояния и далее счет. Это займет один дополнительный триггер и некоторое количество логики, но небольшое. Quote Share this post Link to post Share on other sites More sharing options...
RobFPGA 36 November 21 Posted November 21 · Report post 1 hour ago, tems-ya said: Вроде как не очень много всего 7 элементов О да, сэкономили 7 ячеек из 10K...2M имеющихся ... Но если уж так "жаба давит": .... localparam CNT_5MS_WH = clog2(W5500_INIT_DELAY5MS); localparam [CNT_5MS_WH:0 ] DIV_5MS_N = (1<<CNT_5MS_WH) - W5500_INIT_DELAY5MS + 1; reg tick; reg [CNT_5MS_WH-1:0] cnt; .... if (!rst_n) {tick, cnt} <= DIV_5MS_N; else {tick, cnt} <= tick ? DIV_5MS_N : {tick, cnt} + 1'b1; .... И если функционал позволяет и допустима точность "+-километр" то строить дерево счётчиков/делителей. Сначала счётчик на "километр" (например на 1ms), а затем уж мало разрядные счётчики тиков "километров" на 5 на 10 ... Quote Share this post Link to post Share on other sites More sharing options...
_4afc_ 30 November 21 Posted November 21 · Report post 1 hour ago, tems-ya said: Никаких существенных требований к ним нет - это просто паузы, когда ничего не делаем, т.е. их точность может быть +-километр. У каждой ПЛИС есть внутренний RC генератор для загрузки прошивки. Частотой около 120МГц с возможностью деления до 128 - сделайте счётчик на нём. А лишняя PLL есть? За сколько она лочится? Внешняя RC цепочка между ногами ? У меня написан модуль Pause( C, R, CE, D, S, E) который задерживает прохождение строба S->E на 0.02/0.12/1.2/30 мсек в зависимости от D(0..3). Внутри есть параметр задающий частоту C. Для частоты C=30МГц модуль занимает 36 регистров и 44 LUT. Состоит из последовательно соединённых счётчиков-делителей на FREQ=30, и 20,6,10,25 плюс небольшая логика какой из счётчиков последний. Судя по отчётам может работать на GW2A на частоте 340МГц. Просто мне иногда надо чтобы проект и на 120МГц работал, и боюсь 24 битные счётчики тогда на DSP модулях придётся делать... Quote Share this post Link to post Share on other sites More sharing options...
dinam 1 November 25 Posted November 25 · Report post В 21.11.2024 в 21:20, _4afc_ сказал: У каждой ПЛИС есть внутренний RC генератор для загрузки прошивки. Частотой около 120МГц с возможностью деления до 128 - сделайте счётчик на нём. А можете поподробнее? Применял Cyclone II, Cyclone V E и Cylcone 10 LP. Не помню про такую возможность. Quote Share this post Link to post Share on other sites More sharing options...
Alex77 5 November 25 Posted November 25 · Report post Особо одарённые не указывают фирму производителя микросхем - как следствие каждый думает "о своём" 1 Quote Share this post Link to post Share on other sites More sharing options...
tems-ya 0 November 25 Posted November 25 · Report post Спасибо, всем откликнувшимся, особенно RobFPGA - за самый компактный по ресурсам вариант да еще и с начальной предустановкой! Хотел эту идею немного причесать, но застрял в самом неожиданном месте module ZAD_MS #( parameter PARAM_ZAD_MS = 200, parameter CLK_IN_HZ = 50_000_000 )( input clk , //Clock 50MHz input rst_n , //RESET output reg tick ); //проблема в этой строке... localparam integer CUR_CNT = CLK_IN_HZ*PARAM_ZAD_MS/1000; // величина счетчика, соответсвующая требуемой задержке localparam CNT_WH = $clog2(CUR_CNT); //сширина счечика, сколько разрядов нужно, чтобы сформировать требуемую задержку localparam [CNT_WH:0 ] INIT_CNT = (1<<CNT_WH) - CUR_CNT + 1; // (1<<CNT_WH) = 2^CNT_WH = MAX_CNT = 2^19 = 524_288 reg [CNT_WH-1:0] cnt; always @(posedge clk or negedge rst_n) if (!rst_n) {tick, cnt} <= INIT_CNT; else {tick, cnt} <= tick ? INIT_CNT : {tick, cnt} + 1'b1; endmodule Камрады, как правильно реализовать описать параметр CUR_CNT коде выше, чтобы он работал для любых значений задержек. Qurtus 17 - сейчас при PARAM_ZAD_MS > 40 перестает работать.... Спасибо. Quote Share this post Link to post Share on other sites More sharing options...
blackfin 32 November 25 Posted November 25 · Report post On 11/25/2024 at 4:29 PM, tems-ya said: Камрады, как правильно реализовать описать параметр CUR_CNT коде выше, чтобы он работал для любых значений задержек. Проще всего так: module ZAD_MS #( parameter PARAM_ZAD_MS = 200, parameter CLK_IN_KHZ = 50_000 )(...); localparam CUR_CNT = CLK_IN_KHZ*PARAM_ZAD_MS; // величина счетчика, соответствующая требуемой задержке Но можно и так: module ZAD_MS #( parameter PARAM_ZAD_MS = 200, parameter CLK_IN_HZ = 50_000_000 )(...); localparam CUR_CNT = CLK_IN_HZ/1000*PARAM_ZAD_MS; // величина счетчика, соответствующая требуемой задержке Quote Share this post Link to post Share on other sites More sharing options...
_pv 79 November 25 Posted November 25 · Report post если убрать integer он вроде перестанет быть 32х битным localparam CUR_CNT = CLK_IN_HZ*PARAM_ZAD_MS/1000; Quote Share this post Link to post Share on other sites More sharing options...
_4afc_ 30 November 26 Posted November 26 · Report post On 11/25/2024 at 10:30 AM, dinam said: А можете поподробнее? Применял Cyclone II, Cyclone V E и Cylcone 10 LP. Не помню про такую возможность. Ну а как они по вашему грузятся сами? Читайте AN 496: Using the Internal Oscillator Intel® FPGA IP Quote Share this post Link to post Share on other sites More sharing options...
dinam 1 November 26 Posted November 26 · Report post 1 час назад, _4afc_ сказал: Ну а как они по вашему грузятся сами? Читайте AN 496: Using the Internal Oscillator Intel® FPGA IP Согласно документу, который вы привели и вашим словам Cyclone II не могут грузится, а они у меня нормально конфигурируются. 😊 Cyclone V E я осваивал тогда, когда и в помине производитель не предоставлял такую возможность. Да, с Cylcone 10 LP не увидел такую возможность, тут признаю. Но для меня слишком уж частота неопределенная, указывается только верхняя граница. Quote Share this post Link to post Share on other sites More sharing options...
_4afc_ 30 November 26 Posted November 26 · Report post 51 minutes ago, dinam said: Согласно документу, который вы привели и вашим словам Cyclone II не могут грузится, а они у меня нормально конфигурируются. 😊 Cyclone V E я осваивал тогда, когда и в помине производитель не предоставлял такую возможность. Да, с Cylcone 10 LP не увидел такую возможность, тут признаю. Но для меня слишком уж частота неопределенная, указывается только верхняя граница. Intel/AMD предоставляют такую возможность в виде костыля торчащего из упрятанного блока конфигурации ПЛИС - поэтому попытайтесь посмотреть настройки соответствующего IP. У GoWin/Lattice - это отдельные, хорошо описанные блоки, в том числе и дополнительные на 10кГц. Quote Share this post Link to post Share on other sites More sharing options...
RobFPGA 36 November 26 Posted November 26 · Report post Использование внутреннего генератора клока для конфига в качестве "медленного" клока для формирования больших задержек в дизайне для экономии ячеек плохая идея. Мало того что этот клок не на столько уж медленен что бы много сэкономить, так он еще и будет асинхронен к основному клоку(ам) вашего дизайна, и гуляет от температуры и вольтажа "+-километр". Да и вообще, идея экономии "на спичках" в "общем", без учёта конкретики дизайна плохо работает. В одном месте упоролись и сэкономили 7 "спичек"/ячеек, а в соседнем месте дизайна из за этой экономии потеряли целый ящик КЦ ... 1 Quote Share this post Link to post Share on other sites More sharing options...
dinam 1 November 27 Posted November 27 · Report post 15 часов назад, RobFPGA сказал: ... Вы совершенно правы. Но смотрите, Handbook Cyclone III имеет первую ревизию 2007г. А в AN 496: Using the Internal Oscillator Intel® FPGA IP Cyclone III впервые упоминается спустя 10! лет. Наверное, технически такая возможность имелась, но на фиг ни кому была не нужна из-за проблем с её применением. Но похоже всё кто-то нашелся, кому она пригодилась именно в FPGA (не CPLD) и он убедил Intel открыть и задокументировать такую возможность. Я так думаю, что лучше иметь возможность, но не использовать её, чем иметь необходимость, но не иметь возможности 😊 Quote Share this post Link to post Share on other sites More sharing options...
Plain 232 November 27 Posted November 27 · Report post В 21.11.2024 в 15:30, tems-ya сказал: В процессе подключения Ethernet контроллера W5500 к FPGA столкнулся с ситуацией, что данному чипу по феншую надо бы формировать ряд достаточно длинных задержек Нужность задержек отдельный вопрос, но какие с ними могут проблемы, когда эта ИС требует такты 25 МГц, или сама их даёт. Quote Share this post Link to post Share on other sites More sharing options...