Этот пример иллюстрирует, как сгенерировать HDL-код для 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/BR2019ad_1062519_57051/mlx_to_docbook1/tpf272d2b1_8a46_449c_8414_fcee799e597d/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/BR2019ad_1062519_57051/mlx_to_docbook1/tpf272d2b1_8a46_449c_8414_fcee799e597d/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));
Можно изменить настройки по умолчанию и нажать Generate, чтобы сгенерировать HDL и/или испытательный стенд.
Следующее отображение показывает симулятор HDL ModelSim после выполнения испытательного стенда 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 #');
Вы разработали Фильтр Баттерворта, чтобы соответствовать данной спецификации. Вы затем квантовали фильтр и обнаружили, что требование полосы пропускания не было удовлетворено. Переквантование коэффициентов и масштабирование фильтра устранили эту проблему. Вы затем сгенерировали код VHDL для фильтра и испытательного стенда VHDL.
Можно использовать симулятор HDL ModelSim, чтобы проверить эти результаты. Можно также экспериментировать с VHDL и Verilog и для фильтров и для испытательных стендов.