Блог
Курс 7 из каталога: UART покадрово, SPI по режимам, рукопожатие APB, пять каналов AXI4, карты памяти, пакетный мост, кадры Ethernet и тайминг RGMII, дисциплина IO на стенде -- в каждом уроке открывается один виджет и одна спека t27, а 31 виджет -- новые записи нативного t27c на настоящей машине.

В каталоге теперь семь курсов. «Шины и периферия» — 27 уроков в 9 модулях по 3, он сцеплен с курсом о тактах: капстоун того курса ссылается вперёд, урок 1 — назад. Предмет — середина любого настоящего дизайна: как блоки разговаривают. UART покадрово, SPI по режимам, рукопожатие APB, пять каналов AXI4, карты памяти, пакетный мост между шинами, кадры Ethernet и тайминг RGMII, дисциплина IO на стенде, к которой весь трек вёл.
| Модуль | Чему учит |
|---|---|
| 1, Что такое шина | Зачем общим проводам нужен согласованный разговор; UART как двухпроводный архетип, SPI как разговор под тактом, APB как шина регистров с ролями. |
| 2, UART | Кадр (старт, 8 бит данных, стоп, покой вверх), делитель 100,000,000 / 115,200, коды статуса, которые опрашивает драйвер, и FIFO глубиной 16. |
| 3, SPI | CPOL и CPHA как четыре режима, лестница предделителей от одного такта 50 МГц, тайминг выбора кристалла 100 нс и ширины данных до 32 бит. |
| 4, APB | Фазы setup и access у PSEL и PENABLE, байты строоба для 32-битных и 16-битных записей и сколько адресных бит стоят 1, 4 или 8 периферий. |
| 5, AXI4 | Пять каналов с их ширинами (адрес 32, данные 32, строуб 4, ID 4, LEN 8, SIZE 3), что выбрасывает Lite и что покупает ID у пакета. |
| 6, Память | Карта памяти как «кто живёт по какому адресу»: типы, до 8 портов, ROM только-для-чтения, отвергающий порт записи, и задержка, которую должно покрывать ожидание. |
| 7, Мосты | Почему в дизайне вырастает несколько шин и пакетный мост с буферами RX и TX по 256 байт, SPI-буфером 64, пакетами 128 и таймаутом 10,000 тактов. |
| 8, Ethernet | Контрольная сумма кадра как CRC-32, RGMII, переносящий полубайт на обоих фронтах на 125 МГц, и заранее зарегистрированный план запуска, читаемый по шагам. |
| 9, Стенд | Кто сейчас держит IO (tri fpga-ioclients), взятие и возврат захвата и капстоун, открывающий весь дизайн: 8 MAC-блоков и 19 тестов. |
Курсу нужен виджет для каждого урока, и он отчеканил 33 новые записи. Большинство прогоняет нативный t27c 0.4.0 на ноутбуке по спекам шин. Но нативный раннер не берёт большинство этих спек целиком: uart, spi, apb_bridge, axi4, bridge и top_level BLOCKED по comptime-разрешению, которое раннер не завершает. Четыре проходят нативно чисто: memory.t27 — 15 тестов и 6 инвариантов, доказанных comptime, spi_tb.t27 — 7 тестов и обе новые спеки Ethernet: eth_crc.t27 с 8 тестами и rgmii.t27 с 7 тестами и comptime-инвариантом. Поэтому записи показывают то, что компилятор доводит до конца на каждой спеке: t27c check (0 ошибок, 0 предупреждений), t27c gen-verilog (синтезируемый модуль, его порты, его провода) и t27c debug-hir (взгляд аппаратного IR). Тексты уроков говорят, что есть что; ни одна запись не утверждает прогон тестов, которого не было.
Модуль стенда записывает живые инструменты: tri fpga-ioclients читает зарегистрированных клиентов IO, tri fpga-claim и tri fpga-release берут и возвращают захват подряд, tri fpga-next читает, что запускается дальше, а план запуска Ethernet из tri fpga-steps E3 зарегистрирован по шагам заранее. Капстоун опускает весь дизайн: top_level.t27 несёт CLK_FREQ_HZ 100,000,000, SYSTICK_HZ 1000, NUM_MAC_UNITS 8 и четыре кода операций (CMD_NOP, CMD_MAC_MULT, CMD_MAC_DOT, CMD_UART_SEND) на 19 тестах.
Модулю Ethernet нужны были спеки, которых в дереве не было. specs/fpga/eth_crc.t27 несёт CRC-32, который вычисляет контрольная сумма кадра, а specs/fpga/rgmii.t27 — тайминговую арифметику с двойной скоростью данных, 125 МГц для гигабита и одинарное понижение для 10 и 100. Обе написаны в gHashTag/t27 (PR 7626) и вендорены в дерево файлов сайта — в ту сторону, куда указывает правило собственного языка: спека живёт в репозитории, которому принадлежит язык, а сайт отдаёт копию, которую умеет доказать идентичной. Каждая константа в них, взятая не из IEEE 802.3, помечена в шапке спеки как допущение — рядом с документом, из которого её нет. Первая версия CRC-спеки была неверна так, что её собственный CI этого не видел: гейты проверяют, что спека компилируется, а не что её asserts держатся, и нативно падали 6 тестов из 8 — каждый неудачный assert сравнивал бегущий регистр с проинвертированными значениями zlib, а тест приёмника утверждал возврат регистра к пресету, чего CRC-32 из 802.3 не делает. Теперь спека несёт физическую модель: FCS — это проинвертированный регистр, а приёмник, переваривший кадр с FCS, приходит к остатку 0xDEBB20E3, вычисленному тем же Python zlib, который шапка называет оракулом. Все 8 тестов проходят, пустых — нет.
Последний гейт, который прогоняет курс, считает выброшенные токены, и четыре спеки уроков его не прошли, хотя отчитались, что компилируются: uart, spi, bridge и top_level несли тела тестов и инвариантов, которые парсер молча выбрасывал, -- голый оператор там, где ждали клаузу, условие implies в assert-телах, вызов несуществующего метода, комментарии внутри клауз. Компилятор говорил, что с файлами всё в порядке; читателю никто не сообщал, что его тесты даже не читались (дефект заведён как gHashTag/t27#2474, починка парсера заморожена стадией stage0, поэтому спеки переписаны в подмножество, которое парсер уже потребляет, -- gHashTag/t27 PR 7659, там же записана дивергенция wasm и нативного компилятора на записи в массив bridge). Каждый урок, который говорит вот спека, и она компилируется, теперь указывает на спеку, которая парсится до конца.
Поработаем вместе
Работаю по контракту и part-time с hardware-AI, FPGA/RTL и ML-системами — от спецификации и открытого тулчейна до воспроизводимых измерений.