exponenta event banner

Последовательные архитектуры HDL для фильтров FIR

Этот пример иллюстрирует, как генерировать HDL-код для симметричного FIR-фильтра с полностью параллельными, полностью последовательными, частично последовательными и каскадно-последовательными архитектурами для фильтра нижних частот для приложения фильтрации звука.

Проектирование фильтра

Используйте частоту дискретизации звука 44,1 кГц и граничную частоту полосы пропускания 8,0 кГц. Установите допустимую пульсацию полосы пропускания от пика к пику в 1 дБ, а затухание полосы останова в -90 дБ. Затем создайте фильтр с помощью fdesign.lowpass и создайте объект FIR filter System с помощью метода equiripple со структурой Direct form symmetric.

Fs           = 44.1e3;         % Sampling Frequency in Hz
Fpass        = 8e3;            % Passband Frequency in Hz
Fstop        = 8.8e3;          % Stopband Frequency in Hz
Apass        = 1;              % Passband Ripple in dB
Astop        = 90;             % Stopband Attenuation in dB

fdes = fdesign.lowpass('Fp,Fst,Ap,Ast',...
    Fpass, Fstop, Apass, Astop, Fs);
lpFilter = design(fdes,'equiripple', 'FilterStructure', 'dfsymfir', ...
    'SystemObject', true);

Квантование фильтра

Предположим, что вход для аудиофильтра поступает от 12-битового АЦП, а выход является 12-битным АЦП.

nt_in = numerictype(1,12,11);
nt_out = nt_in;
lpFilter.FullPrecisionOverride = false;
lpFilter.CoefficientsDataType = 'Custom';
lpFilter.CustomCoefficientsDataType = numerictype(1,16,16);
lpFilter.OutputDataType = 'Custom';
lpFilter.CustomOutputDataType = nt_out;

% Check the response with fvtool.
fvtool(lpFilter,'Fs',Fs, 'Arithmetic', 'fixed');

Figure Filter Visualization Tool - Magnitude Response (dB) contains an axes and other objects of type uitoolbar, uimenu. The axes with title Magnitude Response (dB) contains 3 objects of type line. These objects represent Filter #1: Quantized, Filter #1: Reference.

Создание полностью параллельного кода HDL из квантованного фильтра

Начиная с правильно квантованного фильтра, генерируйте код VHDL или Verilog. Создайте временную рабочую папку. После создания кода HDL (в этом случае выберите VHDL) откройте созданный файл VHDL в редакторе, щелкнув гиперссылку, отображаемую в сообщениях командной строки.

Это вариант по умолчанию и создает полностью параллельную архитектуру. Имеется выделенный множитель для каждого отвода фильтра в виде структуры фильтра с прямой КИХ и один для каждых двух симметричных отводов в симметричной структуре КИХ. Это приводит к большой площади элементарных посылок (в данном примере 78 умножителей). Фильтр может быть реализован в различных последовательных архитектурах для достижения желаемого компромисса между скоростью и площадью. Они проиллюстрированы в других разделах этого примера.

workingdir = tempname;
% fully parallel (default)
generatehdl(lpFilter, 'Name', 'fullyparallel', ...
            'TargetLanguage', 'VHDL', ...
            'TargetDirectory', workingdir, ...
            'InputDataType', nt_in);
### Starting VHDL code generation process for filter: fullyparallel
### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook2/tp82318ff2_aa22_4795_8726_127d9a22996f/fullyparallel.vhd
### Starting generation of fullyparallel VHDL entity
### Starting generation of fullyparallel VHDL architecture
### Successful completion of VHDL code generation process for filter: fullyparallel
### HDL latency is 2 samples

Создание тестового стенда из квантованного фильтра

Создайте стенд тестирования VHDL, чтобы убедиться, что результат точно соответствует ответу, который вы видите в MATLAB ®. Сгенерированный код VHDL и средства тестирования VHDL можно скомпилировать и смоделировать с помощью симулятора .

Создайте тональные сигналы DTMF, которые будут использоваться в качестве тестового стимула для фильтра. Сигнал DTMF состоит из суммы двух синусоид - или тонов - с частотами, взятыми из двух взаимоисключающих групп. Каждая пара тонов содержит одну частоту низкой группы (697 Гц, 770 Гц, 852 Гц, 941 Гц) и одну частоту высокой группы (1209 Гц, 1336 Гц, 1477Hz) и представляет собой уникальный символ. Вы создадите все сигналы DTMF, но используйте один из них (цифра 1 здесь) для тестового стимула. Это позволит сохранить продолжительность тестового стимула до разумного предела.

symbol = {'1','2','3','4','5','6','7','8','9','*','0','#'};

lfg = [697 770 852 941]; % Low frequency group
hfg = [1209 1336 1477];  % High frequency group

% Generate a matrix containing all possible combinations of high and low 
% frequencies, where each column represents one combination.
f  = zeros(2,12);
for c=1:4
    for r=1:3
        f(:,3*(c-1)+r) = [lfg(c); hfg(r)];
    end
end

Далее, давайте создадим тональные сигналы DTMF

Fs  = 8000;       % Sampling frequency 8 kHz
N = 800;          % Tones of 100 ms
t   = (0:N-1)/Fs; % 800 samples at Fs
pit = 2*pi*t;

tones = zeros(N,size(f,2));
for toneChoice=1:12
    % Generate tone
    tones(:,toneChoice) = sum(sin(f(:,toneChoice)*pit))';
end

% Taking the tone for digit '1' for test stimulus.
userstim = tones(:,1);

generatehdl(lpFilter, 'Name', 'fullyparallel',...
            'GenerateHDLTestbench','on', ...
            'TestBenchUserStimulus', userstim,...
            'TargetLanguage', 'VHDL',...
            'TargetDirectory', workingdir, ...
            'InputDataType', nt_in);
### Starting VHDL code generation process for filter: fullyparallel
### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook2/tp82318ff2_aa22_4795_8726_127d9a22996f/fullyparallel.vhd
### Starting generation of fullyparallel VHDL entity
### Starting generation of fullyparallel VHDL architecture
### Successful completion of VHDL code generation process for filter: fullyparallel
### HDL latency is 2 samples
### Starting generation of VHDL Test Bench.
### Generating input stimulus
### Done generating input stimulus; length 800 samples.
Warning: Wrap on overflow detected. This originated from 'DiscreteFir'
Suggested Actions:
    • Suppress future instances of this diagnostic from this source. - Suppress

### Generating Test bench: /tmp/BR2021ad_1655202_180016/mlx_to_docbook2/tp82318ff2_aa22_4795_8726_127d9a22996f/fullyparallel_tb.vhd
### Creating stimulus vectors ...
### Done generating VHDL Test Bench.

Информация по последовательным архитектурам

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

Функцию hdlfilterserialinfo можно использовать для получения информации о различных длинах фильтров на основе значения коэффициентов. Эта функция также отображает исчерпывающую таблицу возможных опций для указания свойства SerurePartition с соответствующими значениями коэффициента сворачивания и количеством множителей.

hdlfilterserialinfo(lpFilter, 'InputDataType', nt_in);
   | Total Coefficients | Zeros | A/Symm | Effective |
   ---------------------------------------------------
   |         156        |   0   |   78   |     78    |

Effective filter length for SerialPartition value is 78.

  Table of 'SerialPartition' values with corresponding values of 
  folding factor and number of multipliers for the given filter.

   | Folding Factor | Multipliers |   SerialPartition   |
   ------------------------------------------------------
   |        1       |      78     |ones(1,78)           |
   |        2       |      39     |ones(1,39)*2         |
   |        3       |      26     |ones(1,26)*3         |
   |        4       |      20     |[ones(1,19)*4, 2]    |
   |        5       |      16     |[ones(1,15)*5, 3]    |
   |        6       |      13     |ones(1,13)*6         |
   |        7       |      12     |[ones(1,11)*7, 1]    |
   |        8       |      10     |[ones(1,9)*8, 6]     |
   |        9       |      9      |[9 9 9 9 9 9 9 9 6]  |
   |       10       |      8      |[ones(1,7)*10, 8]    |
   |       11       |      8      |[ones(1,7)*11, 1]    |
   |       12       |      7      |[ones(1,6)*12, 6]    |
   |       13       |      6      |[13 13 13 13 13 13]  |
   |       14       |      6      |[14 14 14 14 14 8]   |
   |       15       |      6      |[15 15 15 15 15 3]   |
   |       16       |      5      |[16 16 16 16 14]     |
   |       17       |      5      |[17 17 17 17 10]     |
   |       18       |      5      |[18 18 18 18 6]      |
   |       19       |      5      |[19 19 19 19 2]      |
   |       20       |      4      |[20 20 20 18]        |
   |       21       |      4      |[21 21 21 15]        |
   |       22       |      4      |[22 22 22 12]        |
   |       23       |      4      |[23 23 23 9]         |
   |       24       |      4      |[24 24 24 6]         |
   |       25       |      4      |[25 25 25 3]         |
   |       26       |      3      |[26 26 26]           |
   |       27       |      3      |[27 27 24]           |
   |       28       |      3      |[28 28 22]           |
   |       29       |      3      |[29 29 20]           |
   |       30       |      3      |[30 30 18]           |
   |       31       |      3      |[31 31 16]           |
   |       32       |      3      |[32 32 14]           |
   |       33       |      3      |[33 33 12]           |
   |       34       |      3      |[34 34 10]           |
   |       35       |      3      |[35 35 8]            |
   |       36       |      3      |[36 36 6]            |
   |       37       |      3      |[37 37 4]            |
   |       38       |      3      |[38 38 2]            |
   |       39       |      2      |[39 39]              |
   |       40       |      2      |[40 38]              |
   |       41       |      2      |[41 37]              |
   |       42       |      2      |[42 36]              |
   |       43       |      2      |[43 35]              |
   |       44       |      2      |[44 34]              |
   |       45       |      2      |[45 33]              |
   |       46       |      2      |[46 32]              |
   |       47       |      2      |[47 31]              |
   |       48       |      2      |[48 30]              |
   |       49       |      2      |[49 29]              |
   |       50       |      2      |[50 28]              |
   |       51       |      2      |[51 27]              |
   |       52       |      2      |[52 26]              |
   |       53       |      2      |[53 25]              |
   |       54       |      2      |[54 24]              |
   |       55       |      2      |[55 23]              |
   |       56       |      2      |[56 22]              |
   |       57       |      2      |[57 21]              |
   |       58       |      2      |[58 20]              |
   |       59       |      2      |[59 19]              |
   |       60       |      2      |[60 18]              |
   |       61       |      2      |[61 17]              |
   |       62       |      2      |[62 16]              |
   |       63       |      2      |[63 15]              |
   |       64       |      2      |[64 14]              |
   |       65       |      2      |[65 13]              |
   |       66       |      2      |[66 12]              |
   |       67       |      2      |[67 11]              |
   |       68       |      2      |[68 10]              |
   |       69       |      2      |[69 9]               |
   |       70       |      2      |[70 8]               |
   |       71       |      2      |[71 7]               |
   |       72       |      2      |[72 6]               |
   |       73       |      2      |[73 5]               |
   |       74       |      2      |[74 4]               |
   |       75       |      2      |[75 3]               |
   |       76       |      2      |[76 2]               |
   |       77       |      2      |[77 1]               |
   |       78       |      1      |[78]                 |

Для отображения определенной информации можно использовать дополнительные свойства «Множители» и «Множитель».

hdlfilterserialinfo(lpFilter, 'Multipliers', 4, ...
                    'InputDataType', nt_in);
Serial Partition: [20 20 20 18], Folding Factor:   20, Multipliers:    4
hdlfilterserialinfo(lpFilter, 'Foldingfactor', 6, ...
                    'InputDataType', nt_in);
Serial Partition: ones(1,13)*6, Folding Factor:    6, Multipliers:   13

Полностью последовательная архитектура

В полностью последовательной архитектуре вместо специального множителя для каждого отвода входная выборка для каждого отвода выбирается последовательно и умножается на соответствующий коэффициент. Для симметричных (и антисимметричных) структур входные выборки, соответствующие каждому набору симметричных отводов, предварительно суммируются (для симметричных) или предварительно вычитаются (для антисимметричных) перед умножением на соответствующие коэффициенты. Продукт накапливается последовательно с использованием регистра, и конечный результат сохраняется в регистре до поступления следующего набора входных выборок. Эта реализация требует тактовой частоты, которая во много раз быстрее входной частоты выборки, чем количество вычисляемых продуктов. Это приводит к уменьшению требуемой площади элементарных посылок, поскольку реализация включает только один умножитель с несколькими дополнительными логическими элементами, такими как мультиплексоры и регистры. Тактовая частота в этом примере будет в 78 раз превышать входную частоту выборки (коэффициент сворачивания 78), равную 3,4398 МГц.

Для реализации полностью последовательной архитектуры используйте функцию hdlfilterserialinfo и установите для ее свойства «Множители» значение 1. Также можно задать свойство «SerurePartition» со значением, равным эффективной длине фильтра, которое в данном случае равно 78. Функция также возвращает коэффициент сворачивания и количество множителей, используемых для этой настройки последовательного разбиения.

[spart, foldingfact, nMults] = hdlfilterserialinfo(lpFilter, 'Multipliers', 1, ...
                                    'InputDataType', nt_in); %#ok<ASGLU>
                      
generatehdl(lpFilter,'Name', 'fullyserial', ...
           'SerialPartition', spart, ...
           'TargetLanguage', 'VHDL', ...
           'TargetDirectory', workingdir, ...
           'InputDataType', nt_in);
### Starting VHDL code generation process for filter: fullyserial
### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook2/tp82318ff2_aa22_4795_8726_127d9a22996f/fullyserial.vhd
### Starting generation of fullyserial VHDL entity
### Starting generation of fullyserial VHDL architecture
### Clock rate is 78 times the input sample rate for this architecture.
### Successful completion of VHDL code generation process for filter: fullyserial
### HDL latency is 3 samples

Создайте тестовые инструментальные средства таким же образом, как и в полностью параллельном случае. Для каждой реализации архитектуры важно снова создать тестовую среду.

Частично последовательная архитектура

Полностью параллельные и полностью последовательные представляют две крайности реализаций. Несмотря на то, что Fully serial имеет очень низкую площадь, для его работы необходима более высокая тактовая частота. Полная параллель занимает много площади чипа, но имеет очень хорошую производительность. Частично последовательная архитектура охватывает все случаи, лежащие между этими двумя крайностями.

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

Частично последовательная архитектура для ограничения ресурсов

Предположим, что вы хотите реализовать этот фильтр на FPGA, который имеет только 4 умножителя, доступных для фильтра. Фильтр можно реализовать с помощью 4 последовательных разделов, каждый из которых использует одну схему умножения и накопления.

hdlfilterserialinfo(lpFilter, 'Multipliers', 4, ...
                    'InputDataType', nt_in);
Serial Partition: [20 20 20 18], Folding Factor:   20, Multipliers:    4

Входные отводы, обрабатываемые этими последовательными разделами, будут [20 20 20 18]. Вы указываете SerurePartition с этим вектором, указывающим разложение отводов для последовательных разделов. Тактовая частота определяется наибольшим элементом этого вектора. В этом случае тактовая частота будет в 20 раз превышать входную частоту дискретизации 0,882 МГц.

[spart, foldingfact, nMults] = hdlfilterserialinfo(lpFilter, 'Multipliers', 4, ...
                                    'InputDataType', nt_in);

generatehdl(lpFilter,'Name', 'partlyserial1',...
            'SerialPartition', spart,...
            'TargetLanguage', 'VHDL', ...
            'TargetDirectory', workingdir, ...
            'InputDataType', nt_in);
### Starting VHDL code generation process for filter: partlyserial1
### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook2/tp82318ff2_aa22_4795_8726_127d9a22996f/partlyserial1.vhd
### Starting generation of partlyserial1 VHDL entity
### Starting generation of partlyserial1 VHDL architecture
### Clock rate is 20 times the input sample rate for this architecture.
### Successful completion of VHDL code generation process for filter: partlyserial1
### HDL latency is 3 samples

Частично последовательная архитектура для ограничения скорости

Предположим, что имеется ограничение на тактовую частоту для реализации фильтра и максимальная тактовая частота равна 2 МГц. Это означает, что тактовая частота не может превышать 45-кратную входную частоту дискретизации. Для такого ограничения конструкции «SerurePartition» должен быть указан в [45 33]. Заметим, что это приводит к дополнительным аппаратным средствам последовательного разбиения, подразумевающим дополнительные схемы для умножения-накопления 33 отводов. Можно указать SerurePartition с помощью hdlfilterserialinfo и его свойства Foldingfactor следующим образом.

spart = hdlfilterserialinfo(lpFilter, 'Foldingfactor', 45, ...
                            'InputDataType', nt_in);

generatehdl(lpFilter,'Name', 'partlyserial2', ...
            'SerialPartition', spart,...
            'TargetLanguage', 'VHDL',...
            'TargetDirectory', workingdir, ...
            'InputDataType', nt_in);
### Starting VHDL code generation process for filter: partlyserial2
### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook2/tp82318ff2_aa22_4795_8726_127d9a22996f/partlyserial2.vhd
### Starting generation of partlyserial2 VHDL entity
### Starting generation of partlyserial2 VHDL architecture
### Clock rate is 45 times the input sample rate for this architecture.
### Successful completion of VHDL code generation process for filter: partlyserial2
### HDL latency is 3 samples

Как правило, можно задать любое произвольное разложение отводов для последовательных разделов в зависимости от других ограничений. Единственное требование состоит в том, чтобы сумма элементов вектора была равна эффективной длине фильтра.

Каскадно-последовательная архитектура

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

Архитектура Cascade-Serial может быть задана с помощью свойства ReuseAccum. Это можно сделать двумя способами.

Добавьте ReuseAccum к методу generatehdl и укажите его как on. Обратите внимание, что значение, указанное для свойства «SerurePartition», должно быть таким, чтобы повторное использование накопителя было возможным. Элементы вектора должны быть в порядке убывания, за исключением двух последних элементов, которые могут быть одинаковыми.

Если свойство «» SerurePartition «» не указано, а «» ReuseAccum «» указан как «» on «», разложение отводов для последовательных разделов определяется внутренне. Это делается для минимизации тактовой частоты и повторного использования накопителя. Для этого аудиофильтра используется [12 11 10 9 8 7 6 5 4 3 3]. Следует отметить, что он использует 11 последовательных разделов, подразумевая 11 схем умножения и накопления. Тактовая частота будет в 13 раз превышать входную частоту дискретизации, 573,3 кГц .

generatehdl(lpFilter,'Name', 'cascadeserial1',...
            'SerialPartition', [45 33],...
            'ReuseAccum', 'on', ...
            'TargetLanguage', 'VHDL', ...
            'TargetDirectory', workingdir, ...
            'InputDataType', nt_in);
### Starting VHDL code generation process for filter: cascadeserial1
### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook2/tp82318ff2_aa22_4795_8726_127d9a22996f/cascadeserial1.vhd
### Starting generation of cascadeserial1 VHDL entity
### Starting generation of cascadeserial1 VHDL architecture
### Clock rate is 46 times the input sample rate for this architecture.
### Successful completion of VHDL code generation process for filter: cascadeserial1
### HDL latency is 3 samples

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

generatehdl(lpFilter,'Name', 'cascadeserial2', ...
            'ReuseAccum', 'on',...
            'TargetLanguage', 'VHDL',...
            'TargetDirectory', workingdir, ...
            'InputDataType', nt_in);
### Starting VHDL code generation process for filter: cascadeserial2
### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook2/tp82318ff2_aa22_4795_8726_127d9a22996f/cascadeserial2.vhd
### Starting generation of cascadeserial2 VHDL entity
### Starting generation of cascadeserial2 VHDL architecture
### Clock rate is 13 times the input sample rate for this architecture.
### Serial partition # 1 has 12 inputs.
### Serial partition # 2 has 11 inputs.
### Serial partition # 3 has 10 inputs.
### Serial partition # 4 has 9 inputs.
### Serial partition # 5 has 8 inputs.
### Serial partition # 6 has 7 inputs.
### Serial partition # 7 has 6 inputs.
### Serial partition # 8 has 5 inputs.
### Serial partition # 9 has 4 inputs.
### Serial partition # 10 has 3 inputs.
### Serial partition # 11 has 3 inputs.
### Successful completion of VHDL code generation process for filter: cascadeserial2
### HDL latency is 3 samples

Заключение

Вы разработали низкочастотный фильтр прямой формы, симметричный FIR, соответствующий данной спецификации. Затем вы квантовали и проверяли свой дизайн. Вы создали код VHDL для полностью параллельных, полностью последовательных, частично последовательных и каскадно-последовательных архитектур. Вы создали стенд тестирования VHDL, используя тональный сигнал DTMF для одной из архитектур.

Можно использовать имитатор HDL для проверки созданного кода HDL для различных последовательных архитектур. Для сравнения площади и скорости этих архитектур можно использовать инструмент синтеза. Можно также экспериментировать и генерировать код Verilog и тестовые стенды.