exponenta event banner

Преобразование БИХ-фильтров с плавающей и фиксированной точками

В этом примере показано, как использовать приложение Fixed-Point Converter для преобразования фильтра IIR из реализации с плавающей запятой в реализацию с фиксированной запятой. Структуры второго порядка (также называемые биквадратичными) работают лучше при использовании арифметики с фиксированной точкой, чем структуры, которые реализуют передаточную функцию непосредственно. Мы покажем, что самый верный путь к успешному преобразованию «float-to-fixed» состоит из следующих шагов:

  • Выберите структуру секций второго порядка (SOS), т.е. dsp. BiquadFilter

  • Выполнить динамический анализ диапазона для каждого узла фильтра, т.е. использовать метод испытательного стенда с минимальным и максимальным измерительными приборами моделирования.

  • Сравнение альтернативных реализаций биквадратического масштабирования и просмотр эффектов квантования из-за различных вариантов с использованием «fvtool» и dsp. Анализатор производительности для анализа и проверки.

Введение

Эффективным способом реализации фильтра БИХ является использование структуры фильтра Biquad секции второго порядка (SOS). Предположим, например, что нам нужно удалить помехи высокочастотного тонального сигнала из системы. Одним из способов достижения этого является использование конструкции фильтра нижних частот.

Проектирование низкочастотного эллиптического фильтра

Для целей данного примера используйте конструкцию эллиптической прямой формы I минимального порядка. Проектные характеристики фильтра:

  • Частотный фронт полосы пропускания: 0,4 * pi

  • Граница частоты стоп-полосы: 0,45 * pi

  • Пульсация полосы пропускания: 0,5 дБ

  • Затухание полосы останова: 80 дБ

Визуализируйте совокупный отклик фильтра для всех секций второго порядка с помощью инструмента визуализации фильтра.

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, B, A) для сравнения с плавающей запятой и фиксированной

Следует отметить, что значения коэффициентов фильтра 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

Преобразование функции Biquad IIR-фильтра с плавающей запятой в функцию Fixed-Point

Вместо того, чтобы полагаться на настройки фиксированной точки по умолчанию для объекта, преобразуйте объект в фиксированную точку с помощью приложения преобразователя фиксированной точки. Этот подход дает больше видимости и контроля над отдельными типами фиксированной точки в рамках реализации фильтра и приводит к более правильной работе с фиксированной точкой.

Чтобы сначала подготовиться к использованию Fixed-Point Converter App, создайте функцию для преобразования, установив для всех типов данных фильтра значение «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

Преобразование в фиксированную точку с помощью приложения конвертера фиксированных точек

  • Запуск приложения преобразователя с фиксированной точкой. Существует два способа запуска инструмента: с помощью меню MATLAB APPS или с помощью команды fixedStartConverter.

  • Введите функцию для преобразования в поле Entry-Point Functions.

  • Определите входные данные путем ввода имени сценария тестового стенда.

  • Нажмите кнопку «Analyze» для сбора диапазонов путем моделирования стенда.

  • Проверьте собранные значения «Sim Min», «Sim Max» и «Предлагаемый тип».

  • Внесите необходимые изменения в поля «Предлагаемый тип».

  • Нажмите кнопку «Преобразовать», чтобы создать код с фиксированной точкой и просмотреть отчет.

Результирующая реализация MATLAB с фиксированной точкой

Генерируемая функция с фиксированной точкой реализуется следующим образом:

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 командной строки

Альтернативно преобразование с фиксированной точкой может быть автоматизировано с использованием 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}

Тестирование преобразованной реализации MATLAB с фиксированной точкой

Запустите преобразованную функцию с фиксированной точкой и просмотрите результаты ввода-вывода.

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 дБ. Таким образом, эта конструкция является хорошим кандидатом для реализации с фиксированной точкой.

Получение коэффициентов фильтра Linf-norm для сравнения с фиксированным плаванием

Следует отметить, что значения коэффициентов фильтра 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

Протестируйте преобразованный двухквадратный фильтр MATLAB с фиксированной точкой Linf-Norm

После повторного выполнения процедуры преобразования с фиксированной точкой, как описано выше, но с использованием масштабированных значений коэффициентов фильтра Linf-norm запустите новую преобразованную функцию с фиксированной точкой и просмотрите результаты ввода-вывода.

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

Уменьшенная ошибка реализации с фиксированной точкой с использованием масштабирования Linf-norm SOS

Масштабирование 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 системной Toolbox™ DSP оснащены функциями моделирования Minimum и Maximum instrumentation, которые помогают приложению Fixed-Point Converter автоматически и динамически масштабировать внутренние сигналы фильтра. Кроме того, различные «fvtool» и dsp. Исследования SpectrumAnalyzer предоставляют инструменты пользователю, чтобы выполнить проверки в каждом шаге процесса.