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

Читая даташиты на ПЛИС, можно находить таблички об их рабочих частотах…

Хотя нет, история начинается еще с 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;

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 24

    +1

    У меня проблемы с картинками, они отображаются так: https://i.imgur.com/QYxaqM3.png
    Когда я пробую посмотреть в другой вкладке, сайт не найдено. Положите на hsto)

      0

      Завтра обязательно исправлю.

      +1

      А почему за генерацию клока на счётчике (я так понимаю, это банальное деление частоты внешнего клока?) ругали?


      Насчёт генерации "внутри", как в статье:


      1. Не было желания в петлю воткнуть цепочку из нескольких инверторов или повторителей? Просто чтобы гарантировать, что "генератор" не переклинит в каком-нибудь метастабильном состоянии.
      2. Зависимость частоты от температуры не смотрели?
        0

        На сегодняшний момент уже не вспомню причин почему ругали за кривой клок.
        Да, я хотел сгенерировать клок из последовательно соединенных элементов, но возможно это уже другая статья будет в которой можно учесть воздействие температуры :)

        0
        А какая цель этих манипуляций? Независимость от вендора/платформы?

        Как я понимаю этот вопрос, за формирование тактовой частоты отвечает специфический аналоговый компонент (PLL). И когда вы будете переносить дизайн с FPGA на ASIC, вам всё равно придётся копаться в вендорском решении, ну, только предоставлять его будет фабрика, а не производитель FPGA. Так что лучше заранее приготовиться к тому, что генерация частот зависит от платформы. Вынести её в отдельный исходный файл, что ли.
          0

          Я в статье написал что цель сгенерировать частоту на примитивах. В принципе я понимаю что у каждого примитива своя частота задержки. Но хотел посмотреть на это нагляднее и остальным показать.

          0

          Картинки, кроме фоток плат не открываются

            0

            Постараюсь завтра исправить.

            0
            Я тоже для прикола замыкал вход «инвертора» на выход внутри Arria2 GX, частота получалась около 1ГГц. Но она была совершенно не юзабельная, а вот когда я её поделил на 2 простым счётным триггером, то уже на 500МГц работал тестовый проект, заполняющий кристалл почти на 95%. Вот только с термостабильностью у него была беда, согласен. Плавала от примерно 550МГц до 480МГц. Измерения примерные т.к. измерял поделённую частоту.
              +2

              Норм. Хотя частота более 11 ГГц выглядит результатом гонок, а не работы мультиплексора.
              Но "анакуа"? Арриям, Виртексам и прочим "топовым" кристаллам никуда не впёрлись такие дрянные источники частоты. А у кристаллов типа "как-бы продвинутая CPLD" (MAX X) и так есть встроенный RC(?) генератор и, вроде, относительно стабильный.

                +1
                1. Может быть полезено при разработке ГСЧ.
                2. Как внутренний, резервный независимый генератор, т.к. внешний может выйти из строя, его могут отключить или манипулировать его частотой. Можно асинхронно переключиться на него в случае ЧП и тактировать им некую аварийную логику, которая сделает что-то полезное.
                3. Предполагаю, что подобные схемы можно использовать как дополнительный способ защиты от атак по питанию.
                  +1

                  Пункты 1 и 3. Предполагаю, что как раз с питанием такой генератор будет скоррелирован очень сильно.


                  Пункт 2. Если у злоумышленника есть доступ к Вашему железу, то ПЛИСке останется только пошире раздвинуть… выводы.


                  Всё — на уровне КМК.

                    0
                    Пункты 1 и 3. Предполагаю, что как раз с питанием такой генератор будет скоррелирован очень сильно.
                    Безусловно будет корреляция с питанием, но не только с ним, фактически PVT зависимость (process.voltage.temperature). Но наличие подобной корреляции не означает, что вы сможете точно предсказать состояние генератора. Да, как ГСЧ сам по себе такой генератор будет плох, но очень полезен как подсистема для усиление ГСЧ или дешевое средство для усложнения атаки по питанию.

                    Если у злоумышленника есть доступ к Вашему железу, то ПЛИСке останется только пошире раздвинуть… выводы.
                    Вот тут я бы не сдавался, есть ещё за что побороться. У xilinx в 7 семействе есть возможность изнутри ПЛИС стереть энергозависимую память на батарейке, в которой хранится ключ битстрима, тем самым окирпичить девайс. А, кажется, в ultrascale есть даже возможность писать в эту память (разумеется, без возможности чтения) изнутри ПЛИС, что открывает ещё более интересные возможности.
                0
                Если не секрет, все эти эксперименты — вы так развлекаетесь со старением кремния и PUF-ами?

                примитивы имеют разную задержку работы в зависимости от расположения

                Но здесь есть нюансы, вы всё же имеете некоторый контроль (пусть и неполный) над расположением. Это достигается с помощью физических констрейнтов: можно ведь указать какой именно элемент выбрать (координаты и т.д.). Если глянете гайды по клоковым ресурсам, то сможете найти и критерий выбора — поближе к клоковым буферам, а вот чего наверно всё же не сможете контролировать, так это выбор конкретной линии к нему, впрочем, там наверно можно констрейнт по времянкам потуже навернуть.

                По поводу LUT в Spartan-e, а вы ведь пробовали примитивы из Language Templates?

                По поводу влияния температуры вопросы тоже остаются.
                  0
                  Да, я пробовал примитивы из Language Templates, параллельно заглядывая в «Spartan-6 Libraries Guide for HDL Designs(UG615)»
                  +2
                  Ваши мега эксперименты попахивают филькиной грамотой. Не могут компоненты ПЛИС работать нормально на частотах выше 1ГГц (да и гигагерц — это почти фантастика), а то что у Вас получилось — это просто шум в кремние с «какой-то» фильтрацией, подогнанной для получения результатов высосанных с пальца.
                  И причина то не в глупости, а упрямстве скорее. Если бы Вы послушали знающих людей, они бы Вам рассказали, насколько шумит Ваш синтетический клок, какие методики есть устранения этого шума, а также показали вам вот такой документ для Kintex, где чёрным-по-белому написано, что максимальная частота работы единичного слайса (CPL), включительно FF, как составляющих, не может быть выше 5.5 ГГц (Setup + Hold), но при этом нужно учитывать время на Рутинг, который в Вашем случае произошёл как попало. С того же документа, можно выяснить, что максимальное время переключения мультиплексора порядка 0,4 нс — а это не более 2,5 ГГц рабочей частоты.
                  Если же заглянуть в документацию по Virtex-5, так там в табличке на с.28 и вовсе указаны максимальные рабочие частоты для компонентов, которые не превышают даже 500 МГц. Соответственно как у Вас получились фантастические измерения выше гигагерцов, при максимальных рабочих частотах кристалла до полугигагерца остаётся загадкой.
                  И это не говоря, про разброс в температурных режимах, про то, какой skew фронта у полученного «клока», про его джиттер (тут вообще страшно представить что творится) и шум.
                  Это написано не для оскорбления, но для того чтобы побудить автора разобраться что такое setup/hold флип-флопа, базовые принципы routing'а и фиксации проекта на floorlan, трассировки и констрейнов.
                  Дабы комментарий не показался голословным, у меня имеется проект по детектированию частот порядка 1.2 ГГц (расчётно) с внешнего источника, который реальную точность выдаёт не более 800-900 МГц. И схемы там накручены похлеще вашего счётчика (32-бит!!! ЗАЧЕМ? КАК?) с очень медленным компаратором и комбинационным сложением (для Xilinx есть сложение через CSA — намного менее ресурсоёмкое и быстрое).
                    0
                    В принципе вы правы, то что я сделал и показал не до конца проработано(в заключении я об этом сказал). Если вы знаете как провести подобные измерения в моих условиях, то говорите я попытаюсь их реализовать. Я за точные измерения.
                      0
                      Выполнить точные измерения реально, но зачем? Как эксперимент на коленке с вкраплениями «ненормального программирования» этого достаточно. Как реальный проект для конкретных задач… лучше не стоит себя обнадёживать. Да, такие схемы работоспособны как делитель при правильных констрейнах, но не более.
                      Что действительно важно, повторюсь, это понять принципы работы констрейнов, занятся floorplan'ом и зафиксировать синтезированную схему (можно жёстко, можно по partition'ам), а также написать сопутствующие констрейны.
                      Когда Вы добьётесь 100% повторяемости эксперимента для разных конфигураций и с различными компонентами (как часто бОльшего проекта или дублирование текущего в 3-4 местах), тогда вы пройдёте половину нужного пути.
                      Дальше придётся разобраться на каких примитивах это всё построено, почему на них и как они работают. Чем отличается DSP от сумматора на LUT'ах и т.п. Также рекомендую уменьшить разрядность счётчика до адекватного. Реально контролировать изменения в 20-50 единиц не требует 2^32 счётчика. Оно и места занимает и частоту садит.
                      Что же касается ответа на вопрос «как провести подобные измерения в Ваших условиях» дам подсказку и если будет желание можете попробовать решить: Вам нужно построить схему детектирования, которая будет работать на порядки быстрее анализируемого компонента. тогда с точностью этого порядка Вы сможете вычислить реальную генерированную частоту. По сути нужно погуглить фразу «time to digital converter», которая внесёт кое-какую ясность.
                    0

                    Вопрос автору: я правильно понимаю, что внутри плис счетчики, на которых вы считаете гигагерцы, отрабатывают счет на данной частоте безо всяких проблем?

                      0
                      Плохо понял вопрос. проверку работоспособность счетчиков на гигагерцах не проверял
                        0
                        Частота на луте: 5761.1 МГц

                        Вы подаете этот сигнал на счетчик, что бы вы числить эту частоту. Значит счетчик считает эту частоту безо всяких проблем?
                          0
                          Я на это надеюсь) но в любом случае я запускал несколько раз и в среднем получал этот результат.
                            0
                            Я вот сильно в этом сомневаюсь. А проверить просто: подайте на этот счетчик сигнал с выхода PLL/MMCM и постепенно увеличивайте частоту. В какой то момент он должен начать врать. Я видел в доках Xilinx на 7й Kintex передельные значения частот для счетчиков — там были значения заметно ниже 1ГГц (что то около 700МГц, точно не помню).
                      0
                      Хмммм, когда мне китайская плисина прийдет, тоже надо будет попробовать, интересно стало.

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

                      Самое читаемое