В этом примере показано, как использовать Приложение Fixed-Point Converter для преобразования БИХ из реализации с плавающей точкой в реализацию с фиксированной точкой. Секции второго порядка (также называемые биквадратическими) структуры работают лучше при использовании арифметики с фиксированной точкой, чем структуры, которые реализуют передаточную функцию непосредственно. Мы покажем, что самый верный путь к успешному «плавающему» преобразованию состоит из следующих шагов:
Выберите структуру Секций второго порядка (SOS), т.е. dsp. BiquadFilter
Выполните динамический анализ диапазона для каждого узла фильтра, т.е. используйте стендовый подход с минимумом моделирования и максимумом моделирования КИП
Сравните альтернативные реализации биквадратичного масштабирования и просмотрите эффекты квантования из-за различных вариантов использования 'fvtool' и dsp. SpectrumAnalyzer для анализа и верификации.
Эффективным способом реализации БИХ является использование структуры Биквадского фильтра секции второго порядка (SOS). Предположим для примера, что нам нужно удалить мешающий высокой частоте тональный сигнал из системы. Один из способов добиться этого - использовать lowpass создание фильтра.
Используйте lowpass lowpass минимального порядка Elliptic Direct-Form I для целей этого примера. К проекту спецификаций фильтра относятся:
Ширина полосы пропускания: 0.4 * pi
Граница частоты стоп-диапазона: 0.45 * pi
Неравномерность в полосе пропускания: 0,5 дБ
Затухание в полосе задерживания: 80 дБ
Визуализируйте совокупную фильтрующую характеристику всех секций второго порядка с помощью Filter Visualization Tool.
biquad = design(fdesign.lowpass('Fp,Fst,Ap,Ast',0.4,0.45,0.5,80), ... 'ellip','FilterStructure','df1sos','SystemObject',true); fvt = fvtool(biquad,'Legend','on'); fvt.SosviewSettings.View = 'Cumulative';
Обратите внимание, что значения коэффициентов фильтра SOS приводят к почти идентичной фильтрующей характеристики (будь то двойные или 16-битные значения с фиксированной точкой).
sosMatrix = biquad.SOSMatrix; sclValues = biquad.ScaleValues; fvt_comp = fvtool(sosMatrix,fi(sosMatrix,1,16)); legend(fvt_comp,'Floating-point (double) SOS','Fixed-point (16-bit) SOS'); b = repmat(sclValues(1:(end-1)),1,3) .* sosMatrix(:,(1:3)); a = sosMatrix(:,(5:6)); num = b'; % matrix of scaled numerator sections den = a'; % matrix of denominator sections
close(fvt); % clean up close(fvt_comp); % clean up
Проверьте операцию фильтра путем потоковой передачи через него некоторых данных и просмотра его входно-выходного отклика. Сначала попробуйте фильтровать (с плавающей точкой) псевдослучайный сигнал шума (дискретизированный с частотой 300 Гц) с мешающим аддитивным высокочастотным тоном, чтобы увидеть, удален ли тон. Это также будет служить нашему опорному сигналу для испытательного стенда.
Wo = 75/(300/2); % 75 Hz tone; system running at 300 Hz inp_len = 4000; % Number of input samples (signal length) inp_itf = 0.5 .* sin((pi*Wo) .* (0:(inp_len-1))'); % tone interferer scope = dsp.SpectrumAnalyzer('SampleRate',300, ... 'PlotAsTwoSidedSpectrum',false, ... 'ShowLegend',true,'YLimits',[-85 25], ... 'Title','Floating-Point Input Signal and Filter Output Signal', ... 'ChannelNames',{'Floating-Point Input','Filter Output'}); rng(12345); % seed the rng for repeatable results biquadLPFiltFloat = dsp.BiquadFilter('SOSMatrixSource','Input port', ... 'ScaleValuesInputPort',false); for k = 1:10 inp_sig = rand(inp_len,1) - 0.5; % random values in range (-0.5, 0.5) input = inp_sig + inp_itf; % combined input signal, range (-1.0, 1.0) out_1 = biquadLPFiltFloat(input,num,den); % filter scope([input,out_1]) % visualize input and filtered output end
clear scope biquadLPFiltFloat; % clean up
Теперь запустите некоторые данные с фиксированной точкой через фильтры, используя настройки объекта по умолчанию. Обратите внимание, что поведение с фиксированной точкой по умолчанию приводит к неправильным результатам.
scope = dsp.SpectrumAnalyzer('SampleRate',300, ... 'PlotAsTwoSidedSpectrum',false, ... 'ShowLegend',true,'YLimits',[-85 25], ... 'Title','Fixed-Point Input Signal and Filter Output Signal', ... 'ChannelNames', ... {'Fixed-Point Input','Default (Incorrect) Fixed-Point Output'}); rng(12345); % seed the rng for repeatable results bqLPFiltFixpt = dsp.BiquadFilter('SOSMatrixSource','Input port', ... 'ScaleValuesInputPort',false); for k = 1:10 inp_sig = rand(inp_len,1) - 0.5; % random values in range (-0.5, 0.5) inputFi = fi(inp_sig + inp_itf, 1, 16, 15); % signal range (-1.0, 1.0) out_2 = bqLPFiltFixpt(inputFi,fi(num,1,16),fi(den,1,16)); scope([inputFi,out_2]) % visualize end
clear scope bqLPFiltFixpt; % clean up
Вместо того, чтобы полагаться на настройки объекта с фиксированной точкой по умолчанию, преобразуйте объект в фиксированную точку с помощью приложения Fixed-Point Converter App.Этот подход дает больше видимости и контроля над отдельными фиксированными точками в реализации фильтра и приводит к более правильной операции с фиксированной точкой.
Чтобы сначала подготовиться к использованию приложения Fixed-Point Converter, создайте функцию для преобразования, задав для всех вариантов типа данных фильтра значение «Custom»:
type myIIRLowpassBiquad;
function output = myIIRLowpassBiquad(inp,num,den) %myIIRNotchBiquad Biquad lowpass filter implementation % Used as part of a MATLAB Fixed Point Converter App example. % Copyright 2016 The MathWorks, Inc. persistent bqLPFilter; if isempty(bqLPFilter) bqLPFilter = dsp.BiquadFilter( ... 'SOSMatrixSource', 'Input port', ... 'ScaleValuesInputPort', false, ... 'SectionInputDataType', 'Custom', ... 'SectionOutputDataType', 'Custom', ... 'NumeratorProductDataType', 'Custom', ... 'DenominatorProductDataType', 'Custom', ... 'NumeratorAccumulatorDataType', 'Custom', ... 'DenominatorAccumulatorDataType', 'Custom', ... 'StateDataType', 'Custom', ... 'OutputDataType', 'Custom'); end output = bqLPFilter(inp, num, den); end
Создайте испытательный стенд для моделирования и сбора минимальных значений симуляции с прибором и симуляции для всех наших путей управляемого сигнала типа данных. Это позволит инструменту позже предложить автоматические настройки фиксированной точки. Используйте части кода выше в качестве испытательного стенда скрипта, начиная с входов с плавающей точкой и проверяя испытательный стенд перед симуляцией и сбором минимальных и максимальных данных. Затем используйте Приложение Fixed-Point Converter, чтобы преобразовать реализацию функции с плавающей точкой в реализацию функции с фиксированной точкой.
type myIIRLowpassBiquad_tb.m;
%% Test Bench for myIIRLowpassBiquad.m % Copyright 2016 The MathWorks, Inc. %% Pre-designed filter (coefficients stored in MAT file): % f = design(fdesign.lowpass('Fp,Fst,Ap,Ast',0.4,0.45,0.5,80), ... % 'ellip', 'FilterStructure', 'df1sos','SystemObject',true); % sosMatrix = f.SOSMatrix; % sclValues = f.ScaleValues; % b = repmat(sclValues(1:(end-1)),1,3) .* sosMatrix(:,(1:3)); % a = sosMatrix(:,(5:6)); % num = b'; % den = a'; % save('myIIRLowpassBiquadDesign.mat', 'b', 'a', 'num', 'den'); load('myIIRLowpassBiquadDesign.mat'); %% Interference signal, using values in range (-0.5, 0.5) Wo = 75/(300/2); % 75 Hz tone; system running at 300 Hz inp_len = 4000; sinTvec = (0:(inp_len-1))'; inp_itf = 0.5 .* sin((pi*Wo) .* sinTvec); %% Filtering and visualization % Filter an input signal, including an interference % tone, to see if the tone is successfully removed. rng(12345); % seed the rng for repeatable results scope = dsp.SpectrumAnalyzer('SampleRate',300,... 'PlotAsTwoSidedSpectrum',false,'ShowLegend',true,'YLimits',[-125 25],... 'Title','Input Signal and Filter Output Signal', ... 'ChannelNames', {'Input', 'Filter Output'}); for k = 1:10 inp_sig = rand(inp_len,1) - 0.5; % random values in range (-0.5, 0.5) inp = inp_sig + inp_itf; out_1 = myIIRLowpassBiquad(inp,num,den); % filter scope([inp,out_1]); % visualize end
Запуск Fixed-Point Converter App.Существует два способа запуска инструмента: через меню MATLAB APPS или через команду 'fixedPointConverter'.
Введите функцию для преобразования в поле Entry-Point Functions.
Определите входы путем ввода имени испытательного стенда скрипта.
Нажмите 'Analyze', чтобы собрать области значений путем моделирования испытательного стенда.
Наблюдайте собранные значения 'Sim Min', 'Sim Max' и 'Proposed Type'.
Внесите необходимые корректировки в поля 'Предлагаемый тип'.
Нажмите 'Convert', чтобы сгенерировать код с фиксированной точкой и просмотреть отчет.
Реализация сгенерированной функции с фиксированной точкой выглядит следующим образом:
type myIIRLowpassBiquad_fixpt;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % Generated by MATLAB 9.3 and Fixed-Point Designer 6.0 % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %#codegen function output = myIIRLowpassBiquad_fixpt(inp,num,den) %myIIRNotchBiquad Biquad lowpass filter implementation % Used as part of a MATLAB Fixed Point Converter App example. % Copyright 2016 The MathWorks, Inc. fm = get_fimath(); persistent bqLPFilter; if isempty(bqLPFilter) bqLPFilter = dsp.BiquadFilter( ... 'SOSMatrixSource', 'Input port', ... 'ScaleValuesInputPort', false, ... 'SectionInputDataType', 'Custom', ... 'SectionOutputDataType', 'Custom', ... 'NumeratorProductDataType', 'Custom', ... 'DenominatorProductDataType', 'Custom', ... 'NumeratorAccumulatorDataType', 'Custom', ... 'DenominatorAccumulatorDataType', 'Custom', ... 'StateDataType', 'Custom', ... 'OutputDataType', 'Custom' , 'CustomSectionInputDataType', numerictype([], 16, 8), 'CustomSectionOutputDataType', numerictype([], 16, 8), 'CustomNumeratorProductDataType', numerictype([], 32, 26), 'CustomDenominatorProductDataType', numerictype([], 32, 23), 'CustomNumeratorAccumulatorDataType', numerictype([], 32, 24), 'CustomDenominatorAccumulatorDataType', numerictype([], 32, 23), 'CustomStateDataType', numerictype([], 16, 8), 'CustomOutputDataType', numerictype([], 16, 15)); end output = fi(bqLPFilter(inp, num, den), 1, 16, 15, fm); end function fm = get_fimath() fm = fimath('RoundingMethod', 'Floor',... 'OverflowAction', 'Wrap',... 'ProductMode','FullPrecision',... 'MaxProductWordLength', 128,... 'SumMode','FullPrecision',... 'MaxSumWordLength', 128); end
В качестве альтернативы преобразование с фиксированной точкой может быть автоматизировано с помощью API командной строки:
type myIIRLowpassF2F_prj_script;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Script generated from project 'myIIRLowpassBiquad.prj' on 16-Oct-2014. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Create configuration object of class 'coder.FixPtConfig'. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% cfg = coder.config('fixpt'); cfg.TestBenchName = { sprintf('S:\\Work\\15aFeatureExamples\\biquad_notch_f2f\\myIIRLowpassBiquad_tb.m') }; cfg.DefaultWordLength = 16; cfg.LogIOForComparisonPlotting = true; cfg.TestNumerics = true; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Define argument types for entry-point 'myIIRLowpassBiquad'. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ARGS = cell(1,1); ARGS{1} = cell(3,1); ARGS{1}{1} = coder.typeof(0,[4000 1]); ARGS{1}{2} = coder.typeof(0,[3 5]); ARGS{1}{3} = coder.typeof(0,[2 5]); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Invoke MATLAB Coder. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% codegen -float2fixed cfg myIIRLowpassBiquad -args ARGS{1}
Запустите преобразованную функцию с фиксированной точкой и просмотрите результаты ввода-вывода.
scope = dsp.SpectrumAnalyzer('SampleRate',300, ... 'PlotAsTwoSidedSpectrum',false, ... 'ShowLegend',true,'YLimits',[-85 25], ... 'Title','Fixed-Point Input Signal and Filter Output Signal', ... 'ChannelNames',{'Fixed-Point Input','Fixed-Point Filter Output'}); rng(12345); % seed the rng for repeatable results for k = 1:10 inp_sig = rand(inp_len,1) - 0.5; % random values in range (-0.5, 0.5) inputFi = fi(inp_sig + inp_itf, 1, 16, 15); % signal range (-1.0, 1.0) out_3 = myIIRLowpassBiquad_fixpt(inputFi,fi(num,1,16),fi(den,1,16)); scope([inputFi,out_3]) % visualize end
clear scope; % clean up
Ошибка между выходами с плавающей и фиксированной точками показана на следующем графике. Ошибка кажется довольно высокой. Причиной этих различий в выходных значениях является выбор масштабирования и упорядоченного расположения секций второго порядка. В следующем разделе мы иллюстрируем способ уменьшить эту ошибку раньше в реализации.
fig = figure; subplot(3,1,1); plot(out_1); title('Floating-point filter output'); subplot(3,1,2); plot(out_3); title('Fixed-point filter output'); subplot(3,1,3); plot(out_1 - double(out_3)); axis([0 4000 -4e-2 7e-2]); title('Error');
close(fig); % clean up
Создания эллиптического фильтра имеют характеристику относительно хорошего масштабирования при использовании масштабирования секции второго порядка 'Linf' (то есть норма по бесконечности). Использование этого подхода часто приводит к меньшим ошибкам квантования.
biquad_Linf = design(fdesign.lowpass('Fp,Fst,Ap,Ast',0.4,0.45,0.5,80), ... 'ellip','FilterStructure','df1sos', ... 'SOSScaleNorm','Linf','SystemObject',true); fvt_Linf = fvtool(biquad_Linf,'Legend','on'); fvt_Linf.SosviewSettings.View = 'Cumulative';
Заметьте, что ни одна из совокупных внутренних частотных характеристик, измеренных от входа в фильтр до различных состояний каждой секции, не превышает 0 дБ. Таким образом, этот проект является хорошим кандидатом для реализации с фиксированной точкой.
Обратите внимание, что значения коэффициентов фильтра SOS приводят к почти идентичной фильтрующей характеристики (будь то двойные или 16-битные значения с фиксированной точкой).
sosMtrLinf = biquad_Linf.SOSMatrix; sclValLinf = biquad_Linf.ScaleValues; fvt_comp_Linf = fvtool(sosMtrLinf,fi(sosMtrLinf,1,16)); legend(fvt_comp_Linf,'Floating-point (double) SOS, Linf Scaling', ... 'Fixed-point (16-bit) SOS, Linf Scaling'); bLinf = repmat(sclValLinf(1:(end-1)),1,3) .* sosMtrLinf(:,(1:3)); aLinf = sosMtrLinf(:,(5:6)); numLinf = bLinf'; % matrix of scaled numerator sections denLinf = aLinf'; % matrix of denominator sections
close(fvt_Linf); % clean up close(fvt_comp_Linf); % clean up
После повторного следования процедуре Fixed-Point Converter, как и выше, но используя значения масштабированного фильтра Linf-нормы, запустите новую преобразованную функцию с фиксированной точкой и просмотрите результаты ввода-вывода.
scope = dsp.SpectrumAnalyzer('SampleRate',300, ... 'PlotAsTwoSidedSpectrum',false,'ShowLegend',true, ... 'YLimits',[-85 25],'Title', ... 'Fixed-Point Input Signal and Linf-Norm Filter Output Signal', ... 'ChannelNames', ... {'Fixed-Point Input','Fixed-Point Linf-Norm Filter Output'}); rng(12345); % seed the rng for repeatable results for k = 1:10 inp_sig = rand(inp_len,1) - 0.5; % random values in range (-0.5, 0.5) inputFi = fi(inp_sig + inp_itf, 1, 16, 15); % signal range (-1.0, 1.0) out_4 = myIIRLinfBiquad_fixpt( ... inputFi,fi(numLinf,1,16),fi(denLinf,1,16)); scope([inputFi,out_4]) % visualize end
clear scope; % clean up
Масштабирование SOS с нормой по бесконечности часто приводит к выходам с меньшей ошибкой.
fig1 = figure; subplot(3,1,1); plot(out_1); title('Floating-point filter output'); subplot(3,1,2); plot(out_4); title('Fixed-point (Linf-norm SOS) filter output'); subplot(3,1,3); plot(out_1 - double(out_4)); axis([0 4000 0 1e-3]); title('Error');
fig2 = figure; subplot(2,1,1); plot(out_1 - double(out_3)); axis([0 4000 -4e-2 7e-2]); title('Fixed-point error (default SOS filter scaling)'); subplot(2,1,2); plot(out_1 - double(out_4)); axis([0 4000 0 1e-3]); title('Fixed-point error (''Linf'' SOS filter scaling)');
close(fig1); % clean up close(fig2); % clean up
Мы наметили процедуру для преобразования БИХ с плавающей точкой в реализацию с фиксированной точкой. dsp. Объекты BiquadFilter DSP System Toolbox™ оснащены возможностями Simulation Minimum и Maximum instrumentation, которые помогают приложению Fixed-Point Converter автоматически и динамически масштабировать внутренние фильтрующие сигналы. Кроме того, различные 'fvtool' и dsp. Анализы SpectrumAnalyzer предоставляют пользователю инструменты для выполнения верификаций на каждом шаге процесса.