Я разработал очень простой фильтр низких частот Баттерворта с использованием Matlab. Следующий фрагмент кода демонстрирует, что я сделал.
fs = 2.1e6;
flow = 44 * 1000;
fNorm = flow / (fs / 2);
[b,a] = butter(10, fNorm, 'low');
В [b, a] хранятся коэффициенты фильтра. Я хотел бы получить [b, a] как целые числа, чтобы я мог использовать онлайн-генератор кода HDL для генерации кода в Verilog.
Значения Matlab [b, a] кажутся слишком маленькими для использования с онлайн-генератором кода (серверный скрипт Perl отказывается генерировать код с коэффициентами), и мне интересно, возможно ли получить [b, а] в форме, которая может быть использована в качестве правильного ввода.
Коэффициенты, которые я получаю в Matlab:
1.0000
-9.1585
37.7780
-92.4225
148.5066
-163.7596
125.5009
-66.0030
22.7969
-4.6694
0.4307
Коэффициенты b, которые я получаю в Matlab:
1.0167e-012
1.0167e-011
4.5752e-011
1.2201e-010
2.1351e-010
2.5621e-010
2.1351e-010
1.2201e-010
4.5752e-011
1.0167e-011
1.0167e-012
Используя онлайн-генератор, я хотел бы разработать фильтр с 12-битной битовой шириной и формой фильтра I или II. Я не знаю, что подразумевается под "дробными битами" по ссылке выше.
Запустив генератор кода (http://www.spiral.net/hardware/filter.html) с коэффициентами [b, a], перечисленными выше, с дробными битами, установленными в 20, и битовой шириной в 12, я получаю следующую ошибку запуска :
Integer A constants: 1048576 -9603383 39613104 -96912015 155720456 -171714386 131597231 -69209161 23904282 -4896220 451621
Integer B constants: 0 0 0 0 0 0 0 0 0 0 0
Error: constants wider than 26 bits are not allowed, offending constant = -69209161, effective bitwidth = 7 mantissa + 20 fractional = 27 total.
An error has occurred - please revise the input parameters.
Как я могу изменить свой дизайн, чтобы эта ошибка не возникала?
ОБНОВЛЕНИЕ: Используя Matlab для генерации фильтра Баттерворта 6-го порядка, я получаю следующие коэффициенты:
Для:
1.0000
-5.4914
12.5848
-15.4051
10.6225
-3.9118
0.6010
для б:
0.0064e-005
0.0382e-005
0.0954e-005
0.1272e-005
0.0954e-005
0.0382e-005
0.0064e-005
Запустив онлайн-генератор кода (http://www.spiral.net/hardware/filter.html), я теперь получаю следующую ошибку (с дробными битами, равными 8, и битовой шириной, равной 20):
./iirGen.pl -A 256 '-1405' '3221' '-3943' '2719' '-1001' '153' -B '0' '0' '0' '0' '0' '0' '0' -moduleName acm_filter -fractionalBits 8 -bitWidth 20 -inData inData -inReg -outReg -outData outData -clk clk -reset reset -reset_edge negedge -filterForm 1 -debug -outFile ../outputs/filter_1330617505.v 2>&1
At least 1 non-zero-valued constant is required. Please check the inputs and try again.
Возможно, b-коэффициенты слишком малы или генератор кода (http://www.spiral.net/hardware/filter.html) хочет получить [b, a] в другом формате?
ОБНОВИТЬ:
Возможно, мне нужно масштабировать коэффициенты [b, a] по числу дробных битов, чтобы получить коэффициенты в виде целых чисел.
a .* 2^12
b .* 2^12
Тем не менее, я все еще думаю, что коэффициенты b чрезвычайно малы. Что я здесь не так делаю?
Возможно, другой тип фильтра (или метод дизайна фильтра) будет более подходящим? Может ли кто-нибудь сделать предложение?
ОБНОВЛЕНИЕ: Как предложено Джейсоном Р и Кристофером Фелтоном в комментариях ниже, фильтр SOS был бы более подходящим. Теперь я написал код Matlab для получения фильтра SOS.
fs = 2.1e6;
flow = 44 * 1000;
fNorm = flow / (fs / 2);
[A,B,C,D] = butter(10, fNorm, 'low');
[sos,g] = ss2sos(A,B,C,D);
Матрица SOS, которую я получаю:
1.0000 3.4724 3.1253 1.0000 -1.7551 0.7705
1.0000 2.5057 1.9919 1.0000 -1.7751 0.7906
1.0000 1.6873 1.0267 1.0000 -1.8143 0.8301
1.0000 1.2550 0.5137 1.0000 -1.8712 0.8875
1.0000 1.0795 0.3046 1.0000 -1.9428 0.9598
Можно ли по-прежнему использовать инструмент генерации кода Verilog (http://www.spiral.net/hardware/filter.html) для реализации этого фильтра SOS или мне просто нужно написать Verilog вручную? Хорошая ссылка доступна?
Я хотел бы знать, будет ли фильтр FIR лучше использовать в этой ситуации.
Еще: рекурсивные БИХ-фильтры могут быть реализованы с использованием целочисленной математики, выражая коэффициенты в виде дробей. (См. Превосходную книгу Смита по обработке сигналов DSP для получения дополнительной информации: http://www.dspguide.com/ch19/5.htm )
Следующая программа Matlab преобразует коэффициенты фильтра Баттерворта в дробные части, используя функцию Matlab rat (). Затем, как упоминалось в комментариях, разделы второго порядка можно использовать для численной реализации фильтра (http://en.wikipedia.org/wiki/Digital_biquad_filter).
% variables
% variables
fs = 2.1e6; % sampling frequency
flow = 44 * 1000; % lowpass filter
% pre-calculations
fNorm = flow / (fs / 2); % normalized freq for lowpass filter
% uncomment this to look at the coefficients in fvtool
% compute [b,a] coefficients
% [b,a] = butter(7, fNorm, 'low');
% fvtool(b,a)
% compute SOS coefficients (7th order filter)
[z,p,k] = butter(7, fNorm, 'low');
% NOTE that we might have to scale things to make sure
% that everything works out well (see zp2sos help for 'up' and 'inf' options)
sos = zp2sos(z,p,k, 'up', 'inf');
[n,d] = rat(sos);
sos_check = n ./ d; % this should be the same as SOS matrix
% by here, n is the numerator and d is the denominator coefficients
% as an example, write the the coefficients into a C code header file
% for prototyping the implementation
% write the numerator and denominator matices into a file
[rownum, colnum] = size(n); % d should be the same
sections = rownum; % the number of sections is the same as the number of rows
fid = fopen('IIR_coeff.h', 'w');
fprintf(fid, '#ifndef IIR_COEFF_H\n');
fprintf(fid, '#define IIR_COEFF_H\n\n\n');
for i = 1:rownum
for j = 1:colnum
if(j <= 3) % b coefficients
bn = ['b' num2str(j-1) num2str(i) 'n' ' = ' num2str(n(i,j))];
bd = ['b' num2str(j-1) num2str(i) 'd' ' = ' num2str(d(i,j))];
fprintf(fid, 'const int32_t %s;\n', bn);
fprintf(fid, 'const int32_t %s;\n', bd);
end
if(j >= 5) % a coefficients
if(j == 5)
colstr = '1';
end
if(j == 6)
colstr = '2';
end
an = ['a' colstr num2str(i) 'n' ' = ' num2str(n(i,j))];
ad = ['a' colstr num2str(i) 'd' ' = ' num2str(d(i,j))];
fprintf(fid, 'const int32_t %s;\n', an);
fprintf(fid, 'const int32_t %s;\n', ad);
end
end
end
% write the end of the file
fprintf(fid, '\n\n\n#endif');
fclose(fid);
Ответы:
Как уже говорилось, лучше всего использовать сумму сечений, то есть разбить фильтр высшего порядка на каскадные фильтры 2-го порядка. Обновленный вопрос имеет матрицу SOS. Используя этот код и пример здесь, объект Python может использоваться для генерации отдельных разделов.
В матлаб
В питоне
Дополнительную информацию о фиксированной точке можно найти здесь
источник
«Дробные биты» - это количество битов в шине, выделенных вами для представления дробной части числа (например, 0,75 в 3,75).
Скажем, у вас цифровая шина шириной 4 бита, какое число
1001
представляет? Это может означать «9», если вы рассматриваете его как положительное целое число (2 ^ 3 + 2 ^ 0 = 8 + 1 = 9). Или это может означать -7 в двоичной записи: (-2 ^ 3 + 2 ^ 0 = -8 + 1 = -7).Как насчет чисел с некоторыми дробями в них, то есть «реальных» чисел? Действительные числа могут быть представлены в аппаратных средствах как «с фиксированной запятой» или «с плавающей запятой». Похоже, что эти генераторы фильтров используют фиксированную точку.
Вернемся к нашему 4-битному автобусу (
1001
). Давайте введем двоичную точку, чтобы мы получили1.001
. Это означает, что теперь использовались биты на RHS точки для построения целых чисел и биты на LHS для построения дроби. Число, представленное цифровой шиной, установленной на1.001
1,125 (1
* 2 ^ 0 +0
* 2 ^ -1 +0
* 2 ^ -2 +1
* 2 ^ -3 = 1 + 0,125 = 1,125). В этом случае из 4 битов в шине мы используем 3 из них для представления дробной части числа. Или у нас есть 3 дробных бита.Итак, если у вас есть список действительных чисел, как у вас выше, теперь вы должны решить, сколько дробных битов вы хотите их представить. И здесь есть компромисс: чем больше дробных битов вы используете, тем ближе вы можете представить желаемое число, но тем больше должна быть ваша схема. Более того, чем меньше дробных битов вы используете, тем больше фактическая частотная характеристика фильтра будет отличаться от той, которую вы спроектировали в начале!
И что еще хуже, вы хотите создать фильтр бесконечного импульсного отклика (IIR). Они могут на самом деле работать нестабильно, если у вас недостаточно дробных и целочисленных битов!
источник
Так что Марти хорошо позаботился о битах. Что касается самого фильтра, я думаю, что вы, вероятно, получаете предупреждение или жалобу от Matlab по поводу плохо масштабированных коэффициентов? Когда я строю фильтр, от scipy не matlab, но он, вероятно, очень похож.
Что на 100 дБ ниже в полосе пропускания! Итак, вы можете убедиться, что вам нужен фильтр меньшего порядка, который в любом случае поможет вам в реализации. Когда я добираюсь до фильтра 6-го порядка, я прекращаю получать жалобы на плохие коэффициенты. Возможно, попробуйте уменьшить заказ и посмотреть, соответствует ли он вашим требованиям.
источник