Перейти к содержанию

Lab 11.32 — Двухплатный захват coarse-CFO внутри FPGA

Цель

Проверить, что блок qpsk_coarse_cfo.v в опубликованном PL-битстриме захватывает живой QPSK-кадр при управляемом межплатном CFO от 0 до 55 кГц. RF-тракт, кадр, число попыток и перебор восьми фаз одинаковы; между сериями меняется только gp_ctrl[13]: coarse-CFO включён или работает одна петля Костаса.

Это эксперимент по полосе захвата, а не заявление о долговременном BER. Нулевой BER хотя бы у одного кадра доказывает возможность захвата данной CFO. Устойчивость отдельно показывают доля чистых попыток, доля захватов и агрегированный BER полностью принятых кадров.

Стенд и параметры

плата A: vendor image, циклический DMA TX на 915 МГц + Δ
    TX1 ── аттенюатор 30 дБ ── SMA-кабель ── RX1
плата B: course bitstream, fabric RX + coarse-CFO + Costas + BER counter
Параметр Значение
Несущая 915 МГц
Символьная частота / Fs 480 ксимв/с / 3,84 Мвыб/с
Кадр 140 QPSK-символов, 280 проверяемых бит
TX / RX gain −30 дБ / 50 дБ
Start offsets 0…7
Попытки 3 на каждую фазу и режим, 24 на CFO-точку
CFO sweep 0…55 кГц, шаг 5 кГц

Обе платы переводятся в −89,75 дБ до настройки и в блоке finally, включая аварийное завершение.

Контракт метрик

Метрика Смысл
reached_zero / best_ber Найден хотя бы один полный кадр 280/280 без ошибок: факт захвата.
clean_attempt_rate Чистые кадры / все попытки, включая отсутствие захвата.
lock_rate Попытки с полными 140 символами / все попытки.
aggregate_ber BER только по полным кадрам; отсутствие захвата не считается нулём.
Wilson interval 95%-й интервал для долей захвата и чистых попыток.

JSON сохраняет каждую попытку, поэтому итог пересчитывается без ручного выбора удачных строк.

Результат 2026-07-20

Coarse-CFO достиг BER=0 во всех 12/12 CFO-точках и дал 75/288 чистых попыток (26,0%). Costas-only дал 0/216 чистых попыток в девяти различающих точках от 15 до 55 кГц.

Двухплатный in-fabric coarse-CFO

CFO, кГц Coarse: чистые Coarse: lock Coarse: aggregate BER Costas: лучший BER Costas: чистые Costas: lock
0 7/24 50,0% 0,175 0 8/24 66,7%
5 6/24 70,8% 0,267 0,400 0/24 70,8%
10 6/24 79,2% 0,302 0,464 0/24 83,3%
15 5/24 66,7% 0,245 0,493 0/24 25,0%
20 9/24 79,2% 0,203 нет захвата 0/24 0%
25 7/24 83,3% 0,227 нет захвата 0/24 0%
30 7/24 70,8% 0,232 0,439 0/24 12,5%
35 8/24 87,5% 0,276 0,468 0/24 25,0%
40 2/24 58,3% 0,395 0,443 0/24 16,7%
45 3/24 58,3% 0,361 0,514 0/24 4,2%
50 10/24 70,8% 0,136 0,454 0/24 4,2%
55 5/24 66,7% 0,171 нет захвата 0/24 0%

Эксперимент подтверждает полосу захвата CFO: coarse-блок находит чистый кадр в каждой точке, а одна петля Костаса не справляется на 15–55 кГц. Но это ещё не устойчивая непрерывная связь: 26% чистых попыток и высокий условный BER показывают оставшуюся проблему sample-clock/timing phase. Следующий инженерный шаг — непрерывное timing recovery либо формализованный burst-phase search.

Воспроизведение

python blocks/block_11_integrated_sdr_project/python/lab_11_32_two_board_fabric_coarse_cfo.py --self-test

python blocks/block_11_integrated_sdr_project/python/lab_11_32_two_board_fabric_coarse_cfo.py \
  --host-a 192.168.40.1 --host-b 192.168.20.1 \
  --cfo-start 0 --cfo-stop 55000 --cfo-step 5000 \
  --retries-per-offset 3

Канонический результат: lab1132_two_board_fabric_coarse_cfo.json. Команда возвращает ненулевой код, если coarse не захватил хотя бы одну CFO-точку или Costas-only получил чистый кадр при |CFO| ≥ 15 кГц.

RF-безопасность

Использовать только замкнутый кабельный тракт с аттенюатором 30 дБ. Не подключать антенны с этими настройками и не повышать мощность TX для «улучшения картинки». После прерывания проверить, что обе платы возвращены в −89,75 дБ.