# Стенд цифрового микрофона Стенд проверяет цифровой микрофон 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`](../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`](../tools/requirements.txt) | запись, просмотр, прослушивание | | GHDL, Icarus Verilog | только симуляция | Gowin Programmer с заменённой прошивкой BL616 **не работает**: он видит только мост со штатной прошивкой Sipeed. Вернуть штатную — `flash.ps1 -Restore` в проекте BL616, но со штатной UART BL616 работает хуже. ```bash 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. Загрузить ```powershell 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. Посмотреть поток на ПК ```bash 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. Записать и послушать ```bash 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](../README.md#по-на-пк). ## Если не работает | Признак | Вероятная причина | Что сделать | |:--|:--|:--| | светодиод не мигает | битстрим не загружен или нет клока | загрузить заново; с `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, раздел про ограничения кристалла.