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

Лабораторная 5.6 — RTL FIR формирующего RRC-фильтра BPSK TX

Цель

Продвинуть исполняемый HDL-маршрут BPSK за пределы маппера символов и реализовать настоящий 65-коэффициентный FIR формирования импульса в Q1.15, используемый общим эталонным пакетом Блока 11.

Эта работа это первый настоящий мост от fixed-point модели Simulink к переиспользуемому RTL-блоку модема:

handoff BPSK Блока 11 -> маппер символов -> RRC TX FIR -> будущие TX gain / ЦАП / интеграция Zynq

Исполняемый HDL-пакет

Файл Назначение
blocks/block_05_fpga_hdl_flow/rtl/bpsk_rrc_tx_fir.v 65-коэффициентный FIR формирования импульса Q1.15 для потоков I/Q
blocks/block_05_fpga_hdl_flow/rtl/bpsk_rrc_tx_fir_taps.mem сгенерированный образ ROM коэффициентов из rrc_taps_q15.txt
blocks/block_05_fpga_hdl_flow/python/generate_bpsk_rrc_tx_fir_vectors.py пересоздаёт память коэффициентов и детерминированные тестовые векторы
blocks/block_05_fpga_hdl_flow/tb/tb_bpsk_rrc_tx_fir.v самопроверяющийся Verilog-testbench
blocks/block_05_fpga_hdl_flow/tb/bpsk_rrc_tx_fir_input_vectors.txt сгенерированный выход маппера в Q1.15 после повышения частоты
blocks/block_05_fpga_hdl_flow/tb/bpsk_rrc_tx_fir_expected_vectors.txt сгенерированный эталонный выход FIR в Q1.15

Запуск из корня репозитория:

python blocks/block_05_fpga_hdl_flow/python/generate_bpsk_rrc_tx_fir_vectors.py

iverilog -g2012 \
  -o blocks/block_05_fpga_hdl_flow/tb/tb_bpsk_rrc_tx_fir.out \
  blocks/block_05_fpga_hdl_flow/rtl/bpsk_rrc_tx_fir.v \
  blocks/block_05_fpga_hdl_flow/tb/tb_bpsk_rrc_tx_fir.v

vvp blocks/block_05_fpga_hdl_flow/tb/tb_bpsk_rrc_tx_fir.out

Ожидаемый результат:

PASS: bpsk_rrc_tx_fir test completed without errors

Общие входные данные

Работа намеренно использует тот же общий пакет, что и Блок 4.4:

Общий файл Роль на этом шаге RTL
tx_symbols_q15.txt детерминированный поток символов после BPSK-маппинга
rrc_taps_q15.txt точные 65 коэффициентов формирующего фильтра
config.json задаёт samples_per_symbol = 8 для вставки нулей

Python-генератор повышает частоту символов, добавляет хвост для очистки фильтра, вычисляет fixed-point отклик FIR и записывает и тестовые векторы, и файл памяти ROM.

Тракт данных

flowchart LR
    MAP[Символы BPSK Q1.15] --> UPS[Вставка нулей 8x]
    UPS --> SR[Сдвиговый регистр на 65 отсчётов]
    SR --> MUL[Знаковые умножители 16x16]
    TAPS[ROM коэффициентов RRC] --> MUL
    MUL --> ACC[40-битный аккумулятор]
    ACC --> ROUND[Округление Q2.30 до Q1.15]
    ROUND --> SAT[Насыщение до 16 бит]
    SAT --> OUT[Отсчёты Q1.15 после формирования импульса]

Контракт fixed-point

Параметр Значение
Формат входного отсчёта знаковый Q1.15
Формат коэффициентов знаковый Q1.15
Формат произведения знаковый Q2.30
Число коэффициентов 65
Минимум защитных бит ceil(log2(65)) = 7
Ширина аккумулятора в RTL 40 бит
Формат выхода знаковый Q1.15 с насыщением

Блок 4.4 уже проверяет тот же тракт формирования импульса в Simulink с общими коэффициентами rrc_taps_q15.

Эта работа использует те же коэффициенты и тот же поток символов, поэтому на следующем шаге интеграции можно сравнить:

  1. выход MATLAB/Simulink;
  2. выход RTL-симуляции;
  3. итоговый захват отсчётов TX на Zynq.

Чего ожидать

PASS: bpsk_rrc_tx_fir test completed without errors (2312 vectors, latency 9 cycles)

2312 = 281 символ x 8 отсчётов + 64 отсчёта дочистки (NTAPS - 1), так что проверяется весь хвост фильтра. Задержка 9 тактов это конвейер: симметричное предсложение (1), умножение (1), 6-ступенчатое дерево сумматоров, сводящее 33 произведения (33 -> 17 -> 9 -> 5 -> 3 -> 2 -> 1), и регистр округления/насыщения (1).

Раннер курса генерирует векторы, компилирует, запускает симуляцию и считает ошибкой любую строку FAIL или ненулевой код выхода симулятора:

python tools/run_block5_hdl_smoke.py --test tb_bpsk_rrc_tx_fir

В Vivado 2021.1 фильтр размещается и разводится на кристалле курса xc7z020clg400-2 на 100 МГц с запасом +3,038 нс и занимает 96 DSP48E1, 2266 триггеров и 148 LUT (отчёт). Журнал синтеза показывает, куда уходят 96 блоков: 66 выполняют умножения (по 33 на канал, симметричное предсложение каждого это внутри блока), а 30 используются только как 40-битные сумматоры дерева. Сравните это со своим ответом на упражнение 3: полностью параллельный фильтр дёшев по таймингу и дорог по площади.

Упражнения

Каждое упражнение ниже: намеренная мутация RTL в одну строку. Внесите её, запустите testbench, прочитайте сообщения и верните файл (git checkout -- <file>). Приведённые выводы получены на Icarus Verilog 12.0.

  1. Замените округление усечением: round_q15 = value >>> SHIFT;. Testbench сообщает FAIL: bpsk_rrc_tx_fir test completed with 1084 errors, каждая на 1 LSB меньше, например out=(23,0) expected=(24,0). Почему это близко к половине из 2312 выходов?
  2. По RTL подтвердите задержку 9 тактов поступенчато и скажите, какое число изменится, если NTAPS вырастет с 65 до 129.
  3. Фильтр симметричный, поэтому ему нужно 33 умножителя вместо 65. Сколько DSP48 займут I и Q вместе на Zynq-7020 и сколько понадобится версии с разделением по времени (folded) при 8 тактах на отсчёт?
Ответы (сверены с RTL и стендом)
  1. Усечение ошибается ровно тогда, когда отброшенная дробная часть не меньше половины МЗР. Дробные части произведений распределены почти равномерно, поэтому ошибается около половины выходов (1084 из 2312, 47 %); остальные либо имели дробную часть меньше половины, либо были точными.
  2. Входной регистр симметричных пар отводов (1), умножители (2), шесть уровней дерева сумматоров для 33 произведений (3–8, ⌈log2 33⌉ = 6) и выходной регистр с округлением и насыщением (9). При NTAPS = 129 произведений 65, и дереву нужно ⌈log2 65⌉ = 7 уровней: латентность становится 10.
  3. Арифметика даёт 33 умножителя на канал, 66 на I и Q. Out-of-context прогон Vivado для этого RTL показывает 96 DSP48E1 (отчёт Vivado блока 5): синтез не всегда раскладывает проект так, как считаешь на бумаге, поэтому курс приводит измеренные числа. При свёртке на 8 тактов на отсчёт: ⌈33/8⌉ = 5 умножителей на канал, около 10 на оба. Ещё лучше: большинство входов это вставленные нули, и полифазная версия из Лабораторной 5.7 использует 14 DSP48E1 на повышающий дискретизатор и фильтр вместе.

Чек-лист отчёта

  • Показано, что один и тот же rrc_taps_q15.txt питает и Simulink, и RTL.
  • Указаны ширина аккумулятора и правило округления.
  • Объяснено, почему NTAPS = 65 требует больше, чем учебная 4-коэффициентная архитектура.
  • Приложен лог PASS самопроверяющегося testbench.
  • Указано, какой блок следующий: TX gain / кадрирование или согласованный фильтр RX.

Шаблон инженерного вывода

RTL BPSK TX FIR принимает общие символы Q1.15 Блока 11 и 65 коэффициентов RRC.
Проект использует 40-битный аккумулятор и округляет обратно в Q1.15 с насыщением.
Теперь этот блок — опорная точка формирования импульса между маппером символов и будущим передающим трактом Zynq.