Реализация базовых компонентов ЦОС: КИХ фильтр
Представленный материал является частью цикла статей, в которых рассматривается RTL реализация базовых компонентов цифровой обработки сигналов. В качестве языка описания используется VHDL-2008, проектирование ведется с учетом особенностей ПЛИС фирмы Xilinx. Для написания тестовых окружений используется UVM.
Исходные коды из статьи выложены на гитхабе (см ссылки в конце статьи)
Скачать статью в формате PDF
Содержание
1 Аннотация
В данной статье рассматриваются особенности реализации одного из базовых компонентов цифровой обработки сигналов – фильтра с конечной импульсной характеристикой. Разобраны отличия практической реализации базовой архитектуры КИХ фильтра от теоретической модели. Представлено RTL описание параметризируемого модуля на языке VHDL-2008. Представлено описание верификационного окружения для RTL модуля с использованием UVM.
2 Теоретическая часть
КИХ фильтр (фильтр с конечной импульсной характеристикой) – один из видов линейных цифровых фильтров, характерной особенностью которого является ограниченность по времени его импульсной характеристики. Выходной сигнал КИХ фильтра описывается уравнением 1:
N−1
y(k) = ∑︁ a(n)× x(k − n), где (1)
n=0
x(k) – отсчеты входного сигнала; y(k) – отсчеты выходного сигнала; a(n) – коэффициенты фильтра;
N – количество коэффициентов фильтра.
труктурная схема КИХ фильтра в простейшем виде представлена на рисунке 2.1.
Рисунок 2.1 – Структурная схема КИХ фильтра, N = 4
Как видно из данной схемы, для реализации КИХ фильтра используются три элемента: умножитель, сумматор и блок задержки.
В интернете часто можно встретить прямое описание данной схемы на HDL, которое выглядит примерно следующим образом:
|
Главный недостаток такого описания: с увеличением количества коэффициентов, растет количество слагаемых в итоговой сумме. Схемотехнически это приводит к многовходовому сумматору (либо каскаду сумматоров). Очевидно, что рабочая тактовая частота такой схемы будет крайне мала.
Чтобы избавиться от многовходового аккумулятора, можно разбить схему, представленную на рисунке 2.1, на стадии. На выходе каждой стадии ставятся дополнительные триггеры. Результат такого разбиения показан на рисунке 2.2.
Рисунок 2.2 – КИХ фильтр с дополнительными триггерами
Здесь, при увеличении числа коэффициентов, будет расти количество стадий, но при этом быстродействие не будет падать. Следует помнить, что дополнительные триггеры увеличивают латентность схемы.
Добавив еще пару триггеров к схеме, представленной на рисунке 2.2 и слегка реорганизовав ее, получим схему, представленную на рисунке 2.3.
Рисунок 2.3 – КИХ фильтр, модернизированная архитектура на блоках DSP48
В результате мы получили схему, в которой все элементы КИХ фильтра укладываются внутри аппаратных блоков DSP48, что позволяет достичь для выбранного кристалла максимально возможной рабочей тактовой частоты.
3 RTL описание
3.1 Описание интерфейса компонента
Перечень параметров компонента представлен в таблице 3.1.
Таблица 3.1 – Параметры компонента
Имя | Тип | Описание |
g_nof_taps | integer | длина фильтра (количество коэффициентов) |
g_coef_dw | integer | разрядность коэффициентов |
g_sample_dw | integer | разрядность отсчетов входного сигнала |
g_iraxi_coef_dw 1 | integer | разрядность данных загрузки коэффициентов |
g_iraxi_dw 2 | integer | разрядность данных входного сигнала |
g_oraxi_dw 3 | integer | разрядность данных выходного сигнала |
Перечень портов компонента представлен в таблице 3.2.
Таблица 3.2 – Порты компонента
Имя | I/O | Тип | Описание |
iclk | in | std_logic | тактовый сигнал |
icoef_rst | in | std_logic | загрузка коэффициентов, сброс |
icoef_valid | in | std_logic | загрузка коэффициентов, валидность |
icoef_data | in | std_logic_vector[1] | загрузка коэффициентов, данные |
ivalid | in | std_logic | входной сигнал, валидность |
idata | in | std_logic_vector[2] | входной сигнал, данные |
ovalid | out | std_logic | выходной сигнал, валидность |
odata | out | std_logic_vector[3] | выходной сигнал, данные |
Временная диаграмма загрузки коэффициентов фильтра представлена на рисунке 3.4.
Рисунок 3.4 – Временная диаграмма загрузки коэффициентов фильтра
Процесс загрузки коэффициентов начинается с подачи логической ’1’ на вход icoef_rst минимум на один такт. Это приведет к сбросу внутреннего массива коэффициентов, после чего на данный вход необходимо подать логический ’0’.
Коэффициенты загружаются последовательно, начиная с нулевого, через вход icoef_d, при этом каждый коэффициент должен сопровождаться активным уровнем сигнала icoef_v.
Обрабатываемые отсчеты подаются на порт idata и сопровождаются активным уровнем сигнала ivalid.
Результат обработки выдается с выхода odata и сопровождается активным уровнем сигнала ovalid.
|
3.2 Объявление констант, типов, сигналов
Для реализации КИХ фильтра необходимо объявить константу для разрядности результатов умножения:
|
Далее объявим все необходимые типы сигналов:
|
Для простоты разрядность результатов сложений равна разрядности сумматора блока DSP48E1.
Объявим сигналы для приема данных со входных и выдачи данных на выходные порты:
|
Наконец, сигналы для реализации основной логики работы фильтра:
|
3.3 Архитектура
Подключим сигналы для приема данных со входных и выдачи данных на выходные порты:
|
Опишем процесс загрузки коэффициентов:
|
При активном сигнале сброса массив коэффициентов заполняется нулями. После снятия сброса, входные коэффициенты задвигаются в массив по сигналу валидности.
Наконец, непосредственно реализация фильтра:
|
Здесь описаны преобразования всех триггеров, представленных на рисунке 2.3.
При подаче результата умножения на сумматор, его разрядность расширяется со знаком до 48 бит.
Валидность входного сигнала транслируется на валидность выходного. Данные для выходного сигнала берутся с последнего сумматора.
4 UVM окружение
4.1 Верхний уровень
Верхним уровнем тестового окружения в данном примере является файл tb_simple_fir_filter.sv:
|
Пакет pkg_simplefir содержит ссылки на все компоненты, необходимые для реализации тестового окружения.
На верхнем уровне заданы параметры, которые соответствуют параметрам КИХ фильтра, описанным в разделе 3.1:
|
Для подключения тестируемого КИХ фильтра объявлены три интерфейса типа raxi_bfm:
|
iraxi_bfm – используется для подачи входного сигнала, разрядность данных задается параметром G_IRAXI_DW;
iraxi_bfm_coef – используется для загрузки коэффициентов, разрядность данных задается параметром G_IRAXI_DW_COEF;
oraxi_bfm – используется для считывания выходного сигнала, разрядность данных задается параметром G_ORAXI_DW.
Схема подключения тестируемого компонента показана на рисунке 4.5.
Рисунок 4.5 – Схема подключения тестируемого компонента
Все интерфейсы передаются в uvm_config_db, после чего запускается тест.
|
Для реализации параметризируемого теста, его необходимо объявить на верхнем уровне следующим образом:
|
4.2 Тест
Диаграмма классов, используемых в тесте, представлена на рисунке 4.6.
Рисунок 4.6 – Диаграмма классов теста
Класс simplefir_base_test наследуется от uvm_test.
Чтобы тест мог принимать параметры из верхнего уровня, его необходимо объявить следующим образом:
|
В тесте используются компоненты, предназначенные для работы с интерфейсом raxi_bfm и транзакциями типа raxi_seqi: секвенсеры типа raxi_seqi, драйверы типа raxi_drvr и мониторы типа raxi_mont. С их помощью обеспечивается передача данных между тестируемым КИХ фильтром и тестовым окружением через интерфейсы, которые извлекаются из uvm_config_db.
Для загрузки коэффициентов в фильтр и для подачи на него входного сигнала используются, соответственно, генераторы транзакций simplefir_seqc_coef_h и simplefir_seqc_data_h. Генераторы запускаются по очереди:
|
Для сравнения данных, полученных с выхода тестируемого КИХ фильтра, с эталонной моделью, используется чекер simplefir_scrb_h.
4.3 Генератор транзакций для загрузки коэффициентов
Диаграмма классов, используемых в генераторе транзакций, представлена на рисунке 4.7.
Рисунок 4.7 – Диаграмма классов генератора транзакций для загрузки коэффициентов
Класс simplefir_seqc_coef наследуется от uvm_sequence #(raxi_seqi).
Для формирования массива коэффициентов, которые будут загружены в фильтр, используется функция get_coefs_rcos() класса filter_design:
|
В функцию передается значение длины фильтра G_NOF_TAPS, в результате функция вернет массив действительных значений такого же размера. Для перевода коэффициентов в фиксированную точку, они домножаются на число, которое зависит от заданной разрядности G_COEF_DW.
Далее генератор создает транзакции raxi_seqi_h для загрузки фильтра согласно временной диаграмме, указанной на рисунке 3.4:
|
Схема включения генератора транзакций для загрузки коэффициентов в тест представлена на рисунке 4.8.
Рисунок 4.8 – Схема включения генератора транзакций для загрузки коэффициентов
Генератор запускается на секвенсере raxi_seqr_coef, который передает формируемые транзакции типа raxi_seqi в драйвер raxi_drvr_coef. Драйвер, в свою очередь, транслирует их на интерфейс загрузки коэффициентов iraxi_bfm_coef.
4.4 Генератор транзакций для входного сигнала
Диаграмма классов, используемых в генераторе транзакций, представлена на рисунке 4.9.
Рисунок 4.9 – Диаграмма классов генератора транзакций для входного сигнала
Класс simplefir_seqc_data наследуется от uvm_sequence #(raxi_seqi).
Генератор создает транзакции raxi_seqi_h для формирования входного сигнала:
|
Для каждой транзакции генерируется случайный сигнал валидности. В случае, если она оказалась равна ’1’, то формируется случайное значение в диапазоне −2G_SAMPLE_DW−1 ... 2G_SAMPLE_DW−1 −1.
Схема включения генератора транзакций для входного сигнала представлена на рисунке 4.10.
Рисунок 4.10 – Схема включения генератора транзакций для входного сигнала
Генератор запускается на секвенсере raxi_seqr_data, который передает формируемые транзакции типа raxi_seqi в драйвер raxi_drvr_data. Драйвер, в свою очередь, транслирует их на интерфейс подачи входного сигнала iraxi_bfm_data.
4.5 Чекер
Диаграмма классов, используемых в чекере, представлена на рисунке 4.11.
Рисунок 4.11 – Диаграмма классов чекера
Класс simplefir_scrb наследуется от raxi_scrb.
Чекер содержит порты анализа для транзакций коэффициентов iraxi_aprt_coef, входных iraxi_aprt_data и выходных oraxi_aprt_data данных. Данным портам соответствуют функции write_icoef, write_idata и write_odata соответственно.
При поступлении транзакции коэффициентов, вызывается функция add_coefficient() класса sim_simple_fir_filter. В результате коэффициенты, загружаемые в тестируемый КИХ фильтр, также загружаются и в эталонную модель.
При поступлении транзакции входных данных, она сохраняется в очередь iraxi_seqi_queue_data.
При поступлении транзакции выходных данных, она сохраняется в очередь oraxi_seqi_queue_data, после чего вызывается функция processing():
|
Для формирования эталонной транзакции вызывается функция simulate() класса sim_simple_fir_filter, в которую передается входная транзакция. Работа данной функции полностью имитирует поведение тестируемого компонента.
Для сравнения транзакций используется функций compare() класса raxi_seqi.
Схема включения чекера в тест представлена на рисунке 4.12.
Рисунок 4.12 – Схема включения чекера
Мониторы iraxi_mont_coef, iraxi_mont_data и oraxi_mont_data анализируют соответствующие интерфейсы, формируют транзакции типа raxi_seqi и передают их на соответствующие порты анализа чекера.
- 1. Исходный код КИХ фильтра
- 2. Исходный код тестового окружения
- 3. Подробнее про реализацию конвейера КИХ фильтра
- 4. Описание различных архитектур КИХ фильтра
- 5. Xilinx FIR Compiler v7.2
- 6. Описание аппаратного блока DSP48E1
- 7. UVM, реализация параметризируемых тестов
Скачать статью в формате PDF