Этот пример иллюстрирует, как сгенерировать HDL-код для lowpass конечной импульсной характеристики с архитектурой распределенной арифметики (DA).
Распределенная арифметика является популярной архитектурой для реализации конечных импульсных характеристик без использования множителей. DA реализует сумму расчетов продуктов, необходимых для конечная импульсная характеристика, эффективно используя LUT, переключатели и сумматоры. Поскольку эти операции эффективно отображаются на FPGA, DA является предпочтительной архитектурой на этих устройствах.
Используйте частоту дискретизации 48 кГц, частоту ребра полосы пропускания 9,6 кГц и частоту упора 12 кГц. Установите допустимый пик-к-пику неравномерности в полосе пропускания равным 1 дБ, а затуханием в полосе задерживания равным -90 дБ. Затем спроектируйте фильтр с помощью fdesign.lowpass и создайте Системный объект фильтр как прямую форму конечной импульсной характеристики фильтр.
Fs = 48e3; % Sampling Frequency in Hz Fpass = 9.6e3; % Passband Frequency in Hz Fstop = 12e3; % Stopband Frequency in Hz Apass = 1; % Passband Ripple in dB Astop = 90; % Stopband Attenuation in dB lpSpec = fdesign.lowpass( 'Fp,Fst,Ap,Ast',... Fpass, Fstop, Apass, Astop, Fs); lpFilter = design(lpSpec, 'equiripple', 'filterstructure', 'dffir',... 'SystemObject', true);
Поскольку DA реализует фильтр конечной импульсной характеристики путем сериализации бит входных данных, то это требует квантованного фильтра. Предположим, что требуются 12-разрядные входы и выходные размеры слова с 11 дробными битами (из-за требований к фиксированным путям данных или входных ширин ЦАП/вывода). Примените эти настройки фиксированной точки.
inputDataType = numerictype(1,12,11); outputDataType = inputDataType; coeffsDataType = numerictype(1,16,16); lpFilter.FullPrecisionOverride = false; lpFilter.CoefficientsDataType = 'Custom'; lpFilter.CustomCoefficientsDataType = coeffsDataType; lpFilter.OutputDataType = 'Custom'; lpFilter.CustomOutputDataType = outputDataType; % Now check the filter response with fvtool. fvtool(lpFilter,'Fs',Fs,'Arithmetic','fixed');
Чтобы сгенерировать HDL-код с архитектурой DA, активируйте команду generatehdl, передав допустимое значение свойству 'DALUTPartition'. Свойство 'DALUTPartition' предписывает генератору кода использовать архитектуру DA и делит LUT на заданное количество разделов. Свойство 'DALUTPartition' задает количество разделов LUT и количество отводов, сопоставленных с каждым разделом. Для фильтра с многими отводами лучше всего разделить отводы на несколько LUT, при этом каждый LUT хранит сумму коэффициентов только для связанных с ним отводов. Сумма выходов LUT вычисляется в древовидной структуре сумматоров.
Проверьте длину фильтра, получив количество коэффициентов.
FL = length(lpFilter.Numerator);
Предположим, что у вас есть 8 входных LUT; вычислите значение свойства DALUTPartition таким образом, чтобы вы использовали как можно больше из этих LUT на каждый раздел.
dalut = [ones(1, floor(FL/8))*8, mod(FL, 8)];
Создавайте HDL с архитектурой DA. По умолчанию генерируется код VHDL. Чтобы сгенерировать код Verilog, передайте в свойстве 'TargetLanguage' значение 'Verilog'.
workingdir = tempname; generatehdl(lpFilter, 'DALUTPartition', dalut, ... 'TargetDirectory', workingdir, ... 'InputDataType', inputDataType);
Warning: Structure fir has symmetric coefficients, consider converting to structure symmetricfir for reduced area.
Warning: Structure fir has symmetric coefficients, consider converting to structure symmetricfir for reduced area.
### Starting VHDL code generation process for filter: firfilt ### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook1/tp65546d1a_b9ca_474d_82e0_aeff8a74cd8d/firfilt.vhd ### Starting generation of firfilt VHDL entity ### Starting generation of firfilt VHDL architecture ### Clock rate is 12 times the input sample rate for this architecture. ### Successful completion of VHDL code generation process for filter: firfilt ### HDL latency is 3 samples
Симметричная структура фильтра предлагает преимущества в оборудовании, так как она вдвое меньше коэффициентов для работы. Это существенно снижает сложность оборудования. Создайте новую конечную импульсную характеристику фильтр Системного объекта 'lpSymFilter' со структурой 'Direct form symmetric' и теми же настройками фиксированной точки.
lpSymFilter = design(lpSpec, 'equiripple', 'filterstructure', 'dfsymfir',... 'SystemObject', true); lpSymFilter.FullPrecisionOverride = false; lpSymFilter.CoefficientsDataType = 'Custom'; lpSymFilter.CustomCoefficientsDataType = coeffsDataType; lpSymFilter.OutputDataType = 'Custom'; lpSymFilter.CustomOutputDataType = outputDataType; % Calculate filter length FL for lpSymFilter for the purpose of calculating 'DALUTPartition' FL = ceil(length(lpSymFilter.Numerator)/2); % Generate the value for 'DALUTPartition' as done previously for lpFilter. dalut_sym = [ones(1, floor(FL/8))*8, mod(FL, 8)]; % Generate HDL code for default radix of 2 generatehdl(lpSymFilter, 'DALUTPartition', dalut_sym, ... 'TargetDirectory', workingdir, ... 'InputDataType', inputDataType);
### Starting VHDL code generation process for filter: firfilt ### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook1/tp65546d1a_b9ca_474d_82e0_aeff8a74cd8d/firfilt.vhd ### Starting generation of firfilt VHDL entity ### Starting generation of firfilt VHDL architecture ### Clock rate is 13 times the input sample rate for this architecture. ### Successful completion of VHDL code generation process for filter: firfilt ### HDL latency is 3 samples
Заметьте, что симметричный фильтр принимает один дополнительный тактовый цикл перед получением выхода. Это происходит из-за бита переноса, который добавляется к входу размера слова когда входные данные от симметричных отводов суммируются вместе. Тактовая частота для 'lpSymFilter' в 13 раз превышает входную частоту выборки, тогда как для 'lpFilter' тактовая частота была в 12 раз выше входной частоты выборки.
Архитектурой по умолчанию является реализация Radix 2, которая работает с одним битом входных данных на каждом такте. Количество тактовых импульсов, прошедших до получения выхода, равно количеству бит во входных данных. Таким образом, DA может потенциально ограничить пропускную способность. Чтобы улучшить пропускную способность DA, можно сконфигурировать DA, чтобы обрабатывать несколько биты параллельно. Для этой цели предоставляется свойство 'DARadix'. Для примера можно задать 'DARadix' на 2 ^ 3, чтобы работать с 3 битами параллельно. Для 12-битной длины входного слова можно задать обработку 1, 2, 3, 4, 6 или 12 битов за раз, задав соответствующие значения 'DARadix' 2 ^ 1, 2 ^ 2, 2 ^ 3, 2 ^ 4, 2 ^ 6 или 2 ^ 12 соответственно.
При выборе различных значений 'DARadix' происходит компромисс скорости и площади в архитектуре DA. Количество бит, работающих параллельно, определяет коэффициент, на который необходимо увеличить тактовую частоту. Это известно как коэффициент складывания. Например, значение по умолчанию 'DARadix 2 ^ 1, подразумевающее 1 бит за раз, приводит к тактовой частоте, в 12 раз превышающей входную частоту дискретизации или коэффициент складывания 12. 'DARadix' из 2 ^ 3 результаты с тактовой частотой только в 4 раз больше, чем вход скорость выборки, но требует 3 одинаковых наборов LUT, по одному на каждый бит, обрабатываемый параллельно.
Как объяснялось в предыдущем разделе, архитектура DA представляет массу опций как с точки зрения размеров LUT, так и коэффициента складывания. Можно использовать функцию hdlfilterdainfo, чтобы получить информацию относительно различных длин фильтра на основе значения коэффициентов. Эта функция также отображает две другие таблицы, одна для всех возможных значений свойства DARadix с соответствующими факторами складывания. Во второй таблице отображаются детали наборов LUT с соответствующими значениями свойства DALUTPartition.
hdlfilterdainfo(lpFilter, 'InputDataType', inputDataType);
| Total Coefficients | Zeros | Effective | ------------------------------------------ | 58 | 0 | 58 | Effective filter length for SerialPartition value is 58. Table of 'DARadix' values with corresponding values of folding factor and multiple for LUT sets for the given filter. | Folding Factor | LUT-Sets Multiple | DARadix | ------------------------------------------------ | 1 | 12 | 2^12 | | 2 | 6 | 2^6 | | 3 | 4 | 2^4 | | 4 | 3 | 2^3 | | 6 | 2 | 2^2 | | 12 | 1 | 2^1 | Details of LUTs with corresponding 'DALUTPartition' values. | Max Address Width | Size(bits) | LUT Details | DALUTPartition | ----------------------------------------------------------------------------------------------------------------------- | 12 | 259072 |1x1024x13, 1x4096x13, 1x4096x14, 1x4096x15, 1x4096x18 |[12 12 12 12 10] | | 11 | 147544 |2x2048x13, 2x2048x14, 1x2048x18, 1x8x11 |[11 11 11 11 11 3] | | 10 | 78080 |3x1024x13, 1x1024x16, 1x1024x18, 1x256x13 |[10 10 10 10 10 8] | | 9 | 43712 |1x16x12, 1x512x12, 2x512x13, 1x512x14, 1x512x15, 1x512x18 |[9 9 9 9 9 9 4] | | 8 | 25384 |4x256x13, 1x256x14, 1x256x15, 1x256x18, 1x4x10 |[8 8 8 8 8 8 8 2] | | 7 | 14248 |2x128x12, 3x128x13, 1x128x14, 1x128x16, 1x128x18, 1x4x10 |[7 7 7 7 7 7 7 7 2] | | 6 | 8000 |1x16x12, 4x64x12, 1x64x13, 2x64x14, 1x64x16, 1x64x17 |[ones(1,9)*6, 4] | | 5 | 4696 |1x32x11, 4x32x12, 3x32x13, 1x32x14, 1x32x15, 1x32x17, 1x8x11 |[ones(1,11)*5, 3] | | 4 | 2904 |3x16x11, 5x16x12, 2x16x13, 2x16x14, 1x16x15, 1x16x17, 1x4x10 |[ones(1,14)*4, 2] | | 3 | 1926 |1x2x7, 5x8x11, 8x8x12, 1x8x13, 2x8x14, 2x8x15, 1x8x17 |[ones(1,19)*3, 1] | | 2 | 1412 |2x4x10, 12x4x11, 6x4x12, 2x4x13, 4x4x14, 2x4x15, 1x4x17 |ones(1,29)*2 | Notes: 1. LUT Details indicates number of LUTs with their sizes. e.g. 1x1024x18 implies 1 LUT of 1024 18-bit wide locations.
Вы можете использовать дополнительные свойства для LUT и коэффициентов складывания, чтобы отобразить конкретную информацию. Можно выбрать одно из двух свойств LUT, 'LUTInputs' или 'DALUTPartition', чтобы отобразить все опции коэффициента складывания, доступные для определенных входов LUT.
hdlfilterdainfo(lpFilter, 'InputDataType', inputDataType, ... 'LUTInputs', 4);
| Folding Factor | LUT Inputs | LUT Size | LUT Details | ---------------------------------------------------------------------------------------------------------------- | 1 | 4 | 34848 |12 x (3x16x11, 5x16x12, 2x16x13, 2x16x14, 1x16x15, 1x16x17, 1x4x10) | | 2 | 4 | 17424 |6 x (3x16x11, 5x16x12, 2x16x13, 2x16x14, 1x16x15, 1x16x17, 1x4x10) | | 3 | 4 | 11616 |4 x (3x16x11, 5x16x12, 2x16x13, 2x16x14, 1x16x15, 1x16x17, 1x4x10) | | 4 | 4 | 8712 |3 x (3x16x11, 5x16x12, 2x16x13, 2x16x14, 1x16x15, 1x16x17, 1x4x10) | | 6 | 4 | 5808 |2 x (3x16x11, 5x16x12, 2x16x13, 2x16x14, 1x16x15, 1x16x17, 1x4x10) | | 12 | 4 | 2904 |1 x (3x16x11, 5x16x12, 2x16x13, 2x16x14, 1x16x15, 1x16x17, 1x4x10) |
Можно также выбрать одно из двух свойств, связанных с коэффициентом складывания, 'FoldingFactor' или 'DARadix', чтобы отобразить все опции LUT для определенного фактора складывания.
hdlfilterdainfo(lpFilter, 'InputDataType', inputDataType, ... 'Foldingfactor', 6);
| Folding Factor | LUT Inputs | LUT Size | LUT Details | --------------------------------------------------------------------------------------------------------------- | 6 | 12 | 518144 |2 x (1x1024x13, 1x4096x13, 1x4096x14, 1x4096x15, 1x4096x18) | | 6 | 11 | 295088 |2 x (2x2048x13, 2x2048x14, 1x2048x18, 1x8x11) | | 6 | 10 | 156160 |2 x (3x1024x13, 1x1024x16, 1x1024x18, 1x256x13) | | 6 | 9 | 87424 |2 x (1x16x12, 1x512x12, 2x512x13, 1x512x14, 1x512x15, 1x512x18) | | 6 | 8 | 50768 |2 x (4x256x13, 1x256x14, 1x256x15, 1x256x18, 1x4x10) | | 6 | 7 | 28496 |2 x (2x128x12, 3x128x13, 1x128x14, 1x128x16, 1x128x18, 1x4x10) | | 6 | 6 | 16000 |2 x (1x16x12, 4x64x12, 1x64x13, 2x64x14, 1x64x16, 1x64x17) | | 6 | 5 | 9392 |2 x (1x32x11, 4x32x12, 3x32x13, 1x32x14, 1x32x15, 1x32x17, 1x8x11) | | 6 | 4 | 5808 |2 x (3x16x11, 5x16x12, 2x16x13, 2x16x14, 1x16x15, 1x16x17, 1x4x10) | | 6 | 3 | 3852 |2 x (1x2x7, 5x8x11, 8x8x12, 1x8x13, 2x8x14, 2x8x15, 1x8x17) | | 6 | 2 | 2824 |2 x (2x4x10, 12x4x11, 6x4x12, 2x4x13, 4x4x14, 2x4x15, 1x4x17) |
Заметьте, что детали LUT указывают коэффициент, с помощью которого наборы LUT должны быть реплицированы, чтобы достичь соответствующего коэффициента складывания. Кроме того, общий размер LUT вычисляется с указанным выше коэффициентом.
Можно использовать выходные аргументы, чтобы вернуть значения DALUTPartition и DARadix для определенного строения и использовать его с командой generatehdl. Предположим, что вы можете увеличить тактовую частоту в 4 раза больше частоты дискретизации и хотите использовать 6 входных LUT. Можно проверить, что данные LUT соответствуют требованиям области.
hdlfilterdainfo(lpFilter, 'InputDataType', inputDataType, ... 'FoldingFactor', 4, ... 'LUTInputs', 6);
| Folding Factor | LUT Size | LUT Details | DALUTPartition | DARAdix | ------------------------------------------------------------------------------------------------------------------------------- | 4 | 3 x 8000 = 24000 |3 x (1x16x12, 4x64x12, 1x64x13, 2x64x14, 1x64x16, 1x64x17) | [ones(1,9)*6, 4] | 2^3 |
Теперь сгенерируйте HDL с вышеуказанными ограничениями, сначала сохраняя необходимые значения DALUTPartition и DARadix в переменных с помощью выходных аргументов в функцию hdlfilterdainfo. Затем можно вызвать команду generatehdl, используя эти переменные.
[dalut, dr] = hdlfilterdainfo(lpFilter, 'InputDataType', inputDataType, ... 'FoldingFactor', 4, ... 'LUTInputs', 6); generatehdl(lpFilter, 'InputDataType', inputDataType, ... 'DALUTPartition', dalut, ... 'DAradix', dr, ... 'TargetDirectory', workingdir);
Warning: Structure fir has symmetric coefficients, consider converting to structure symmetricfir for reduced area.
Warning: Structure fir has symmetric coefficients, consider converting to structure symmetricfir for reduced area.
### Starting VHDL code generation process for filter: firfilt ### Generating: /tmp/BR2021ad_1655202_180016/mlx_to_docbook1/tp65546d1a_b9ca_474d_82e0_aeff8a74cd8d/firfilt.vhd ### Starting generation of firfilt VHDL entity ### Starting generation of firfilt VHDL architecture ### Clock rate is 4 times the input sample rate for this architecture. ### Successful completion of VHDL code generation process for filter: firfilt ### HDL latency is 3 samples
Вы разработали lowpass прямую форму конечной импульсной характеристики фильтра, чтобы соответствовать данным спецификациям. Затем вы квантовали и проверили свой проект. Вы сгенерировали код VHDL для DA с различными радиусами и исследовали компромиссы скорости и площади в DA путем репликации LUT и параллельной работы с несколькими битами.
Можно сгенерировать испытательный стенд с помощью стандартного стимула и/или собственного определенного стимула и использовать Симулятор HDL для проверки сгенерированного HDL-кода для архитектур DA. Можно использовать инструмент синтеза, чтобы сравнить площадь и скорость этих архитектур.