Описание стенда и быстрый старт

- docs/stand.md: состав стенда, схема и таблица соединений, питание,
  порядок работы, нормальные показания на ПК и на выходе ЦАП, неисправности;
- README: UART через мост BL616 вместо внешнего FT232, быстрый старт,
  структура, команды симуляции через --elab-run (работают и с mcode-сборкой
  GHDL), python вместо py -3, список локальной документации;
- .gitignore: мусор генератора IP Gowin, Python, Windows.
This commit is contained in:
2026-10-02 14:21:07 +03:00
parent d6f3ee5ef8
commit 525a1dd90e
3 changed files with 490 additions and 40 deletions
+211
View File
@@ -0,0 +1,211 @@
# Стенд цифрового микрофона
Стенд проверяет цифровой микрофон 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, раздел про ограничения кристалла.