Визуальная электроника

Сегодня использование устройств на ПЛИС с сетью Ethernet – обычное явление. Особенно если речь идёт о высокоскоростной передачи данных (АЦП/ЦАП с сетевым выходом, обработка видео, «сырца» с радиолокаторов и гидроакустических комплексов, сбора данных с большой сети (решётки датчиков и т.д. и т.п.). Когда я вижу, как люди, покрывшись испариной, пытаются упихать поток отсчётов с квадратурного демодулятора SDR в USB 3.0, мне их становится откровенно жалко. Напомним, наша новая отладочная плата VE-10CL025 имеет встроенный сетевой интерфейс 1 Гбит. В этой статье мы расскажем о передаче ethernet пакетов из FPGA во внешний мир.

Отдельная огромная тема — это на чём это реализовывать. Вариантов несколько, но, в большинстве своём, плисоводы приходят к выводу, что лучший вариант — это «рукопашный».

В начале стоит внешняя «физическая» микросхема (PHY), которая выполняет работу нулевого уровня (если строго следовать модели OSI), т.е. преобразование аналоговых сигналов в цифровые, битовую и кадровую синхронизации. Затем следует MAC-уровень, т.е. всё, начиная от проверки контрольной суммы (КС) пакета до разборки и вытаскивания «полезной нагрузки» из многочисленных IP-протоколов: начиная от TCP, UDP и ARP и заканчивая экзотикой типа H.248.

Для соединения MAC уровня и PHY обычно используется один из интерфейсов.

MII- Media Independent Interface.

pic2

MII (Media Independent Interface — независящий от среды передачи интерфейс) — стандартизованный интерфейс для подключения MAC-блока сети Fast Ethernet к блоку PHY. Интерфейс MII может быть выведен на разъём для подключения внешнего приемопередатчика или может просто соединять две микросхемы на одной печатной плате. Независимость от среды передачи означает, что существует возможность использования любых PHY-устройств без необходимости смены или переработки аппаратуры MAC-блока. Интерфейс MII состоит из двух частей: канала приема-передачи данных (MII) и служебного канала управления (MDIO и MDC). Все операции интерфейса MII выполняются в синхронном режиме.

GMII- Gigabit Media-Independent Interface.

pic2

GMII (Gigabit Media-Independent Interface) — расширение стандарта MII (Media Independent Interface — независимый от среды передачи интерфейс) для гигабитных Ethernet-интерфейсов, обеспечивающий передачу данных между устройствами, реализующими подуровень Media Access Control (MAC) канального уровня с устройствами, реализующими физический уровень (PHY) модели OSI (например, как с оптическими интерфейсами 1000BASE-*X стандарта 802.3z, так и с медными интерфейсами 1000BASE-T* стандарта 802.3ab). GMII обеспечивает работу на скоростях до 1000 Мбит с использованием восьмибитного интерфейса с тактовой частотой 125 МГц и является обратно совместимым с MII, поддерживая работу на скоростях 10/100 Мбит в соответствии со спецификацией MII. Определён (как и MII) в рамках стандарта IEEE 802.3[1].

RMII- Reduced Media Independent Interface.

pic2

RMII (Reduced Media Independent Interface — сокращенный независящий от среды передачи интерфейс) представляет собой стандартизованный интерфейс использующий сокращенный набор сигналов интерфейса RMII применяется для подключения MAC-блока сети FastEthernet к блоку PHY. Разрядность шин RXD и TXD сокращается вдвое по сравнению с MII, но соответственно вдвое поднимается частота синхронизации MAC. Такое решение позволяет упростить конструкцию печатной платы и сократить количество используемых выводов микроконтроллера. В ряде случаев возможно использовать единую частоту синхронизации для MAC и PHY. Интерфейс RMII имеет сокращенный набор сигналов и полностью совместим с IEEE 802.3u. Он позволяет работать в режимах 10 и 100 Мбит/c, имеет частоту синхронизации 50 МГц.

RGMII- Reduce Gigabit Media Independent Interface.

pic

RGMII (Reduce Gigabit Media Independent Interface) — улучшенный интерфейс GMII указывает конкретный интерфейс между Ethernet MAC и PHY. RGMII использует половину цепей, используемых в GMII интерфейсе. Это сокращение достигается за счет синхронизации данных как по фронту, так и по спаду клока в режиме 1000 Мбит/с, а также путём устранения несущественных сигналов (несущей и индикации). Таким образом RGMII состоит только из следующих цепей: RX_CTL, RXC, RXD [3:0], TX_CTL, TXC, TXD [3:0] (12 контактов, в отличие от GMII).

SGMII- Serial Gigabit Media Independent Interface.

pic2

SGMII — это последовательный интерфейс, который хорош тем, что ему требуется всего одна пара проводов (в одну сторону, есс-но дифференциальных, конкретнее — LVDS), если работа идёт без опорного генератора. А огромный минус его в том, что работа идёт на частоте аж 625 МГц по обоим фронтам. Далее этот поток (если речь о приёме) следует преобразовать в параллельный код.

SGMII — это последовательный интерфейс, который хорош тем, что ему требуется всего одна пара проводов (в одну сторону, есс-но дифференциальных, конкретнее — LVDS), если работа идёт без опорного генератора. А огромный минус его в том, что работа идёт на частоте аж 625МГц по обоим фронтам. Далее этот поток (если речь о приёме) следует преобразовать в параллельный код. В принципе, топовые микросхемы, типа того же Stratix'а IV и V с максимальными суффиксами в состоянии выполнить такое преобразование «на себе», т.е. на схеме, реализованной на внутреннем массиве логических элементов (ЛЭ). Но, такая схема будет весьма нестабильна (ибо работать будет почти на пределе возможностей, когда, по-сути, цифровая схема превращается в «полу-аналоговую» и всё, что показывают имитаторы типа Modelsim'а — никакого отношения к действительности не имеет), да и ставить мегадорогущие каменюги ради стыковки с PHY — не очень серьёзно. Поэтому, во многие ПЛИСины втискивают аппаратные приёмопередатчики SGMII. Но настройка этих блоков — отдельная и непростая штука. Кроме того, нужно помнить про сложности разводки печатной платы, ибо даже исходная частота (625 МГц), мягко говоря, не детская, а с учётом требований к фронтам и спадам (типично, максимум — 0,2нС) — можете легко посчитать требуемую широкополосность линий. Поэтому, мой совет — с SGMII связываться только в крайнем случае!

Гораздо проще ситуация с GMII и RGMII-интерфейсами. Это — параллельные (8 и 4, соответственно) линии связи. Тактовая частота снижена до разумных 125 МГц, хотя даже такая частота может представлять определённую проблему для дешёвых вариантов современных ПЛИС, особенно если нужно «выжать» всё, что можно из 1Гбит-интерфейса и, соотвественно, пакеты должны формироваться «на лету». Поскольку, для RGMII-интерфейса при тактировании по одному фронту понадобилась бы тактовая частота в 250 МГц (что уже совсем тяжеловато для большинства современных ПЛИС), здесь также производится тактирование по фронту и спаду тактового сигнала.

pic2

Если очень страшно связываться с двойным тактированием, то можно использовать GMII-интерфейс и тут, фактически, разработчик почти спокойно может использовать наработки, взятые из MII-интерфейса, разве что не забыв, что по GMII передаются байты, а не полубайты(нибблы) и, есс-но, подняв скорость передачи в 5 раз.

Но лишние выводы в современных ПЛИС'инах весьма дороги и RGMII-интерфейс предоставляет возможность разумной экономии (между GMII и SGMII) ценой некоторого (на самом деле, небольшого) усложнения схемы. И, кстати, если ваше устройство должно иметь возможность работать и с 1Гбит и с 100Мбит-устройствами, то, на самом деле, наиболее простой переход с MII обеспечивает RGMII.

Как стыковать RGMII с ПЛИС. Достаточно просто. Теоретически двухтактный буфер можно создать в основном массиве ЛЭ, используя (лучше всего) графику, или поизвращавшись (вообще, убогость этих языков — отдельная тема) в VHDL или Verilog'е (не забыв указать *useioff* у соответствующих выводов). Но, как показала практика, работать это всё будет весьма убого (ибо, с учётом требований к крутизне фронтов, широкополосность должна достигать 400 МГц!), правда, даст подсмотреть генерируемые сигнал в SignalTap (ChipScope).

Более правильный путь — использовать специализированные двухтриггерные буфера, например, в альтеровском случае — это ALTDDIO в соответствии с документом AN477 «Designing RGMII Interfaces».

pic2

На языке Verilog реализация передатчика 1 Gbit ethernet, с выходными буферами и передаваемым пакетом выглядит так:

Verilog Code:
  1. //----------------------PHY1 Send------------------------------
  2. eth_dat_iobuf tx_buf_h
  3. (
  4. .datain (PHY_TX_BUF[3:0]),
  5. .dataout (DATA_OUT_H[3:0])
  6. );
  7.  
  8. eth_dat_iobuf tx_buf_l
  9. (
  10. .datain (PHY_TX_BUF[7:4]),
  11. .dataout (DATA_OUT_L[3:0])
  12. );
  13.  
  14. eth_ddo eth_ddio_buf(
  15. .datain_h (DATA_OUT_H),
  16. .datain_l (DATA_OUT_L),
  17. .outclock (PLL_CLK_125_45),
  18. .dataout (DATA_TO_PHY)
  19. );
  20.  
  21. eth_obuf eth_o_buf(
  22. .datain (DATA_TO_PHY),
  23. .dataout (DATA_TO_PHY_BUF)
  24. );
  25.  
  26. phy1 phy_snd(
  27. .clock25_0 (PLL_CLK_25_0),
  28. .clock250_0 (PLL_CLK_250_0),
  29. .clock125_90 (PLL_CLK_125_90),
  30. .rst (KEY[0]),
  31. .phy1_mdc (PHY_MDC),
  32. .phy1_mdio (PHY_MDIO),
  33. .phy1_res (PHY_RES),
  34. .phy1_int (PHY_INT),
  35. .phy1_clk_25 (PHY_CLK25),
  36. .phy1_tx_clk (PHY_TX_CLK),
  37. .phy1_rx_clk (PHY_RX_CLK),
  38. .phy1_ctl (PHY_CTL_BUF),
  39. .phy1_rx_dv (PHY_RXDV),
  40. .phy1_tx (PHY_TX_BUF),
  41. .phy1_rx (PHY_RX),
  42.  
  43. .ipmem_address (IP_RAM_ADDRESS_R),
  44. .ipmem_q (IP_RAM_Q),
  45.  
  46. .phy_ready (PHY_READY),
  47.  
  48. .cpy_ready (~KEY[1])
  49. );
  50.  
  51. ip_buffer video_pckt(
  52. .clock (PLL_CLK_250_0),
  53. .data (IP_RAM_DATA),
  54. .rdaddress (IP_RAM_ADDRESS_R),
  55. .wraddress (IP_RAM_ADDRESS_W),
  56. .wren (IP_RAM_WREN),
  57. .q (IP_RAM_Q)
  58. );

А так выглядит графическое представление передатчика:

pic8

Строб пакета tx_en, как показывает практика, лучше тоже протаскивать через ALTDDIO (что и сделано под именем dataout[4]).

Показанная схема будет работать только при условии, что тактовая частота gtx_clk сдвигается на 90 градусов на внутреннем ФАПЧ микросхемы PHY (см. выше диаграмку с RGMII-сигналами). Такая весьма удобная опция предусмотрена в большинстве 1Гбит-PHY, но она включается в соответствующем регистре через MDIO. Например, для 88E1111 — это бит 1 регистра 20. Если же MDIO-приёмопередатчик писать лень, то тогда сдвинутую последовательность нужно сгенерить в ПЛИС с помощью ФАПЧ(PLL) и подать её на выход GTX_CLK. К сожалению, такой вариант часто не обеспечивает нужной стабильности и приводит к редким пропаданием отдельных пакетов.

А так выглядит сам код, передающий один пакет из памяти:

Verilog Code:
  1. //----------------------------ETH Send----------------------------------
  2. reg [10:0] clk_counter; // Number of bits determines pause time
  3. reg [2:0] state;
  4. reg tx_state;
  5. reg [31:0] delay_count;
  6.  
  7. assign phy1_res = rst;
  8. assign phy1_tx_clk = clock125_90;
  9.  
  10. always @(posedge clock250_0)
  11. begin
  12. if (rst==0)
  13. begin
  14. delay_count <= 0;
  15. state <= 1;
  16. end
  17. else
  18. begin
  19. //----------------------------------------------------------------------
  20. if(state==0)
  21. begin
  22. phy1_ctl <= 1'b1; // Transmission is enabled
  23. phy_ready <= 0;
  24. if (clk_counter > 11'd1198)
  25. begin
  26. phy1_ctl <= 1'b0; // Transmission is disabled
  27. phy_ready <=1;
  28. ipmem_address <= 11'h0;
  29. state <= 1;
  30. end
  31. else
  32. begin
  33. if(tx_state==0)
  34. begin
  35.  
  36. phy1_tx <= ipmem_q;
  37. clk_counter <= clk_counter + 1'b1;
  38. tx_state <= 1;
  39. end
  40. else if(tx_state==1)
  41. begin
  42.  
  43. ipmem_address <= clk_counter;
  44. tx_state <= 0;
  45. end
  46. end
  47. end
  48. //--------------------------------------------------------------------
  49. else if(state==1)
  50. begin
  51. if(delay_count<101)
  52. begin
  53. clk_counter <= 11'h0;
  54. delay_count <= delay_count + 1;
  55. end
  56. else
  57. begin
  58. if(cpy_ready==1)
  59. begin
  60. delay_count <= 0;
  61. tx_state <= 0;
  62. state <= 0;
  63. end
  64. end
  65. end
  66. end
  67. end

Ну и по традиции видео работы, и исходники:

Скачать: 1gb_ethernet.zip

P.S. Большая часть была взята с http://we.easyelectronics.ru

Добавить комментарий