gin 0 7 августа Опубликовано 7 августа · Жалоба 1 час назад, dxp сказал: Ну, вот я так сделал сначала, всё просинтезировалось, ошибок нет. А потом констрейны применил и увидел, что тайминги не сходятся. Т.е. дизайн не рабочий. Фиксить это, подбирая экспериментально задержку на внешней микросхеме (речь про приём данных по RGMII)? Вслепую? Я в своей практике сталкивался с возникновением проблем при передаче данных от FPGA на PHY; по приему от PHY на FPGA никогда проблем не было. Если двигаем выходной клок на PLL, то да, констрейнты лучше писать, в этом полностью согласен. Ведь до конца нам не известно как будет проведен сигнал с PLL на ножку. Вполне возможно, что если не обконстрейнтить, то уедет фаза. В последнем проекте я это поленился сделать, скажу честно. Но это был макет на столе, просто для тестирования. Там у меня стабильно всё работало. Чем удобно двигать клоки на самом PHY. Я могу ему указать, что у меня данные на выходе ПЛИС переключаются строго по фронту клока. И на выходных DDR регистрах я это обеспечу (с точностью до нескольких десятков пикосекунд). А дальше сам PHY сдвинет внутри себя клок на 180 градусов. То же самое и для приема на FPGA. Указываю PHY, чтобы он сдвинул свой выходной клок относительно данных на 180 градусов. На приеме на стороне FPGA в ножках регистры, задержки минимальны. Мне лично такой подход кажется удобным. Каких то проблем с ним никогда не было на практике. p.s. поправка - конечно же сдвиг на 90, а не на 180 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 7 августа Опубликовано 7 августа · Жалоба 28 минут назад, gin сказал: по приему от PHY на FPGA никогда проблем не было. Тем не менее, приём сложнее -- тоньше: нужно входной внешний клок так завести внутрь, чтобы фазовые соотношения клока и данных не "сломались". Распространённый способ -- через PLL в режиме компенсации. Но это не всегда используется. В частности, вот именно в этом примере у меня никаких PLL для этого не применяется, а всё разводится на специализированных примитивах: буферах и блоках задержки (ПЛИС позволяет. Так сделано из в корке Xilinx, так сделано и в обсуждаемой либе, только там не доделано). Это получается экономия ценного ресурса PLL и энергопотребления. А PLL используется для формирования выходных сигналов -- чтобы клок внешний был задержан на 2 нс (90°) относительно данных. По спеке RGMII v2.0 предлагается делать именно так. Этот вариант поддерживают все PHY. Нет зависимости от возможностей PHY. 2 часа назад, gin сказал: Ведь никто не гарантирует сто процентную работоспособность бесплатного кода, по доброй воле выложенного в интернете. Такие вещи можно использовать для прототипирования или макетирования. Для коммерческих изделий лучше писать самому. Тем не менее существует немало свободно выложенных библиотек, имеющих вполне коммерческую годность. Особенно в мире традиционного софта. Например: https://github.com/fmtlib/fmt. Или тот же boost. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gin 0 7 августа Опубликовано 7 августа · Жалоба 28 минут назад, dxp сказал: Тем не менее, приём сложнее -- тоньше: нужно входной внешний клок так завести внутрь, чтобы фазовые соотношения клока и данных не "сломались". Распространённый способ -- через PLL в режиме компенсации. Но это не всегда используется. В частности, вот именно в этом примере у меня никаких PLL для этого не применяется, а всё разводится на специализированных примитивах: буферах и блоках задержки (ПЛИС позволяет. Так сделано из в корке Xilinx, так сделано и в обсуждаемой либе, только там не доделано). Это получается экономия ценного ресурса PLL и энергопотребления. Если я правильно понял, ваш подход в следующем: 1. Регистры в ножках не используете, все регистры внутри. 2. Констрейнтами задаете требуемое положение данных относительно клоков. 3. Исходя из требований, разводчик сам пробрасывает пути данных внутри ПЛИС от входов до регистров (и обратно), следя за выполнением констрейнтов. Пожалуй, это более универсальный поход. Он не зависит от внешних микросхем И тогда вопрос, насколько точно у разводчика получается выполнять констрейнты? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 7 августа Опубликовано 7 августа · Жалоба 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. Исходя из требований, разводчик сам пробрасывает пути данных внутри ПЛИС от входов до регистров (и обратно), следя за выполнением констрейнтов. Разводчик и синтезатор, к сожалению, не настолько умные. Хотя ничего не мешает им самостоятельно воткнуть элементы задержки с нужными значениями. Но даже это они не могут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BSACPLD 14 7 августа Опубликовано 7 августа · Жалоба 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BSACPLD 14 7 августа Опубликовано 7 августа · Жалоба Вот ещё 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 8 августа Опубликовано 8 августа · Жалоба 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] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gin 0 8 августа Опубликовано 8 августа · Жалоба 23 часа назад, dxp сказал: Это не мой подход, а компании Xilinx. Понятно, спасибо. Значит это не универсальный вариант. Как быть с Альтерой, или вообще со специфическими 'китайцами'? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 8 августа Опубликовано 8 августа · Жалоба А тут, имхо, универсальных вариантов быть не может -- всё упирается в поддержку этой темы со стороны ПЛИС. Есть ПЛИС, где вообще не получится завести вот такой source-synchronous поток на таких частотах. Наиболее универсальный метод: использование PLL в режиме с компенсацией задержки прохождения клока, Xilinx его тоже поддерживает, но он дороже, поэтому в данном случае ни к чему, раз есть другая, более дешёвая, возможность. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BSACPLD 14 8 августа Опубликовано 8 августа · Жалоба 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 Мбит/с?... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 8 августа Опубликовано 8 августа · Жалоба 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 МГц без всяких извратов заводится как угодно без привязки к особенностям конкретной ПЛИС, там тайминги позволяют. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BSACPLD 14 8 августа Опубликовано 8 августа · Жалоба 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 и входной задержки нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gin 0 8 августа Опубликовано 8 августа · Жалоба 4 часа назад, dxp сказал: Как, например, насчёт MAX V (у которого нет регистров в IOB)? Max V - это всё же CPLD, там даже блочной памяти нет. Наверное, это не лучший вариант для работы по Ethernet. Но при желании, ее можно подключить по GMII, т.е. 8 битная шина без DDR. Кстати, это еще один момент, почему для MAC-ядра не обязательны констрейнты. Ведь один и тот же gigabit MAC можно подключать как по RGMII, так и просто по GMII, если такое PHY позволяет. То есть MAC - это уже про логику работы, а входы/выходы - это тонкости архитектуры конкретной ПЛИС. Они описываются и констрейнтятся отдельно. А ведь есть еще и последовательный SGMII. Он вообще по-другому подключается. Там даже служебные слова, такие как преамбула и идлы - они другие. Конечно же это мой субъективный взгляд. Не для спора, а для обсуждения и обмена опытом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 9 августа Опубликовано 9 августа · Жалоба 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+ МГц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BSACPLD 14 9 августа Опубликовано 9 августа · Жалоба 7 hours ago, dxp said: У Cyclone iV E разве нет? Выходные - есть. Входные - нет. Входные DDIO эмулируются на логике. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться