Files
Gromov_IA 525a1dd90e Описание стенда и быстрый старт
- docs/stand.md: состав стенда, схема и таблица соединений, питание,
  порядок работы, нормальные показания на ПК и на выходе ЦАП, неисправности;
- README: UART через мост BL616 вместо внешнего FT232, быстрый старт,
  структура, команды симуляции через --elab-run (работают и с mcode-сборкой
  GHDL), python вместо py -3, список локальной документации;
- .gitignore: мусор генератора IP Gowin, Python, Windows.
2026-10-02 14:21:07 +03:00

15 KiB
Raw Permalink Blame History

Стенд цифрового микрофона

Стенд проверяет цифровой микрофон SPH9855LM4H-C, вынесенный на кабель с линией LVDS, вместе с трактом его обработки в ПЛИС. ПЛИС тактирует микрофон, принимает поток PDM, приводит его к 24 бит / 12 500 Гц и отдаёт отсчёты сразу в две стороны:

  • на ПК по USB — кадры с CRC: запись, живой просмотр, прослушивание;
  • на ЦАП PCM5102A — аналоговый сигнал, который смотрят осциллографом.

Обе ветви получают одни и те же отсчёты. Кнопкой на плате поднимается усиление только ветви ЦАП, на ПК всегда уходит исходная шкала.

Состав

Узел Что это Роль на стенде
Плата микрофона SPH9855LM4H-C и приёмопередатчики SN65LVDS PDM-микрофон; вывод SELECT задан на плате
Кабель две пары LVDS: CLK к микрофону, DATA от микрофона SN65LVDS на обоих концах
Tang Primer 25K + Dock модуль GW5A-LV25MG121NC1/I0, ревизия A тактирование микрофона, дециматор, кадры UART, I2S
Мост BL616 на Dock встроенный отладчик с заменённой прошивкой (отдельный проект BL616): DirtyJTAG + CDC-UART загрузка битстрима и UART на ПК по одному USB-C
Модуль ЦАП PCM5102A на своей плате, питание через LDO TPS7A2033 I2S -> аналог, выход OUTL на BNC
Осциллограф — смотрит выход ЦАП
ПК Windows, Python 3.10+, openFPGALoader сборка, загрузка, запись, просмотр, прослушивание

Схема

  Плата микрофона                              Tang Primer 25K + Dock (GW5A-25A)
 +----------------------+     кабель LVDS     +--------------------------------------+
 | SPH9855LM4H-C        |                     |                                      |
 |   CLK  <-- SN65LVDS <====== пара CLK ======< SN65LVDS <-- K8  MIC_CLK  3.125 МГц   |
 |   DATA --> SN65LVDS >====== пара DATA =====> SN65LVDS --> K9  MIC_DAT  PDM        |
 |   SELECT: на плате   |                     |                                      |
 +----------------------+                     |  E2  генератор 50 МГц                |
                                              |      PDM -> CIC -> ФНЧ -> 12 500 Гц  |
 +----------------------+        I2S          |                                      |
 | Модуль ЦАП PCM5102A  |<--------------------+  G1 SCK  G2 BCK  L4 LRCK  L3 DIN     |
 |   OUTL -> BNC  ------+--> осциллограф      |                                      |
 +----------------------+                     |  C3  UART_TX --> BL616 --+           |
                                              |  JTAG <--------- BL616 <-+--> USB-C --> ПК
                                              |                          |  COM14 + DirtyJTAG
                                              |  H11 кнопка S1: усиление ЦАП         |
                                              |  E8  светодиод: состояние, усиление  |
                                              |  E3  отладка: выход PLL 80 МГц       |
                                              +--------------------------------------+

Земля у ПЛИС, линии LVDS и модуля ЦАП общая.

Соединения

Цепь Вывод ПЛИС Банк Где на плате Куда идёт
clk E2 5 генератор 50 МГц системный клок; весь тракт и I2S делятся от него, без PLL
MIC_CLK K8 0 гребёнка J3 вход драйвера SN65LVDS, пара CLK к микрофону, 3.125 МГц
MIC_DAT K9 0 гребёнка J3 выход приёмника SN65LVDS, пара DATA от микрофона; подтяжка ПЛИС вниз
DAC_SCK G1 2 гребёнка J3 SCK модуля ЦАП, 12.5 МГц = 256 fS
I2S_BCK G2 2 гребёнка J3 BCK модуля ЦАП, 3.125 МГц = 64 fS
I2S_LRCK L4 2 гребёнка J3 LRCK модуля ЦАП, fS = 48 828 Гц
I2S_DIN L3 2 гребёнка J3 DIN модуля ЦАП
UART_TX C3 4 цепь FPGA_UART_TX Dock RX моста BL616 -> COM-порт на ПК, 921600 8N1
BTN_GAIN H11 7 кнопка S1 Dock замыкает вывод на +3.3 В через 100 Ом; подтяжка ПЛИС вниз
LED E8 4 светодиод (READY) индикация, см. ниже
clk_80MHz E3 4 гребёнка J3 только отладка: выход PLL, к тракту не относится

Привязка выводов — в src/DigMic.cst. Номера контактов гребёнки J3 — по схеме Dock (Tang_25K_60033.pdf, цепи вида K8_IOT56B_40P).

Направления MIC_CLK и MIC_DAT проверены на плате до первой прошивки диагностической прошивкой, которая ничего не выдаёт на спорные выводы: K8 висит на подтяжке ПЛИС (вход драйвера), K9 держит приёмник.

Питание

  • Dock — от USB-C; тот же разъём даёт JTAG и UART через BL616.
  • VCCIO банков 6/7 на этой плате подаётся снаружи, через контакты 29 и 31 гребёнки. Без 3.3 В на них не работает кнопка S1 (H11, банк 7).
  • Модуль ЦАП — на разъём X1 (цепь +5.5V), дальше два LDO TPS7A2033 раздельно дают аналоговые и цифровые 3.3 В. На BNC выведен только OUTL; ПЛИС шлёт один и тот же отсчёт в оба канала.
  • Сторона микрофона — по схеме платы микрофона; сам микрофон допускает 1.65...3.6 В.

ПО на ПК

Что Зачем
Gowin EDA V1.9.12 сборка в IDE
openFPGALoader ≥ 1.1.0 или TangProgrammer.exe — оба лежат в проекте BL616 загрузка битстрима через DirtyJTAG
Python 3.10+ и пакеты из tools/requirements.txt запись, просмотр, прослушивание
GHDL, Icarus Verilog только симуляция

Gowin Programmer с заменённой прошивкой BL616 не работает: он видит только мост со штатной прошивкой Sipeed. Вернуть штатную — flash.ps1 -Restore в проекте BL616, но со штатной UART BL616 работает хуже.

python -m pip install -r tools/requirements.txt

Порядок работы

1. Собрать

Gowin IDE: открыть DigMic.gprj, Run All.

Битстрим — impl\pnr\DigMic.fs. Проект собирается под Device Version A (gw5a25a-002). Это важно: битстрим под B на этой плате не выдаёт ни байта, а программатор расхождения не замечает, JTAG-код у ревизий одинаковый.

2. Загрузить

openFPGALoader -c dirtyJtag impl\pnr\DigMic.fs

Битстрим живёт в SRAM до выключения питания. Чтобы ПЛИС стартовала с ним сама, его записывают во флеш: openFPGALoader -c dirtyJtag -f impl\pnr\DigMic.fs. То же самое умеет TangProgrammer.exe, а с флажком «Загружать в SRAM автоматически» он заливает каждую новую сборку из IDE.

3. Проверить по светодиоду

Светодиод Что значит
не мигает, горит или погашен клока нет или битстрим не загружен
медленно, 2 Гц клок есть, отсчёты с дециматора не приходят
быстро, 10 Гц отсчёты идут: тракт PDM -> CIC -> ФНЧ работает
пауза, N коротких вспышек, пауза только что нажали S1: выбрана ступень N
пауза, одна длинная вспышка 1 с, пауза только что нажали S1: ступень 0

Рабочее состояние — быстрое мигание.

4. Посмотреть поток на ПК

python tools/uart_live.py --port COM14

COM14 — порт моста BL616 на этом ПК; на другом номер другой, его показывает python tools/uart_capture.py --list. Порт держит только одна программа: uart_live, uart_capture и uart_audio по очереди.

В строке состояния исправный стенд показывает:

Показатель Норма
кадров/с 250
CRC, потеряно, ресинхр 0; одна-две ошибки CRC и ресинхронизации в первый момент — норма: порт открылся посреди кадра
STATUS чисто (FIFO=1 — переполнение буфера, SAT=1 — выход упёрся в шкалу)
тишина в комнате СКО около −72 dBFS
смещение нуля около −90 dBFS
речь рядом с микрофоном пики около −50 dBFS

5. Посмотреть выход ЦАП

Осциллограф — на BNC модуля ЦАП. Полная шкала 24 бит — 2.1 В скз на выходе PCM5102A. При ступени 0 сигнал там в той же шкале, что на ПК, то есть доли и единицы милливольт. Каждое нажатие S1 даёт ровно +6.02 дБ (сдвиг на разряд), после ступени 8 снова 0:

Ступень S1 Усиление Фон комнаты, −72 dBFS Речь, −50 dBFS
0 0 дБ ≈ 0.5 мВ скз ≈ 7 мВ
4 +24 дБ ≈ 8 мВ ≈ 0.1 В
8 +48 дБ ≈ 0.13 В ≈ 1.7 В, у предела шкалы

На ступени 8 всё громче примерно 85 дБ SPL упирается в шкалу и ограничивается; признака этого нигде нет, на ПК при этом шкала прежняя. Полоса выхода, как у всего тракта, — до 5 кГц, задержка относительно UART — один отсчёт, 80 мкс.

6. Записать и послушать

python tools/uart_capture.py --port COM14 --seconds 10 --out test1
python tools/Bin_to_wav.py test1.bin
python tools/uart_audio.py --port COM14

uart_capture пишет test1.raw (поток как есть), test1.bin (только отсчёты, 3 байта BE) и test1.log со сводкой: те же показатели, что в таблице п. 4. Bin_to_wav делает из .bin WAV. uart_audio отправляет поток на звуковую карту ПК, слушать лучше в наушниках. Подробности — в README.

Если не работает

Признак Вероятная причина Что сделать
светодиод не мигает битстрим не загружен или нет клока загрузить заново; с LED_SRC = 3 в Top.vhd светодиод мигает ровно 1 Гц прямо от clk: другой период значит, что клок не 50 МГц
светодиод мигает медленно отсчёты не идут: обрыв MIC_CLK или MIC_DAT, нет питания линии или микрофона осциллографом: 3.125 МГц на K8 и PDM на K9; LED_SRC = 2 — мигание от битов PDM, 1 — от CIC: быстрое мерцание значит, что этот участок живой
на ПК ни одного байта битстрим собран под ревизию B; открыт не тот порт; UART не на C3 проверить Device Version A в проекте; uart_capture.py --list; UART_TX в DigMic.cst
CRC или ресинхронизации растут постоянно скорость порта не 921600 --baud 921600, это значение по умолчанию
кадров/с меньше 250, потеряно растёт байты теряются в мосте или драйвере, либо разбор не успевает uart_capture.py --port COM14 --dump: только приём без разбора, сравнивает скорость с ожидаемой и говорит, где потери
сигнал пропал или стал шумом после замены кабеля или SN65LVDS сдвинулась точка выборки бита перемерить фазу смены MIC_DAT относительно MIC_CLK и поправить MIC_SMP_CNT в Top.vhd, см. README
кнопка S1 не меняет ступень нет 3.3 В на VCCIO банков 6/7 подать 3.3 В на контакты 29 и 31 гребёнки
на ПК сигнал есть, на осциллографе нет ступень 0: на выходе доли мВ; нет питания модуля ЦАП нажать S1 несколько раз; проверить питание X1 и общую землю
could not open port порт держит другая программа закрыть uart_live / uart_audio / терминал
Gowin Programmer не видит кабель на BL616 заменённая прошивка грузить через openFPGALoader или TangProgrammer

Чего не делать

Два ограничения кристалла найдены на железе ещё при сборке под ревизию B. Под A их пока не перепроверяли, поэтому они остаются в силе:

  • не расширять аккумуляторы CIC сверх 18 бит: при 20 битах и больше тракт молча отдаёт нули, хотя синтез, тайминг и симуляция чистые;
  • не добавлять сброс по включению: счётчик, держащий rst_n, убивает тракт.

Подробности — в README, раздел про ограничения кристалла.