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

Я уже многократно писал,  что рассматриваю LiteX как некий аналог подсистемы Qsys из среды разработки Quartus. То есть, как удобное средство составить шинно-ориентированную систему из множества готовых ядер. Но если Qsys – он только для Альтер, то LiteX – он подходит и для Altera (Intel), и для Xilinx, и для Lattice. А сейчас я по работе плотно вожусь именно с Латтисами. У Латтисов самое узкое место – это параметр FMax. И вот построение базовых систем на базе шины Wishbone у Litex получается очень красиво. Там FMax выходит достаточно высоким. Даже у Латтисов он превышает 100 МГц.

В предыдущих статьях мы уже научились добавлять в систему устройства, доступные по шине через регистры команд-состояний (CSR), а также пассивные (Slave) устройства с шиной Wishbone. Сегодня мы добавим на шину активное (Master) устройство. Поехали!

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

class SpiToWishBone (Module):
   def __init__(self, clk, rst, spi, notEmpty, lastByte, wishbone):

      self.bus = wishbone
      self.data_width = 32

      self.specials += Instance("SpiToWishBone",
         i_clk = clk,
         i_rst = rst,

         i_sck = spi["sck"],
         i_mosi = spi["mosi"],
         o_miso = spi["miso"],
         i_cs = spi["cs"],

         o_notEmpty = notEmpty,
         i_lastByte = lastByte,

         o_wb_adr_o = wishbone.adr,
         i_wb_dat_i = wishbone.dat_r,
         o_wb_dat_o = wishbone.dat_w,
         o_wb_we_o = wishbone.we,
         o_wb_sel_o = wishbone.sel,
         o_wb_stb_o = wishbone.stb,
         i_wb_ack_i = wishbone.ack,
         i_wb_err_i = wishbone.err,
         o_wb_cyc_o = wishbone.cyc

      )

Как видно, это интерфейс для внешнего (описанного на Верилоге) моста между SPI и шиной Wishbone. Линии MOSI, MISO, SCK и CS – стандартные SPI-ные линии. Так как у линии sck префикс «i» — это вход. То есть, spi является пассивным. Но об этом – чуть ниже. Линии notEmpty и lastData тоже относятся к нашей реализации шины SPI.

А всё, что ниже – это шина Wishbone.

Как эти шины подключаются к нашей системе – ну мне уже скучно описывать, это я всё неоднократно описывал в предыдущих статьях. Кто попробовал всё это на практике, тот уже видит, что мы вышли из области творчества в область рутины. Давайте, чтобы хоть что-то новое рассказать, я покажу, как раскрываются эти префиксы сигналов «i», «o», «io» и бывают ли какие-то ещё префиксы. Чтобы быстро найти разгадку, ставим точку останова на одну из строк, где эти префиксы фигурируют. Такие вещи лучше всего ловить при трассировке.

Так как мы создаём объект класса Instance, то ставим курсор на его имя, нажимаем правую кнопку «мыши» и выбираем «Перейти к определению».

Немного поездив по тексту, находим ответ на наш вопрос:

Оказывается, тут же мы можем добавлять не только входы, выходы и двунаправленные порты для модуля, но и параметры для него. В этом случае, префикс будет «p_». Ну хоть что-то новое. А то статьи какие-то шаблонные пошли.

Итак. Мы сделали класс устройства. Теперь в основном коде его надо подключить. Тоже уже отработанный процесс! Причём он намного проще, чем мы это делали раньше!

    # Self Reset Generator
    local_rst = Signal()
    reset_gen = rst_gen (clk,rst,local_rst)
    soc.platform.add_source("rst_gen.v")
    soc.submodules.reset_gen = reset_gen

 Это я добавил собственный генератор сброса, так как на плате он отсутствует, а шина требует. Сразу после загрузки он сформирует короткий импульс на линии local_rst:

    #WishBone Master
    soc.platform.add_source("axis_fifo.v")
    soc.platform.add_source("axis_wb_master.v")
    soc.platform.add_source("SPItoAXIS.sv")
    soc.platform.add_source("SpiToWishBone.sv")

    wbMaster = wishbone.Interface()

    spi_pins = {
           'sck' : soc.platform.request ('sck',0),
           'mosi' : soc.platform.request ('mosi',0),
           'miso' : soc.platform.request ('miso',0),
           'cs' : soc.platform.request ('cs',0)
       }

    spi2wb = SpiToWishBone (clk, local_rst,spi_pins,soc.platform.request ('notEmpty',0),
                            soc.platform.request ('lastByte',0),wbMaster)

    soc.submodules.spi2wb = spi2wb

    soc.bus.add_master ("spi2wb_master",wbMaster)

Сначала мы надобавляли Верилоговскимх файлов (зачем так много – будет описано ниже), после чего привычным движением руки описали шину, описали ножки, которые пойдут на SPI, объявили объект мастера и подключили его к общей шине системы. ВСЁ!  На этом можно расходиться… Тема статьи исчерпана!

Неожиданное заключение

Написанное выше – это примерно четверть от задуманной статьи. Дальше по планам должно идти описание тестового окружения. Вторая четверть – как был найден более-менее приемлемый Wishbone мастер (стык Wishbone с AXI Stream). Если что – я про этот проект alexforencich/verilog-wishbone: Verilog wishbone components. Попутно я хотел пройтись по тому, чем плохи другие найденные реализации. Третья четверть планировалась на то, чтобы рассказать о недостатках найденного проекта (нет таймера для ловли таймаутов, а также система адресации и инкремента адреса не совместима с тем, что принято в LiteX). Ну, и рассказ о том, как всё было состыковано. Ну, и последняя четверть – моя реализация преобразователя SPI в AXI Stream и программная поддержка FT232H через кросс платформенную библиотеку libftdi  libFTDI » FTDI USB driver with bitbang mode.

Но и так-то не хватало сил из-за подготовки лекций и лабораторных для студентов, плюс случилось то, из-за чего пропало вдохновение вовсе. И очень долго не возвращалось. Мало того, из случившегося вытекло, что фирма Латтис начала угнетать нас по национальному, расовому или религиозному признаку. Документацию на чипы уже не скачать. Хорошо, хоть ГитХаб с открытой средой разработки пока доступен. Но всё равно, интерес к их и без того не самым лучшим в мире чипам, подорван. Короче, со вдохновением – труба. Мы посовещались и решили, что раз у статьи есть завершённая мысль, то опубликуем её так, а недостающие части я опишу, когда это самое вдохновение вернётся.

Но и когда вернётся, что делать с циклом дальше – большой вопрос. Дело в том, что дальше хоть делай процессорную систему, хоть что-то без процессора, а всё равно надо задействовать SDRAM. И вот выяснилось, что при этом параметр FMax будет не очень высоким. Буквально 50 МГц. Судя по критическим цепям, задержки вносит не сам контроллер SDRAM, а подсистема кэширования. Если превысить FMax, тесты ОЗУ будут давать ошибки. А производительность ОЗУ будет совсем смешной. Я несколько дней поснимал времянки (и в режиме 1:1, и в режиме 1:2), и вижу, что особо там выскакивать некуда. Попутно была найдена табличка, которая очень похожа на мои выводы: LiteDRAM benchmarks summary. Там у неё много вкладок. И результаты – один другого хуже для SDRAM.  А на целевой плате припаян SDRAM, и он нужен хоть для процессора, хоть как буферное ОЗУ для того же HDMI, хоть для хранения данных.

В общем, как шинная основа, LiteX – просто замечательная штука, а как полноценная система – кажется, уже не очень. Возможно, кто-то знает про подсистему памяти что-то такое, что опровергнет мои выводы. Рад буду списаться хоть в комментариях, хоть в диалогах. Но эта часть – уже совсем на будущее. Сначала пусть вернётся вдохновение для описания тестового набора, а там уж и времянки со своими мыслями я сделаю. А так – все принципы для того, чтобы построить шинно-ориентированную систему на базе LiteX, описав для неё рабочие блоки на чистом Verilog, мы изучили. И эта подсистема получается весьма и весьма эффективной.  Буду рад, если кому-то это пригодится. И буду надеяться на то, что следующие части выйдут более-менее скоро.

Комментарии (4)


  1. le2
    17.05.2022 23:48

    Статью я конечно же не читал. Простите за оффтоп.
    Какие 50МГц? Какой SDRAM, когда DD3 уже снимается (посмотрите графики производства). Какой VGA (из прочих статей)?
    В текущей ситуации нужно полностью переходить на китайские ширпотребные четырехядерные процессоры по 5 баксов в Москве с НДС. А за 7 баксов с GPU (Rockchip, Allwinner). И на Линукс.
    Мои эксперименты показывают что с рилтаймовостью сейчас совсем не так как пишут в книжках. Освоил конвейер OpenGL и шейдеры (включая вычислительные). Вам не кажется что это прямая альтернатива параллельным вычислениям на ПЛИС? На GPU производительность просто чудовищная.
    К тому же ПЛИС в масмаркете существует только до тех пор пока кто-то не заковыряет наработки в ASIC и не выбьет тебя с рынка.
    Да, я понимаю, что ниши у ПЛИС остаются — разработка ASIC'ов — супердорогие решения, типа осциллографов и базовых станций, но в остальном все это тупиковые истории для коммерческого сектора.
    Простите за безаппеляционные заявления. Порог входа в системное программирование под Линукс гораздо выше. А конвейер GPU это просто вывих мозга.
    Последний аргумент, если я ничего не путаю, станции и марсоходы NASA летают и бегают без плисин и микроконтроллеров.


    1. EasyLy Автор
      18.05.2022 00:48

      Какой SDRAM, когда DD3 уже снимается (посмотрите графики производства).

      Да, но сколько он стоит и какие требования к плате, на которой он установлен? И на данной конкретной плате стоит именно SDRAM. Но даже и DDR3. Посмотрите таблицы по той ссылке. Для DDR3 производительность иногда лучше, но сильно не всегда.

      Какой VGA (из прочих статей)?

      Это точно. В выводах к той статье так и было написано: "Больше с VGA мы дела не имеем, глупости это, теперь все это сами видели". А в уме я держал: "Перейдём к HDMI - сошлюсь на все эти формулы, так как они все будут точно такими же". Половину той статьи занимал вывод критически важных параметров.

       На GPU производительность просто чудовищная.

      Тут надо смотреть в комплексе. Производительность - один из параметров. А энергопотребление? А автономность? А цена? В первой статье я отмечал, что тут ПЛИС + плата + два ОЗУ + флэшка + генератор + два гигабитных Ethernet (PHY и обвязка) + куча барахла... Всё это было куплено менее, чем за тысячу рублей, включая доставку. Сейчас цены плавающие, так что текущую смотреть не буду. Будем ориентироваться на стабильные времена. Потому что плавают цены на всё. На GPU - тоже.

       Порог входа в системное программирование под Линукс гораздо выше. А конвейер GPU это просто вывих мозга.

      То есть, трудозатраты (а значит - цена разработки) существенно выше. Специалистов тоже искать сложнее. Странное преимущество.

      Последний аргумент, если я ничего не путаю, станции и марсоходы NASA летают и бегают без плисин и микроконтроллеров.

      Да, но наш Заказчик конкретно на эту ПЛИС не марсоход делает, а станки с ЧПУ. Не со всеми его задумками я согласен, но деньги платит он. Заказчик, как я уже отмечал в комментариях к прежним статьям, не из России. А так... Цены на космическую технику таковы, что ещё недавно их могло выкладывать только государство. Поэтому ориентироваться на марсоходы, как на основу для массового решения... Ну, я бы не стал. Помню, фирма Fujutsu перешла на альтернативный формат сервометок, который создал дичайшие трудности. Аргументация была - это снижает себестоимость жёсткого диска на сколько-то там центов... Даже не на доллар! Правда, в том конкретном случае, они прогадали.


      1. le2
        18.05.2022 01:01

        Марсоход я привел в качестве примера как аргумент того многие задачи можно решить без периферийных микроконтроллеров и плис. Станки, конечно, опасно так делать. Вернее дорого, на решениях типа VxWorks это возможно.
        В моей картине мира компоненты для космоса, авиации, обороны всегда были и будут убыточны. Это безопасность и престиж. Никаких частных компаний не существует без скрытой протекции или благословления государств.


        1. EasyLy Автор
          18.05.2022 01:19

          Ну да. Любая задача имеет множество решений. И вот у ПЛИС. Те же мои статьи с анализаторами. Сколько стоит купить готовый анализатор USB? А на ПЛИС - я уже на базе универсальной платформы сделал целых два анализатора. USB и Ethernet на два канала (для проверки EtherCAT). Причём Ethernet получился за несколько дней из USB. На базе одного и того же железа, только обвязка разная втыкается и прошивка заливается.

          ПЛИС - гибкая штука для штучных решений. А штучные решения нужны часто. Это как 3D принтер. Массовые вещи на нём тоже делать бесполезно.

          В рамках этого цикла, ну попробовал я систему LiteX. И поделился с читателями тем, что мне показалось там классным. А выводы к этой статье, показывают, какие я там вижу проблемы. Причём там чётко сказано, что проблемы, похоже, тупиковые. Если только не придёт кто-то, кто раскроет мне глаза...

          Вот в комментариях про производительность USB на STM32... Рылся я, рылся, ничего в сети нет. Опубликовал... Рррраз! Сразу три отечественных библиотеки в комментариях подкинули! Так что если нет решения - все увидят, куда соваться не стоит. Есть решение - оно будет зафиксировано, а до того никакой поисковик не обнаруживал его. В любом случае, стоит опубликовать.

          Но даже при наличии тупиковых проблем, шинная система у LiteX классная и шустрая. На неё нанизывать блоки - вполне можно. А это упрощает и ускоряет разработку. В этом практическая польза от цикла.