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

Библиотека от Alex Forencich. Продукт или пример?

1 час назад, dxp сказал:

Ну, вот я так сделал сначала, всё просинтезировалось, ошибок нет. А потом констрейны применил и увидел, что тайминги не сходятся. Т.е. дизайн не рабочий. Фиксить это, подбирая экспериментально задержку на внешней микросхеме (речь про приём данных по RGMII)? Вслепую?

Я в своей практике сталкивался с возникновением проблем при передаче данных от FPGA на PHY; по приему от PHY на FPGA никогда проблем не было.

Если двигаем выходной клок на PLL, то да, констрейнты лучше писать, в этом полностью согласен. Ведь до конца нам не известно как будет проведен сигнал с PLL на ножку. Вполне возможно, что если не обконстрейнтить, то уедет фаза. В последнем проекте я это поленился сделать, скажу честно. Но это был макет на столе, просто для тестирования. Там у меня стабильно всё работало.

 

Чем удобно двигать клоки на самом PHY. Я могу ему указать, что у меня данные на выходе ПЛИС переключаются строго по фронту клока. И на выходных DDR регистрах я это обеспечу (с точностью до нескольких десятков пикосекунд). А дальше сам PHY сдвинет внутри себя клок на 180 градусов. То же самое и для приема на FPGA. Указываю PHY, чтобы он сдвинул свой выходной клок относительно данных на 180 градусов. На приеме на стороне FPGA в ножках регистры, задержки минимальны. Мне лично такой подход кажется удобным. Каких то проблем с ним никогда не было на практике.

 

p.s. поправка - конечно же сдвиг на 90, а не на 180

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


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

28 минут назад, gin сказал:

по приему от PHY на FPGA никогда проблем не было.

Тем не менее, приём сложнее -- тоньше: нужно входной внешний клок так завести внутрь, чтобы фазовые соотношения клока и данных не "сломались". Распространённый способ -- через PLL  в режиме компенсации. Но это не всегда используется. В частности, вот именно в этом примере у меня никаких PLL для этого не применяется, а всё разводится на специализированных примитивах: буферах и блоках задержки (ПЛИС позволяет. Так сделано из в корке Xilinx, так сделано и в обсуждаемой либе, только там не доделано). Это получается экономия ценного ресурса PLL и энергопотребления.

А PLL используется для формирования выходных сигналов -- чтобы клок внешний был задержан на 2 нс (90°) относительно данных. По спеке RGMII v2.0 предлагается делать именно так. Этот вариант поддерживают все PHY. Нет зависимости от возможностей PHY.

 

2 часа назад, gin сказал:

Ведь никто не гарантирует сто процентную работоспособность бесплатного кода, по доброй воле выложенного в интернете. Такие вещи можно использовать для прототипирования или макетирования. Для коммерческих изделий лучше писать самому.

Тем не менее существует немало свободно выложенных библиотек, имеющих вполне коммерческую годность. Особенно в мире традиционного софта. Например: https://github.com/fmtlib/fmt. Или тот же boost.

 

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


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

28 минут назад, dxp сказал:

Тем не менее, приём сложнее -- тоньше: нужно входной внешний клок так завести внутрь, чтобы фазовые соотношения клока и данных не "сломались". Распространённый способ -- через PLL  в режиме компенсации. Но это не всегда используется. В частности, вот именно в этом примере у меня никаких PLL для этого не применяется, а всё разводится на специализированных примитивах: буферах и блоках задержки (ПЛИС позволяет. Так сделано из в корке Xilinx, так сделано и в обсуждаемой либе, только там не доделано). Это получается экономия ценного ресурса PLL и энергопотребления.

Если я правильно понял, ваш подход в следующем:

1. Регистры в ножках не используете, все регистры внутри.

2. Констрейнтами задаете требуемое положение данных относительно клоков.

3. Исходя из требований, разводчик сам пробрасывает пути данных внутри ПЛИС от входов до регистров (и обратно), следя за выполнением констрейнтов.

 

Пожалуй, это более универсальный поход. Он не зависит от внешних микросхем

 

И тогда вопрос, насколько точно у разводчика получается выполнять констрейнты? 

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


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

12 минут назад, gin сказал:

Если я правильно понял, ваш подход в следующем:

Это не мой подход, а компании Xilinx.

12 минут назад, gin сказал:

1. Регистры в ножках не используете, все регистры внутри.

Неправильно. Регистры находятся внутри специальных примитивов IDDR, способных воспринимать DDR поток. Эти примитивы находятся в iOB.

А клок входной разводится через другие специальные примитивы -- клоковые буфера, для этого входящий клок должен быть заведён на специальный пин (Clock Capable Pin). Для тактирования IDDR используется BUFIO, а для регулярной логики -- BUFR. И вот тут, чтобы привести тайминги в норму и потребовалось вставить примитивы IDELAY, которые подключаются между пинами и IDDR. Для IDELAY нужно указать подходящее значение задержки (там они используются в режиме FIXED, т.е. со статической задержкой). Топология входных цепей этой ПЛИС такова, что позволяет получать стабильные тайминги, применяя такой подход (без PLL).

12 минут назад, gin сказал:

2. Констрейнтами задаете требуемое положение данных относительно клоков.

Нет. Констрейнами контролируется правильность таймингов при приёме данных на этих входных элементах. Если тайминги неверные, получаем ошибки от STA.

12 минут назад, gin сказал:

3. Исходя из требований, разводчик сам пробрасывает пути данных внутри ПЛИС от входов до регистров (и обратно), следя за выполнением констрейнтов.

Разводчик и синтезатор, к сожалению, не настолько умные. Хотя ничего не мешает им самостоятельно воткнуть элементы задержки с нужными значениями. Но даже это они не могут. 

 

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


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

On 8/1/2024 at 8:57 AM, dxp said:

Тут потребовалось поднимать RGMII (Xilinx 7-series), рассматривал разные варианты, в том числе вспомнил и про эту библиотеку. И по мере вникания в тему возник вопрос: а кто-нибудь реально что-то из этой библиотеки использовал? Каков успех?

Я использовал AXI, AXI-Stream и I2C.

Ethernet и PCIe мне показали немного "недоделанными", поэтому писал сам, точнее у меня уже была своя реализация под RGMII.

Собственно вот моя кроссплатформенная реализация MAC для RGMII.

eth_mac_rgmii.7z lib.7z

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


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

Вот ещё MDIO до кучи.

P.S.

Для MAC я обычно ставил IDELAY_VALUE = 10.

На Artix-7 этого было достаточно чтобы setup был порядка -1.0 нс.

Констрейны при этом были:

create_clock -period 7.200 -name {RXC_VIRTUAL}
create_clock -period 7.200 -name {RXC} [get_ports {eth_rxc}]


set_false_path -rise_from [get_clocks {RXC_VIRTUAL}] -rise_to [get_clocks {RXC}]
set_false_path -fall_from [get_clocks {RXC_VIRTUAL}] -fall_to [get_clocks {RXC}]


set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -max  0.500 [get_ports {eth_rx_ctl}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -min -0.500 [get_ports {eth_rx_ctl}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -clock_fall -max -add_delay  0.500 [get_ports {eth_rx_ctl}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -clock_fall -min -add_delay -0.500 [get_ports {eth_rx_ctl}]

set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -max  0.500 [get_ports {eth_rd[0]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -min -0.500 [get_ports {eth_rd[0]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -clock_fall -max -add_delay  0.500 [get_ports {eth_rd[0]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -clock_fall -min -add_delay -0.500 [get_ports {eth_rd[0]}]

set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -max  0.500 [get_ports {eth_rd[1]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -min -0.500 [get_ports {eth_rd[1]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -clock_fall -max -add_delay  0.500 [get_ports {eth_rd[1]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -clock_fall -min -add_delay -0.500 [get_ports {eth_rd[1]}]

set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -max  0.500 [get_ports {eth_rd[2]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -min -0.500 [get_ports {eth_rd[2]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -clock_fall -max -add_delay  0.500 [get_ports {eth_rd[2]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -clock_fall -min -add_delay -0.500 [get_ports {eth_rd[2]}]

set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -max  0.500 [get_ports {eth_rd[3]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -min -0.500 [get_ports {eth_rd[3]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -clock_fall -max -add_delay  0.500 [get_ports {eth_rd[3]}]
set_input_delay -clock [get_clocks {RXC_VIRTUAL}] -clock_fall -min -add_delay -0.500 [get_ports {eth_rd[3]}]

7.2 нс это период клока от PHY с учётом возможного гуляния фронтов при восстановлении клока - ставим самый худший случай.

eth_mdio.7z

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


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

3 часа назад, BSACPLD сказал:

Для MAC я обычно ставил IDELAY_VALUE = 10.

На Artix-7 этого было достаточно чтобы setup был порядка -1.0 нс.

Видимо, это зависит от задержки клока относительно данных от PHY. У моего нынешнего в доке указано 1.2 нс. Соответственно, задержку IDELAY подобрал: 15. Мой файл констрейнов:

# Rx

create_clock      -name rgmii_rxclk -period 8
create_clock -add -name rgmii_rxc   -period 8 [get_ports rgmii_rxc]

set rxclk [get_clocks -include_generated_clocks -of [get_ports rgmii_rxc]]

set_input_delay -clock [get_clocks rgmii_rxclk] -max -1.5 [get_ports {rgmii_rxd[*] rgmii_rxctl}]
set_input_delay -clock [get_clocks rgmii_rxclk] -min -2.8 [get_ports {rgmii_rxd[*] rgmii_rxctl}]
set_input_delay -clock [get_clocks rgmii_rxclk] -clock_fall -max -1.5 -add_delay [get_ports {rgmii_rxd[*] rgmii_rxctl}]
set_input_delay -clock [get_clocks rgmii_rxclk] -clock_fall -min -2.8 -add_delay [get_ports {rgmii_rxd[*] rgmii_rxctl}]

set_false_path -rise_from [get_clocks rgmii_rxclk] -fall_to ${rxclk} -setup
set_false_path -fall_from [get_clocks rgmii_rxclk] -rise_to ${rxclk} -setup
set_false_path -rise_from [get_clocks rgmii_rxclk] -rise_to ${rxclk} -hold
set_false_path -fall_from [get_clocks rgmii_rxclk] -fall_to ${rxclk} -hold

set_multicycle_path -from [get_clocks rgmii_rxclk] -to ${rxclk} -setup 0
set_multicycle_path -from [get_clocks rgmii_rxclk] -to ${rxclk} -hold -1

set_property IDELAY_VALUE  "15"   [get_cells -hier -filter {name =~ *rgmii/*idelay_rxd*}   ]
set_property IDELAY_VALUE  "15"   [get_cells -hier -filter {name =~ *rgmii/*idelay_rxctl*} ]
set_property IODELAY_GROUP "gpr1" [get_cells -hier -filter {name =~ *rgmii/*idelay_rxd*}   ]
set_property IODELAY_GROUP "gpr1" [get_cells -hier -filter {name =~ *rgmii/*idelay_rxctl*} ]
set_property IODELAY_GROUP "gpr1" [get_cells -hier -filter {name =~ *rgmii/*idelayctrl*}   ]


# Tx

create_generated_clock -add -name rgmii_txclk -divide_by 1 \
                       -source [get_pins -of [get_cells -hier -filter {name =~ *txc_oddr}] -filter {name =~ *C}] \
                       -master_clock [get_clocks -of_objects [get_nets gmii_clk90]] [get_ports rgmii_txc]

set_output_delay  0.75 -max -clock [get_clocks rgmii_txclk] [get_ports {rgmii_txd[*] rgmii_txctl}]
set_output_delay -0.7  -min -clock [get_clocks rgmii_txclk] [get_ports {rgmii_txd[*] rgmii_txctl}]
set_output_delay  0.75 -max -clock [get_clocks rgmii_txclk] [get_ports {rgmii_txd[*] rgmii_txctl}] -clock_fall -add_delay
set_output_delay -0.7  -min -clock [get_clocks rgmii_txclk] [get_ports {rgmii_txd[*] rgmii_txctl}] -clock_fall -add_delay

set_property slew FAST [get_ports [list {rgmii_txd[3]} {rgmii_txd[2]} {rgmii_txd[1]} {rgmii_txd[0]} rgmii_txc rgmii_txctl]]

set_false_path -to [get_ports rgmii_txc]

 

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


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

23 часа назад, dxp сказал:

Это не мой подход, а компании Xilinx.

Понятно, спасибо. Значит это не универсальный вариант. Как быть с Альтерой, или вообще со специфическими 'китайцами'?

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


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

А тут, имхо, универсальных вариантов быть не может -- всё упирается в поддержку этой темы со стороны ПЛИС. Есть ПЛИС, где вообще не получится завести вот такой source-synchronous поток на таких частотах. Наиболее универсальный метод: использование PLL в режиме с компенсацией задержки прохождения клока, Xilinx его тоже поддерживает, но он дороже, поэтому в данном случае ни к чему, раз есть другая, более дешёвая, возможность.

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


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

15 minutes ago, dxp said:

А тут, имхо, универсальных вариантов быть не может -- всё упирается в поддержку этой темы со стороны ПЛИС. Есть ПЛИС, где вообще не получится завести вот такой source-synchronous поток на таких частотах. Наиболее универсальный метод: использование PLL в режиме с компенсацией задержки прохождения клока, Xilinx его тоже поддерживает, но он дороже, поэтому в данном случае ни к чему, раз есть другая, более дешёвая, возможность.

Не совсем согласен.

Метод с входной задержкой был успешно применён на Altera (Cyclone II, IV E, Stratix III), Xilinx (Artix-7, Kintex-7), Lattice (ECP5), Fudan (JFMK50T4) и PangoMicro (Logos2).

Единственное, где не прокатило, это Gowin, но там всё уперлось в максимальную частоту проекта (больше 80МГц не удалось вытянуть), а не в задержки.

При этом единственное различие, это примитивы и конкретные значения задержки.

Я просто оборачивал все примитивы во враппер - см. MAC что я выкладывал в этой теме.

А с PLL могут быть проблемы, т.к. при изменении скорости падает частота клока - не факт, что PLL будет корректно работать на частоте отличной от указанной при генерации IP блока.

На 2.5МГц точно не будет работать, но с другой стороны кто сейчас применяет 10 Мбит/с?...

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


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

17 минут назад, BSACPLD сказал:

Не совсем согласен.

Метод с входной задержкой был успешно применён на Altera (Cyclone II, IV E, Stratix III), Xilinx (Artix-7, Kintex-7), Lattice (ECP5), Fudan (JFMK50T4) и PangoMicro (Logos2).

Как, например, насчёт MAX V (у которого нет регистров в IOB)?

И речь идёт про RGMII, т.е. 125 МГц, по обоим фронтам, т.е. 4 нс смена данных. MII какой-нить о 25 МГц без всяких извратов заводится как угодно без привязки к особенностям конкретной ПЛИС, там тайминги позволяют.

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


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

3 hours ago, dxp said:
4 hours ago, BSACPLD said:

Не совсем согласен.

Метод с входной задержкой был успешно применён на Altera (Cyclone II, IV E, Stratix III), Xilinx (Artix-7, Kintex-7), Lattice (ECP5), Fudan (JFMK50T4) и PangoMicro (Logos2).

Как, например, насчёт MAX V (у которого нет регистров в IOB)?

Так у Cyclone II, IV E тоже нет входных DDR регистров.

Но есть статическая задержка.

И метод с задержкой там прекрасно работал на 125 МГц, только я задерживал клок, а не данные.

Хотя в случае MAX V и входной задержки нет.

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


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

4 часа назад, dxp сказал:

Как, например, насчёт MAX V (у которого нет регистров в IOB)?

Max V - это всё же CPLD, там даже блочной памяти нет. Наверное, это не лучший вариант для работы по Ethernet. Но при желании, ее можно подключить по GMII, т.е. 8 битная шина без DDR. Кстати, это еще один момент, почему для MAC-ядра не обязательны констрейнты. Ведь один и тот же gigabit MAC можно подключать как по RGMII, так и просто по GMII, если такое PHY позволяет. То есть MAC - это уже про логику работы, а входы/выходы - это тонкости архитектуры конкретной ПЛИС. Они описываются и констрейнтятся отдельно.  А ведь есть еще и последовательный SGMII. Он вообще по-другому подключается. Там даже служебные слова, такие как преамбула и идлы - они другие.

Конечно же это мой субъективный взгляд. Не для спора, а для обсуждения и обмена опытом.

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


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

15 часов назад, BSACPLD сказал:

Так у Cyclone II, IV E тоже нет входных DDR регистров.

Речь не про DDR, а про просто наличие регистров в IOB, без которых с жёсткими таймингами бороться тяжело, если вообще возможно. У Cyclone iV E разве нет? Выходные DDR точно есть -- я через atlddio выходной клок формировал для SDRAM контроллера. 

15 часов назад, gin сказал:

Max V - это всё же CPLD

Технически это FPGA. Как и MAX II. Не помню, чья архитектура внутри MAX V, а у MAX II внутри Cyclone I обрезанный -- без блоков памяти и регистров в IOB.

Я имел в виду, что не все ПЛИС обладают необходимой аппаратурой внутри для реализации входных source-synchronous интерфейсов на 100+ МГц.

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


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

7 hours ago, dxp said:

У Cyclone iV E разве нет?

Выходные - есть. Входные - нет.

Входные DDIO эмулируются на логике.

image.thumb.png.8a419242f23d8e3d7c838a61f2ba0945.png

image.thumb.png.7b2ee2d41fe340019b8d44e94f6c9f24.png

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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