В этом примере показано, как создать код HDL для фильтра Butterworth 5-го порядка. Частота отсечки для этого фильтра очень низка относительно частоты дискретизации, что приводит к тому, что фильтр трудно сделать практичным. Кроме того, малые размеры входных (8 бит) и выходных (9 бит) слов заставляют квантованный фильтр требовать реализации масштабирования.
Используйте частоту дискретизации CD 44,1 кГц и частоту отсечки 500 Гц. Во-первых, создайте объект проектирования фильтра, затем создайте Системный объект Фильтра DF1 Biquad. Наконец, изучите отклик в логарифмической частоте с помощью fvtool.
Fs = 44100; F3db = 500; filtdes = fdesign.lowpass('n,f3db', 5, F3db, Fs); butterFilter = design(filtdes,'butter',... 'SystemObject',true,'FilterStructure','df1sos'); fvtool(butterFilter,'Fs',Fs,'FrequencyScale','log');

Примените параметры фиксированной точки к объекту фильтра. Предположим, что 9-разрядные выходные данные с фиксированной точкой содержат 12-разрядные коэффициенты, 20-разрядные состояния, продукты полной точности и 32-разрядные сумматоры. Проверьте ответ с помощью fvtool.
butterFilter.NumeratorCoefficientsDataType = 'Custom'; butterFilter.CustomNumeratorCoefficientsDataType = numerictype([],12); butterFilter.CustomDenominatorCoefficientsDataType = numerictype([],12); butterFilter.CustomScaleValuesDataType = numerictype([],12); butterFilter.SectionInputDataType = 'Custom'; butterFilter.CustomSectionInputDataType = numerictype([],20,15); butterFilter.SectionOutputDataType = 'Custom'; butterFilter.CustomSectionOutputDataType = numerictype([],20,15); butterFilter.NumeratorProductDataType = 'Full precision'; butterFilter.DenominatorProductDataType = 'Full precision'; butterFilter.NumeratorAccumulatorDataType = 'Custom'; butterFilter.CustomNumeratorAccumulatorDataType = numerictype([],32,24); butterFilter.DenominatorAccumulatorDataType = 'Custom'; butterFilter.CustomDenominatorAccumulatorDataType = numerictype([],32,25); butterFilter.OutputDataType = 'Custom'; butterFilter.CustomOutputDataType = numerictype([],9,7); butterFilter.RoundingMethod = 'nearest'; butterFilter.OverflowAction = 'wrap'; fvtool(butterFilter,'Fs',Fs,'FrequencyScale','log','Arithmetic','fixed');

На графике выше fvtool показывает, что квантованная полоса пропускания приблизительно на 2 дБ ниже желаемого отклика. Отрегулируйте длину слова коэффициента от 12 до 16, чтобы получить квантованный отклик ближе к эталонному отклику двойной точности и увеличить отклик полосы пропускания. Квантованный фильтр теперь чуть более 0,1 дБ ниже опорного фильтра.
butterFilter.CustomNumeratorCoefficientsDataType = numerictype([],16); butterFilter.CustomDenominatorCoefficientsDataType = numerictype([],16); butterFilter.CustomScaleValuesDataType = numerictype([],16); fvtool(butterFilter,'Fs',Fs,'FrequencyScale','log','Arithmetic','fixed'); axis([0 1.0 -1 1]);

Ключевым шагом для аппаратной реализации конструкции фильтра является проверка обоснованности значений шкалы и, при необходимости, корректировка значения шкалы. Сначала изучите квантованные значения шкалы относительно входной спецификации - 8-битовое значение с длиной дроби 7 бит. Поскольку первые два значения шкалы меньше, чем входные настройки, большинство входных значений квантуются. Чтобы исправить это, необходимо масштабировать фильтр.
scaless = butterFilter.ScaleValues .* 2^7; disp(scaless);
0.1588
0.1535
4.4042
128.0000
Теперь масштабируйте фильтр, используя норму бесконечности частотной области. После масштабирования все значения масштаба в данном случае равны единице.
scale(butterFilter,'Linf');
scaless = butterFilter.ScaleValues;
disp(scaless); 1.0000
1.0000
1.0000
1.0000
Начиная с правильно квантованного фильтра, генерируйте код VHDL или Verilog. Имеется возможность создания стенда VHDL или Verilog для проверки соответствия конструкции HDL фильтру MATLAB ®.
Чтобы создать Verilog, измените значение свойства TargetLanguage с VHDL на Verilog.
Поскольку полоса пропускания этого фильтра так низка относительно частоты дискретизации, пользовательский входной стимул является лучшим способом проверки реализации фильтра. Создайте тестовый вход с одним циклом с частотой от 50 до 300 Гц в течение 50 Гц.
Предположим, что 8-битный вход со знаком фиксированной точки имеет 7 бит дроби.
Создайте стенд тестирования VHDL, чтобы убедиться, что результаты точно соответствуют результатам MATLAB.
Создайте временную рабочую папку. Создайте код VHDL для фильтра и стенда тестирования VHDL, чтобы убедиться, что результаты точно соответствуют результатам MATLAB.
Откройте созданный файл VHDL для фильтра в редакторе.
workingdir = tempname; userstim = []; for n = [50, 100, 150, 200, 250, 300] userstim = [userstim,sin(2*pi*n/Fs*(0:Fs/n))]; %#ok end generatehdl(butterFilter,'Name','hdlbutter',... 'TargetLanguage','VHDL',... 'TargetDirectory',workingdir, ... 'GenerateHDLTestbench','on', ... 'TestBenchUserStimulus',userstim, ... 'InputDataType',numerictype(1,8,7));
### Starting VHDL code generation process for filter: hdlbutter ### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook1/tp444233f3_9928_41c3_b966_49741c6a18e9/hdlbutter.vhd ### Starting generation of hdlbutter VHDL entity ### Starting generation of hdlbutter VHDL architecture ### First-order section, # 1 ### Second-order section, # 2 ### Second-order section, # 3 ### Successful completion of VHDL code generation process for filter: hdlbutter ### HDL latency is 2 samples ### Starting generation of VHDL Test Bench. ### Generating input stimulus ### Done generating input stimulus; length 2166 samples. ### Generating Test bench: /tmp/BR2021ad_1655202_180016/mlx_to_docbook1/tp444233f3_9928_41c3_b966_49741c6a18e9/hdlbutter_tb.vhd ### Creating stimulus vectors ... ### Done generating VHDL Test Bench.
edit(fullfile(workingdir,'hdlbutter.vhd')); % Open the generated VHDL test bench in the editor. edit(fullfile(workingdir,'hdlbutter_tb.vhd'));
Код HDL и тестовый стенд могут быть дополнительно сгенерированы с помощью команды FDHDLTOOL, которая открывает диалоговое окно, позволяющее настраивать и генерировать код Verilog или VHDL и тестовые стенды для квантованного фильтра.
Графический интерфейс пользователя настраивается на 'butterFilter' таким образом, что для установки доступны только соответствующие виджеты. Для создания кода HDL и тестового стенда необходимо сначала перейти в рабочий каталог, а затем вызвать команду FDHDLTOOL.
fdhdltool(butterFilter,numerictype(1,8,7));
Можно изменить настройки по умолчанию и нажать кнопку «Создать» для создания ЛПВП и/или тестового стенда.
На следующем экране показан симулятор ModelSim HDL после запуска тестового стенда VHDL. Сравните результат ModelSim с результатом MATLAB ниже.
xrange = (0:length(userstim) - 1); y = butterFilter(fi(userstim.',1,8,7)); subplot(2,1,1); plot(xrange, userstim); axis([0 length(userstim) -1.1 1.1]); title('HDL Butterworth Filter In Stimulus.'); xlabel('Sample #'); subplot(2,1,2); plot(xrange, y); axis([0 length(userstim) -1.1 1.1]); title('HDL Butterworth Filter Out Response.'); xlabel('Sample #');

Вы разработали фильтр Butterworth, соответствующий данной спецификации. Затем вы квантовали фильтр и обнаружили, что требование полосы пропускания не было выполнено. Реквантация коэффициентов и масштабирование фильтра устранили эту проблему. Затем был создан код VHDL для фильтра и тестового стенда VHDL.
Для проверки этих результатов можно использовать симулятор ModelSim HDL. Можно также экспериментировать с VHDL и Verilog как для фильтров, так и для испытательных стендов.