Русский
Русский
English
Статистика
Реклама

Генерация тактового сигнала

Из песочницы Генерация клока в ПЛИС на примитивах

05.07.2020 14:08:58 | Автор: admin
Читая даташиты на ПЛИС, можно находить таблички об их рабочих частотах

Хотя нет, история начинается еще с 2015 года, когда я познакомился с ПЛИС. В своих первых простеньких работах я формировал нужный мне клок из счетчика и запитывал от него всю логику(естественно при условии что клок мне нужен медленнее чем подавался на ПЛИС, например UART и SPI). Естественно за такое меня гоняли, но у меня была простая отмазка но ведь работает же!, и действительно все работало. С тех пор у меня в голове закралась мысль а откуда вообще можно взять тактирующий сигнал?.

Вариантов источников взять клок не много. Либо взять из некого ClockWizard основанный на PLL или MMCM, либо сформировать из счетчика, либо сразу с ножки так сказать single ended. А что, если взять тактовый сигнал сформированный примитивом ПЛИС?

В рамках этой статьи я решил рассмотреть три варианта: мультиплексор(MUXF7), таблица истинности(LUT1) и замкнуть ножки ПЛИС сами на себя.

В случае с мультиплексором выход подаем на управляющий сигнал, а входные сигналы притягиваем к 0 и 1.

image

В случае с LUT замыкаем выход на вход и задаем инвертирующую таблицу истинности. При подаче 1 выдавать ноль, а при 0 выдавать единицу.

image

В случае с GPIO там все просто, выходному сигналу присваиваем инверсию входного:
assign s2 = ~s1;

Цель эксперимента: сгенерировать частоту тремя способами и замерить ее.
Измерять частоту будем за счет счетчиков. Будет 4 счетчика: три на каждый вариант и один счетчик базовый, относительно которого все будет считаться. А смотреть эти счетчики будем через ChipScope.

А вот собственно весь код модуля:
module gen_clk(    input clk_base,    input s1, //gpio    output s2 //gpio    );//счетчик на входных-выходных контактахassign s2 = ~s1;wire clk_gpio = s1;reg [31:0] cnt_gpio = 0; (* MARK_DEBUG="true" *) reg [31:0] cnt_gpio_buf = 0;always@(posedge clk_gpio)begin     if(cnt_gpio[2:0]==3'd0) cnt_gpio_buf<=cnt_gpio;     cnt_gpio <= cnt_gpio + 1'b1;end//счетчик на мультиплексореwire clk_mux;MUXF7 MUXF7_inst(    .O(clk_mux),    .I0(1'b1),    .I1(1'b0),    .S(clk_mux));reg [31:0] cnt_mux = 0; (* MARK_DEBUG="true" *) reg [31:0] cnt_mux_buf = 0;always@(posedge clk_mux)begin     if(cnt_mux[2:0]==3'd0) cnt_mux_buf<=cnt_mux;     cnt_mux <= cnt_mux + 1'b1;end//счетчик на одном лутеwire clk_lut;LUT1#(    .INIT(2'b01))LUT1_inst(    .O(clk_lut),    .I0(clk_lut));reg [31:0] cnt_lut = 0; (* MARK_DEBUG="true" *) reg [31:0] cnt_lut_buf = 0;always@(posedge clk_lut)begin     if(cnt_lut[2:0]==3'd0) cnt_lut_buf<=cnt_lut;     cnt_lut <= cnt_lut + 1'b1;end//базовый счетчик относительно которого будем считать     (* MARK_DEBUG="true" *) reg [31:0] cnt_base = 'd0;        always@(posedge clk_base)begin    cnt_base <= cnt_base + 1'b1;end       endmodule


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

image


Практическая часть

В моем распоряжении есть три платы:

  1. KC705 Evaluation Kit

    image

  2. ML507 Evaluation Kit

    image

  3. Китайская плата Spartan-6 XC6SLX16

    image

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


И так теперь собственно результаты


Kintex-7:

Так как проект начинал делать под него, то и проект был написан не сразу целиком, а поэтапно. Сначала подключил один LUT добавил сигналы в отладку и стал смотреть.

Базовый счетчик тактируется на 200 МГц, поэтому посчитать частоту клока сгенерированного на луте не сложно, во сколько раз больше дельта счетчика лута дельты базового счетчика за одно и тоже время, во столько раз больше его частота. В данном случае: получается частота генерируемая лутом 381.55 МГц.

image

Теперь к проекту добавим мультиплексор, и по аналогии как с одним лутом посчитаем частоту для него, ну и для лута (должно ведь что-то поменяться).

image

Первое на что бросается взгляд это на то, как сильно дребезжит счетчик. Это сказывается огромная частота мультиплексора, но в целом видно, что счетчик идет по нарастающей, а это значит, что его тоже можно взять и посчитать. В итоге:

  • Частота на мультиплексоре: 5953.89 МГц
  • Частота на луте(изменилась): 379.98 МГц

Ну и на конец добавим к проекту замкнутую петлю из пары GPIO. На плате KC705 есть SMA разъемы J13 и J14. Вот их то я и замкнул проводником длиной примерно 10 см. В результате:

  • Частота на GPIO: 90.59 МГц
  • Частота на мультиплексоре: 12994.13 МГц
  • Частота на луте: 380.18 МГц

Заменим, эксперимента ради, проводник на более длинный, у меня имеется провод в два раза длиннее. В итоге частота упала до 85.29 МГц.

На данном этапе эксперимента можно отметить, что частота работы примитивов в ПЛИС не одинаковая. В случае, когда был только один лут то синтезатор выбрал самый быстрый лут и строил вокруг него схему, затем когда добавился мультиплексор синтезатор попытался найти ту супер позицию где и лут и мультиплексор работают максимально быстро, а это уже другие элемента и частоты уже медленнее. Когда добавились внешние пины то весь проект на кристалле в принципе передислоцировался к этим ножкам и проект стал синтезироваться на близ лежащих элементах, по какой-то причине в том месте частоты лута и мультиплексора заметно выросли, но не стоит забывать что на фоне всего этого к проекту подключён ChipScope глубиной 1024 и шиной данных от 64 до 128(от проекта к проекту меняется). Теперь перейдем к следующей плате.

Virtex-5:

Я не стал проходить весь путь что прошел с предыдущей платой, сразу добавил все 3 варианта генерации клока и посмотрел в ChipScope что получилось.

image

На рисунке видны две метки Х и О. А так же их значения в столбцах, формат чисел беззнаковый десятичный. Стоит отметить, что базовый счетчик теперь считает на частоте 100 МГц. И так результат:

  • Частота на GPIO: 96.34 МГц
  • Частота на мультиплексоре: 614.41 МГц
  • Частота на луте: 5761.1 МГц

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

А теперь последний вариант с китайской платой.

Spartan-6:

В ChipScope появилось два базовых счетчика, на самом деле это один и тот же счетчик просто не хотел перенастраивать ChipScope. В данном проекте базовый счетчик тактируется на частоте 50 МГц.

image

В случае с этой платой все получилось гораздо сложнее. Во-первых, проект никак не хотел синтезироваться в том виде что за синтезировался в предыдущий вариантах. Во-вторых, в итоге пришлось выкинуть LUT, пытался его заменить на пятивходовый но тоже ни чего не дало. В общем вот результаты:

  • Частота на GPIO: 51.77 МГц
  • Частота на мультиплексоре: 3 490 504 МГц
  • Частота на луте: не получилось собрать

Результаты, в исполнении этой платы, оказались совсем уж не радостные, и не только потому что лут не получилось использовать в качестве клока, но и из-за неимоверно огромной частоты мультиплексора. Что касательно клока генерируемого на ножках, то был использован проводник порядка 25-30 см, на конце замкнутый проволочкой, наверняка там образовались паразитные емкости и индуктивности которые и оказали свое влияние на генерацию клока.

Заключение

В целом, получилось сгенерировать тактовые сигналы на различных примитивах, а так же получилось увидеть(на примере Kintex-7), что примитивы имеют разную задержку работы в зависимости от расположения. От себя хочу добавить, что не считаю проведённый эксперимент полностью корректным, например не рассчитывалась разрядность счетчиков, не учитывался перенос сигнала из разных клоковых доменов(хотя я сделал чтобы сигнал в буфере держался несколько тактов), сам ChipScope в идеале нужно убрать и найти другой способ анализировать генерируемую частоту.

Встретившиеся проблемы:
В ходе эксперимента синтезаторы Vivado и ISE ругались на комбинаторные петли, и трудности развода сигналов. Эти трудности решаются добавлением парой строк в констрейн:

  • set_property ALLOW_COMBINATORIAL_LOOPS TRUE [get_nets -of_objects [get_cells gen_clk_inst/LUT1_inst]]
  • NET s1 CLOCK_DEDICATED_ROUTE = FALSE;

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru