Этот пример иллюстрирует, как генерировать код HDL для фильтра FIR с интерфейсом процессора для загрузки коэффициентов. Фильтр может быть запрограммирован на любой желаемый отклик путем загрузки коэффициентов во внутреннюю память коэффициентов с использованием интерфейса процессора.
Предположим, что нам нужно реализовать банк фильтров, имеющих разные ответы, на чипе. Если все фильтры имеют структуру FIR прямой формы и одинаковую длину, то мы можем использовать интерфейс процессора для загрузки коэффициентов для каждого ответа из ОЗУ или файла регистра, когда это необходимо.
Эта конструкция добавит задержку в несколько циклов, прежде чем входные выборки могут быть обработаны с загруженными коэффициентами. Однако преимущество состоит в том, что одно и то же оборудование фильтра может быть запрограммировано с новыми коэффициентами для получения другого отклика фильтра. Это экономит площадь кристалла, поскольку в противном случае каждый фильтр будет реализован отдельно на кристалле.
В этом примере мы рассмотрим два фильтра FIR, один с откликом верхних частот, а другой с откликом нижних частот. Мы покажем, как одно и то же оборудование фильтра может быть запрограммировано для каждого ответа, загрузив соответствующий набор коэффициентов. Мы создадим код VHDL для фильтра и покажем два ответа, используя созданный стенд тестирования VHDL.
Создайте объект конструкции фильтра нижних частот, а затем объект системы фильтров FIR (Hlp). Затем преобразуйте его, чтобы создать объект FIR Filter System с откликом верхних частот (Hhp).
Fpass = 0.45; % Passband Frequency Fstop = 0.55; % Stopband Frequency Apass = 1; % Passband Attenuation (dB) Astop = 60; % Stopband Attenuation (dB) f = fdesign.lowpass('Fp,Fst,Ap,Ast',Fpass,Fstop,Apass,Astop); lpFilter = design(f, 'equiripple','FilterStructure', 'dfsymfir','SystemObject',true); % Lowpass hpcoeffs = firlp2hp(lpFilter.Numerator); hpFilter = dsp.FIRFilter('Numerator', hpcoeffs); % Highpass
Предположим, что коэффициенты должны быть сохранены в памяти шириной 14 битов. Используя эту информацию, примените настройки фиксированной точки к фильтру объектов системы.
lpFilter.FullPrecisionOverride=false; lpFilter.CoefficientsDataType='Custom'; lpFilter.CustomCoefficientsDataType=numerictype(1,14,13); lpFilter.OutputDataType='Same as Accumulator'; lpFilter.ProductDataType='Full precision'; lpFilter.AccumulatorDataType='Full precision'; hpFilter.FullPrecisionOverride=false; hpFilter.CoefficientsDataType='Custom'; hpFilter.CustomCoefficientsDataType=numerictype(1,14,13); hpFilter.OutputDataType='Same as Accumulator'; hpFilter.ProductDataType='Full precision'; hpFilter.AccumulatorDataType='Full precision';
После применения настроек фиксированной точки важно убедиться, что фильтр системных объектов по-прежнему соответствует спецификациям. Мы будем использовать функцию «measure», чтобы проверить, верно ли это.
measure(lpFilter,'Arithmetic','fixed')
ans = Sample Rate : N/A (normalized frequency) Passband Edge : 0.45 3-dB Point : 0.46957 6-dB Point : 0.48314 Stopband Edge : 0.55 Passband Ripple : 0.89243 dB Stopband Atten. : 55.3452 dB Transition Width : 0.1
Генерировать линейный сигнал стимула со сдвигаемой частотой, используя чирп. Используйте этот входной стимул для фильтрации сначала через фильтр FIR нижних частот. Затем измените коэффициенты фильтра, чтобы получить отклик верхних частот, и снова используйте ту же самую входную выборку для фильтрации.
Для вышеописанной двухэтапной операции фильтрации наша цель состоит в том, чтобы сравнить выходные данные фильтра из MATLAB ® с выходными данными из сгенерированного кода HDL.
Печать входных выборок и отфильтрованных выходных данных показывает поведение нижних и верхних частот.
x = chirp(0:199,0,199,0.4); lpcoeffs = lpFilter.Numerator; % store original lowpass coefficients y1 = lpFilter(fi(x,1,14,13).'); % filter the signal lpFilter.Numerator = hpFilter.Numerator; % load the highpass filter coefficients y2 = lpFilter(fi(x,1,14,13).'); % filter the signal y = [y1; y2]; % concatenate output signals lpFilter.Numerator = lpcoeffs; % restore original lowpass coefficients subplot(2,1,1);plot([x,x]); xlabel('Time [samples]');ylabel('Amplitude'); title('Input Stimulus'); subplot(2,1,2);plot(y); xlabel('Time [samples]');ylabel('Amplitude'); title('Filtered Output');

Для квантованного фильтра нижних частот мы создадим VHDL-код с интерфейсом процессора, установив свойству 'ExecutionSource' значение 'ProcessorInterface'. В результате генерируемый код будет иметь дополнительные порты для сигналов write_address, write_enable, coeffs_in и write_done. Этот интерфейс может использоваться для загрузки коэффициентов из хост-процессора во внутренний файл регистров. ЛПВП имеет дополнительный теневой регистр, который обновляется из файла регистра, когда сигнал «write _ done» является высоким. Это позволяет одновременно загружать и обрабатывать данные объектом фильтра.
Чтобы убедиться, что объект фильтра может быть последовательно загружен двумя различными наборами коэффициентов фильтра, мы создадим стенд тестирования VHDL. Во-первых, испытательный стенд загружает коэффициенты нижних частот и обрабатывает входные выборки. Затем испытательный стенд загружает коэффициенты, соответствующие отклику фильтра верхних частот, и снова обрабатывает входные выборки.
Сгенерированный код VHDL и стенд тестирования VHDL можно скомпилировать и смоделировать с помощью имитатора HDL, такого как ModelSim ®. Обратите внимание, что загрузка второго набора коэффициентов и обработка последних нескольких входных выборок выполняются одновременно .
Чтобы создать необходимый стенд тестирования, мы задаем свойству «GenerateHDLTestbench» значение «on» и передаем «TestbenchCoeffStimulus» в вызове команды generatehdl. Значение, переданное для TestbenchCoeffStimulus, является вектором коэффициентов, которые должны использоваться для последующей обработки входных выборок. Этот пример проходит в векторе коэффициентов, соответствующих фильтру верхних частот.
Предположим, что из-за требований к фиксированному тракту данных входного АЦП необходим 14-битный вход с фиксированной точкой со знаком с точностью 13 бит.
%As the symmetric structure is selected, the field 'TestbenchCoeffStimulus' % has to be the half of length of filter. workingdir = tempname; generatehdl(lpFilter,'Name','FilterProgrammable', ... 'InputDataType',numerictype(1,14,13), ... 'TargetLanguage','VHDL', ... 'TargetDirectory',workingdir, ... 'CoefficientSource','ProcessorInterface', ... 'GenerateHDLTestbench','on', ... 'TestBenchUserStimulus',x, ... 'TestbenchCoeffStimulus',hpFilter.Numerator(1:(length(hpFilter.Numerator)+1)/2));
### Starting VHDL code generation process for filter: FilterProgrammable ### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook2/tpbad7135e_7548_417b_b71e_9b88e8520eb7/FilterProgrammable.vhd ### Starting generation of FilterProgrammable VHDL entity ### Starting generation of FilterProgrammable VHDL architecture ### Successful completion of VHDL code generation process for filter: FilterProgrammable ### HDL latency is 2 samples ### Starting generation of VHDL Test Bench. ### Generating input stimulus ### Done generating input stimulus; length 200 samples. ### Generating Test bench: /tmp/BR2021ad_1655202_180016/mlx_to_docbook2/tpbad7135e_7548_417b_b71e_9b88e8520eb7/FilterProgrammable_tb.vhd ### Creating stimulus vectors ... ### Done generating VHDL Test Bench.
На следующем экране показан симулятор ModelSim HDL после выполнения сгенерированных сценариев .do файла для тестового стенда. Сравните результат ModelSim с результатом MATLAB, как было нанесено на график ранее.

Мы разработали фильтры FIR верхних и нижних частот в соответствии с заданными спецификациями. Затем мы квантовали фильтр и генерировали код VHDL для фильтра с интерфейсом для загрузки коэффициентов из процессора. Затем мы создали испытательный стенд VHDL, который показал обработку входных выборок после загрузки коэффициентов нижних частот, повторив операцию с коэффициентами верхних частот. Мы показали, как генерировать код VHDL, реализующий аппаратные средства фильтрации, которые могут многократно использоваться для различных ответов при загрузке различных наборов коэффициентов через интерфейс порта из хост-процессора.