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

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

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

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

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

Введение

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

Создайте 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, 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

Преобразуйте функцию биквадного БИХ с плавающей точкой в функцию filter с фиксированной точкой

Вместо того, чтобы полагаться на настройки объекта с фиксированной точкой по умолчанию, преобразуйте объект в фиксированную точку с помощью приложения 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

  • Запуск Fixed-Point Converter App.Существует два способа запуска инструмента: через меню MATLAB APPS или через команду 'fixedPointConverter'.

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

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

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

  • Наблюдайте собранные значения 'Sim Min', 'Sim Max' и 'Proposed Type'.

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

  • Нажмите 'Convert', чтобы сгенерировать код с фиксированной точкой и просмотреть отчет.

Результат реализации 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 для сравнения с плавающей точкой и фиксированной точкой

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

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

После повторного следования процедуре 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 с нормой Linf

Масштабирование 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 предоставляют пользователю инструменты для выполнения верификаций на каждом шаге процесса.