Этот пример иллюстрирует, как сгенерировать HDL-код для КИХ-фильтра с интерфейсом процессора для загрузки коэффициентов. Фильтр может быть запрограммирован к любому желаемому ответу путем загрузки коэффициентов во внутреннюю содействующую память с помощью интерфейса процессора.
Давайте примем, что мы должны реализовать банк фильтров, имея различные ответы, на чипе. Если все фильтры имеют КИХ-структуру прямой формы и ту же длину, то мы можем использовать интерфейс процессора, чтобы загрузить коэффициенты для каждого ответа от RAM или регистрового файла при необходимости.
Этот проект добавит задержку нескольких циклов, прежде чем входные выборки смогут быть обработаны с загруженными коэффициентами. Однако это имеет преимущество, что то же оборудование фильтра может быть запрограммировано с новыми коэффициентами, чтобы получить различный ответ фильтра. Это сохраняет область чипа, когда в противном случае каждый фильтр был бы реализован отдельно на чипе.
В этом примере мы рассмотрим два КИХ-фильтра, один с highpass ответом и другим с ответом lowpass. Мы покажем, как то же оборудование фильтра может быть запрограммировано для каждого ответа путем загрузки соответствующего набора коэффициентов. Мы сгенерируем код VHDL для фильтра и покажем эти два ответа с помощью сгенерированного испытательного стенда VHDL.
Создайте объект создания фильтра lowpass, затем создайте КИХ-Системный объект Фильтра (Hlp). Затем преобразуйте его, чтобы создать КИХ-Системный объект Фильтра с highpass ответом (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(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
Сгенерируйте линейный сигнал стимула развернутой частоты, использующий щебет. Используйте этот входной стимул в проникновении в КИХ-фильтр lowpass сначала. Затем измените коэффициенты фильтра, чтобы получить highpass ответ и использовать ту же входную выборку, чтобы отфильтровать снова.
Для вышеупомянутой операции фильтрации 2D этапа наша цель состоит в том, чтобы сравнить фильтр выход от MATLAB® с этим от сгенерированного HDL-кода.
Графический вывод входных выборок и отфильтрованного выхода показывает lowpass и highpass поведение.
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');
Для квантованного фильтра lowpass мы сгенерируем код VHDL с интерфейсом процессора путем установки свойства 'CoefficientSource' на 'ProcessorInterface'. Это приведет к сгенерированному коду, имеющему дополнительные порты для write_address, write_enable, coeffs_in, и сигналы write_done. Этот интерфейс может использоваться, чтобы загрузить коэффициенты от главного процессора во внутренний регистровый файл. HDL имеет дополнительный теневой регистр, который обновляется от регистрового файла, когда сигнал 'write_done' высок. Это включает одновременную загрузку и обработку данных сущностью фильтра.
Чтобы проверить, что сущность фильтра может последовательно загрузиться с двумя различными наборами коэффициентов фильтра, мы сгенерируем испытательный стенд VHDL. Во-первых, испытательный стенд загружает коэффициенты lowpass и обрабатывает входные выборки. Затем испытательный стенд загружает коэффициенты, соответствующие ответу фильтра highpass, и обрабатывает входные выборки снова.
Сгенерированный код VHDL и испытательный стенд VHDL могут быть скомпилированы и симулировали использование симулятора HDL, такого как ModelSim®. Заметьте, что загрузка второго набора коэффициентов и обработка последних нескольких входных выборок выполняются одновременно.
Для того, чтобы сгенерировать необходимый испытательный стенд, мы устанавливаем свойство 'GenerateHDLTestbench' на 'on' и передаем 'TestbenchCoeffStimulus' в вызове generatehdl команды. Значение, переданное в для 'TestbenchCoeffStimulus', является вектором коэффициентов, которые должны использоваться в последующей обработке входных выборок. Этот пример передает в векторе коэффициентов, соответствующих фильтру highpass.
Примите, что 14-битный вход фиксированной точки со знаком с 13 битами дробной точности необходим из-за фиксированных требований информационного канала входа ADC.
%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/BR2019bd_1276998_130124/mlx_to_docbook1/tpe256ccfa_d51e_4222_ae9f_80d2b477b4f0/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/BR2019bd_1276998_130124/mlx_to_docbook1/tpe256ccfa_d51e_4222_ae9f_80d2b477b4f0/FilterProgrammable_tb.vhd ### Creating stimulus vectors ... ### Done generating VHDL Test Bench.
Следующее отображение показывает симулятор HDL ModelSim после выполнения сгенерированных .do скриптов файла для испытательного стенда. Сравните результат ModelSim с результатом MATLAB, как построено прежде.
Мы спроектировали highpass и КИХ-фильтры lowpass, чтобы соответствовать данным спецификациям. Мы затем квантовали фильтр и сгенерировали код VHDL для фильтра с интерфейсом, чтобы загрузить коэффициенты от процессора. Мы затем сгенерировали испытательный стенд VHDL, который показал обработку входных выборок после загрузки коэффициентов lowpass, повторив операцию с highpass коэффициентами. Мы показали, как сгенерировать код VHDL, который реализует оборудование фильтра, которое является допускающим повторное использование для различных ответов, когда различные наборы коэффициентов загружаются через интерфейс порта от главного процессора.