В этом примере показано, как сконструировать цифровой понижающий преобразователь (DDC) для приложений радиосвязи, таких как LTE, и генерировать код HDL с Coder™ HDL.
DDC широко используются в цифровых приемниках связи для преобразования радиочастотных (RF) или промежуточных частотных (IF) сигналов в основную полосу частот. Операция DDC сдвигает сигнал на более низкую частоту и уменьшает его частоту дискретизации, чтобы облегчить последующие этапы обработки. Представленный здесь DDC выполняет преобразование сложной частоты с последующим преобразованием частоты дискретизации с использованием 4-ступенчатой цепочки фильтров. Пример начинается с проектирования DDC с функциями DSP System Toolbox™ в плавающей точке. Затем каждая ступень преобразуется в фиксированную точку, а затем используется в модели Simulink ®, которая генерирует синтезируемый код HDL. Для демонстрации и проверки работы DDC используются два тестовых сигнала:
Синусоида модулирована на 32 МГц IF несущей.
Сигнал LTE нисходящей линии связи с полосой пропускания 1,4 МГц, модулированный на несущую 32 МГц IF.
Пример измеряет качество сигнала на выходе DDC с плавающей и фиксированной точками и сравнивает их. Наконец, представлены результаты внедрения FPGA.
Примечание.В этом примере используется DDCTestUtils, класс помощника, содержащий функции для генерирования стимула и анализа выхода DDC. См. раздел DDCTestUtils.m для получения дополнительной информации.
DDC состоит из осциллятора с числовым управлением (NCO), смесителя и прореживающей цепочки фильтров. Цепочка фильтров состоит из дециматора CIC, коррекции усиления CIC, дециматора компенсации CIC (FIR), полуполосного дециматора FIR и конечного дециматора FIR. Общий отклик цепочки фильтров эквивалентен отклику одиночного прореживающего фильтра с той же спецификацией, однако разделение фильтра на несколько ступеней прореживания приводит к более эффективной конструкции, которая использует меньшее количество аппаратных ресурсов. Прореживатель CIC обеспечивает большой начальный коэффициент прореживания, который позволяет последующим фильтрам работать с более низкими скоростями. Дециматор компенсации CIC улучшает спектральную характеристику путем компенсации спада CIC при децимации на два. Полуполоса является промежуточным прореживателем, в то время как конечный прореживатель реализует точное Fpass и Fstop характеристики DDC. Благодаря более низким скоростям дискретизации фильтры ближе к концу цепочки могут оптимизировать использование ресурсов путем совместного использования множителей. Ниже показана блок-схема DDC.

Входной сигнал DDC дискретизируется со скоростью 122,88 мс, в то время как выходная частота дискретизации составляет 1,92 мс. Поэтому общий коэффициент прореживания равен 64. 1,92 мсек - это типичная частота дискретизации, используемая приемниками LTE для выполнения поиска соты и восстановления MIB (главного информационного блока). Таким образом, фильтры DDC были разработаны в соответствии с этим приложением. DDC оптимизирован для работы с тактовой частотой 122,88 МГц.
В этом разделе описывается проектирование DDC с использованием операций с плавающей запятой и функций проектирования фильтров в MATLAB ®.
Параметры DDC
Требуемый отклик DDC определяется входной частотой дискретизации, несущей частотой и характеристиками фильтра. Изменение этого требуемого отклика фильтра может потребовать изменения свойств блока HDL блоков фильтра в модели Simulink. Свойства блока HDL рассматриваются далее в примере.
FsIn = 122.88e6; % Sampling rate at input to DDC Fc = 32e6; % Carrier frequency Fpass = 540e3; % Passband frequency, equivalent to 36x15kHz LTE subcarriers Fstop = 700e3; % Stopband frequency Ap = 0.1; % Passband ripple Ast = 60; % Stopband attenuation
В остальном разделе показано, как проектировать каждый фильтр по очереди.
Каскадный интегратор - дисковый прореживатель (CIC)
Первая ступень фильтра реализована как дециматор CIC благодаря своей способности эффективно реализовывать большой коэффициент децимации. Отклик фильтра CIC аналогичен каскаду фильтров скользящего среднего, однако умножения или деления не используются. В результате фильтр CIC имеет большой коэффициент усиления постоянного тока.
cicParams.DecimationFactor = 8; cicParams.DifferentialDelay = 1; cicParams.NumSections = 3; cicParams.FsOut = FsIn/cicParams.DecimationFactor; cicFilt = dsp.CICDecimator(cicParams.DecimationFactor,... cicParams.DifferentialDelay,cicParams.NumSections) %#ok<*NOPTS> cicGain = gain(cicFilt)
cicFilt =
dsp.CICDecimator with properties:
DecimationFactor: 8
DifferentialDelay: 1
NumSections: 3
FixedPointDataType: 'Full precision'
cicGain =
512
Коэффициент усиления CIC равен двум, поэтому его можно легко скорректировать аппаратными средствами с помощью операции сдвига. Для целей анализа коррекция усиления представлена в MATLAB одним отводом dsp.FIRFilter Системный объект.
cicGainCorr = dsp.FIRFilter('Numerator',1/cicGain)
cicGainCorr =
dsp.FIRFilter with properties:
Structure: 'Direct form'
NumeratorSource: 'Property'
Numerator: 0.0020
InitialConditions: 0
Use get to show all properties
Использовать fvtool отображение амплитудной характеристики фильтра CIC с коррекцией коэффициента усиления и без нее. Для анализа объедините фильтр CIC и фильтр коррекции усиления в dsp.FilterCascade Системный объект. Фильтры CIC всегда используют арифметику с фиксированной точкой внутри, поэтому fvtool строит график как квантованных, так и неквантованных откликов.
ddcPlots.cicDecim = fvtool(... cicFilt,... dsp.FilterCascade(cicFilt,cicGainCorr), ... 'Fs',[FsIn,FsIn]); DDCTestUtils.setPlotNameAndTitle('CIC Decimator'); legend(... 'CIC No Correction: Quantized', ... 'CIC No Correction: Reference', ... 'CIC With Gain Correction: Quantized', ... 'CIC With gain correction: Reference');

Фильтр компенсации падения CIC
Амплитудный отклик фильтра CIC имеет значительный провал в области полосы пропускания, поэтому фильтр компенсации провала на основе FIR используется для сглаживания отклика полосы пропускания. Компенсатор спада конфигурируется с теми же параметрами, что и прореживатель CIC. Этот фильтр также реализует прореживание в два раза, поэтому задаются его характеристики ограничения полосы пропускания. Укажите требования к фильтру, а затем используйте design функция для возврата объекта System фильтра с этими характеристиками.
compParams.R = 2; % CIC compensation decimation factor compParams.Fpass = Fstop; % CIC comp passband frequency compParams.FsOut = cicParams.FsOut/compParams.R; % New sampling rate compParams.Fstop = compParams.FsOut - Fstop; % CIC comp stopband frequency compParams.Ap = Ap; % Same Ap as overall filter compParams.Ast = Ast; % Same Ast as overall filter compSpec = fdesign.decimator(compParams.R,'ciccomp',... cicParams.DifferentialDelay,... cicParams.NumSections,... cicParams.DecimationFactor,... 'Fp,Fst,Ap,Ast',... compParams.Fpass,compParams.Fstop,compParams.Ap,compParams.Ast,... cicParams.FsOut); compFilt = design(compSpec,'SystemObject',true)
compFilt =
dsp.FIRDecimator with properties:
NumeratorSource: 'Property'
Numerator: [-0.0398 -0.0126 0.2901 0.5258 0.2901 -0.0126 -0.0398]
DecimationFactor: 2
Structure: 'Direct form'
Use get to show all properties
Постройте график комбинированного отклика фильтра CIC (с коррекцией усиления) и компенсации спада.
ddcPlots.cicComp = fvtool(... dsp.FilterCascade(cicFilt,cicGainCorr,compFilt), ... 'Fs',FsIn,'Legend','off'); DDCTestUtils.setPlotNameAndTitle('CIC Decim + Droop Comp');

Полуполосный прореживатель
Полуполосный фильтр обеспечивает эффективное прореживание на два. Полуполосные фильтры эффективны, поскольку приблизительно половина их коэффициентов равна нулю.
hbParams.FsOut = compParams.FsOut/2; hbParams.TransitionWidth = hbParams.FsOut - 2*Fstop; hbParams.StopbandAttenuation = Ast; hbSpec = fdesign.decimator(2,'halfband',... 'Tw,Ast',... hbParams.TransitionWidth, ... hbParams.StopbandAttenuation,... compParams.FsOut); hbFilt = design(hbSpec,'SystemObject',true)
hbFilt =
dsp.FIRDecimator with properties:
NumeratorSource: 'Property'
Numerator: [1x11 double]
DecimationFactor: 2
Structure: 'Direct form'
Use get to show all properties
Постройте график отклика DDC до выхода полупополосного фильтра.
ddcPlots.halfbandFIR = fvtool(... dsp.FilterCascade(cicFilt,cicGainCorr,compFilt,hbFilt), ... 'Fs',FsIn,'Legend','off'); DDCTestUtils.setPlotNameAndTitle('CIC Decim + Droop Comp + HB FIR');

Конечный дециматор FIR
Конечный FIR реализует подробные характеристики полосы пропускания и полосы останова DDC. Этот фильтр имеет больше коэффициентов, чем предшествующие фильтры FIR, однако он работает с более низкой частотой дискретизации, что обеспечивает большее совместное использование ресурсов аппаратными средствами.
% Add 3dB of headroom to the stopband attenuation so that the DDC still meets the % spec after fixed-point quantization. This value was determined by trial and error % with |fvtool|. finalSpec = fdesign.decimator(2,'lowpass',... 'Fp,Fst,Ap,Ast',Fpass,Fstop,Ap,Ast+3,hbParams.FsOut); finalFilt = design(finalSpec,'equiripple','SystemObject',true)
finalFilt =
dsp.FIRDecimator with properties:
NumeratorSource: 'Property'
Numerator: [1x70 double]
DecimationFactor: 2
Structure: 'Direct form'
Use get to show all properties
Визуализируйте общую амплитудную характеристику DDC.
ddcFilterChain = dsp.FilterCascade(cicFilt,cicGainCorr,compFilt,hbFilt,finalFilt); ddcPlots.overallResponse = fvtool(ddcFilterChain,'Fs',FsIn,'Legend','off'); DDCTestUtils.setPlotNameAndTitle('Overall DDC Filter Chain');

Частотная характеристика цепочки фильтров DDC с плавающей запятой теперь соответствует спецификации. Затем квантуйте каждый каскад фильтра для использования типов с фиксированной точкой и анализируйте их, чтобы подтвердить, что цепочка фильтров по-прежнему соответствует спецификации.
Квантование фильтра
В этом примере используются 16-битовые коэффициенты, что достаточно для соответствия спецификации. Использование менее 18 битов для коэффициентов минимизирует количество блоков DSP, необходимых для реализации FPGA. На вход цепочки фильтров DDC поступают 16-битовые данные с 15 дробными битами. Выходы фильтра являются 18-битными значениями, что обеспечивает дополнительный запас и точность в промежуточных сигналах.
Для прореживателя CIC выберите Minimum section word lengths параметр типа данных с фиксированной точкой автоматически оптимизирует внутренние значения длины слова на основе выходной длины слова и других параметров CIC.
cicFilt.FixedPointDataType = 'Minimum section word lengths';
cicFilt.OutputWordLength = 18;
Сконфигурируйте параметры с фиксированной точкой для системных объектов коррекции усиления и на основе FIR. Объект, не показанный явным образом, использует значение по умолчанию RoundingMethod и OverflowAction настройкиFloor и Wrap соответственно).
% CIC Gain Correction cicGainCorr.FullPrecisionOverride = false; cicGainCorr.CoefficientsDataType = 'Custom'; cicGainCorr.CustomCoefficientsDataType = numerictype(fi(cicGainCorr.Numerator,1,16)); cicGainCorr.OutputDataType = 'Custom'; cicGainCorr.CustomOutputDataType = numerictype(1,18,16); % CIC Droop Compensation compFilt.FullPrecisionOverride = false; compFilt.CoefficientsDataType = 'Custom'; compFilt.CustomCoefficientsDataType = numerictype([],16,15); compFilt.ProductDataType = 'Full precision'; compFilt.AccumulatorDataType = 'Full precision'; compFilt.OutputDataType = 'Custom'; compFilt.CustomOutputDataType = numerictype([],18,16); % Halfband hbFilt.FullPrecisionOverride = false; hbFilt.CoefficientsDataType = 'Custom'; hbFilt.CustomCoefficientsDataType = numerictype([],16,15); hbFilt.ProductDataType = 'Full precision'; hbFilt.AccumulatorDataType = 'Full precision'; hbFilt.OutputDataType = 'Custom'; hbFilt.CustomOutputDataType = numerictype([],18,16); % FIR finalFilt.FullPrecisionOverride = false; finalFilt.CoefficientsDataType = 'Custom'; finalFilt.CustomCoefficientsDataType = numerictype([],16,15); finalFilt.ProductDataType = 'Full precision'; finalFilt.AccumulatorDataType = 'Full precision'; finalFilt.OutputDataType = 'Custom'; finalFilt.CustomOutputDataType = numerictype([],18,16);
Анализ с фиксированной точкой
Проверка эффектов квантования с помощью fvtool. Фильтры могут анализироваться по отдельности или в каскаде. fvtool показывает квантованные и неквантованные (опорные) ответы, наложенные поверх. Например, показан эффект квантования последнего этапа КИХ-фильтра.
ddcPlots.quantizedFIR = fvtool(finalFilt,'Fs',hbParams.FsOut,'arithmetic','fixed'); DDCTestUtils.setPlotNameAndTitle('Quantized Final Filter');

Переопределить ddcFilterChain каскадный объект для включения свойств отдельных фильтров с фиксированной точкой. Затем использовать fvtool для анализа всей цепочки фильтров и подтверждения того, что квантованный DDC по-прежнему соответствует спецификации.
ddcFilterChain = dsp.FilterCascade(cicFilt,cicGainCorr,compFilt,hbFilt,finalFilt); ddcPlots.quantizedDDCResponse = fvtool(ddcFilterChain,'Fs',FsIn,'Arithmetic','fixed'); DDCTestUtils.setPlotNameAndTitle('Quantized DDC Filter Chain'); legend(... 'DDC filter chain: Quantized', ... 'DDC filter chain: Reference');

Следующим шагом в процессе проектирования является внедрение DDC в Simulink с использованием блоков, совместимых с HDL Coder.
Конфигурация модели
Для настройки блоков и параметров модель использует переменные в рабочем пространстве MATLAB. Он использует уже определенные переменные цепочки фильтров. Затем определите параметры осциллятора с числовым управлением (NCO) и входной сигнал. Эти параметры используются для конфигурирования блока NCO.
Укажите требуемое разрешение по частоте. Вычисляют количество битов-накопителей, необходимое для достижения требуемого разрешения, и определяют количество квантованных битов-накопителей. Квантованный выходной сигнал накопителя используется для обращения к таблице синусоидального поиска внутри NCO. Также вычислите приращение фазы, необходимое для генерации заданной несущей частоты. Фазовое сглаживание применяется к тем битам накопителя, которые удаляются во время квантования.
nco.Fd = 1; nco.AccWL = nextpow2(FsIn/nco.Fd) + 1; nco.QuantAccWL = 12; nco.PhaseInc = round((-Fc * 2^nco.AccWL)/FsIn); nco.NumDitherBits = nco.AccWL - nco.QuantAccWL;
Вход в DDC поступает от ddcIn. На данный момент присвойте фиктивное значение ddcIn чтобы модель могла вычислять свои типы данных. Во время испытаний, ddcIn обеспечивает входные данные для модели.
ddcIn = 0; %#ok<NASGU>
Показан верхний уровень модели DDC Simulink. Импорт модели ddcIn из рабочей области MATLAB с помощью блока «Сигнал из рабочей области» преобразует его в 16 бит и затем применяет к DDC. Код HDL может быть сгенерирован из подсистемы HDL_DDC.
modelName = 'DDCHDLImplementation'; open_system(modelName); set_param(modelName,'SimulationCommand','Update'); set_param(modelName, 'Open','on');

Реализация DDC осуществляется внутри подсистемы HDL_DDC. Блок NCO HDL Optimized генерирует сложный фазор на несущей частоте. Этот сигнал поступает в смеситель, который умножает его на входной сигнал. Затем выходной сигнал смесителя подается в цепочку фильтров, где он прореживается до 1,92 мс.
set_param([modelName '/HDL_DDC'],'Open','on');

Параметры блока NCO
Блок NCO конфигурируется с параметрами, определенными в nco структура. Отображаются обе вкладки диалогового окна параметров блока.

Прореживание CIC и коррекция усиления
Первая ступень фильтра представляет собой каскадный интегратор-дисковый прореживатель (CIC), реализованный с блоком оптимизации децимации HDL CIC. Параметры блока устанавливаются в значение cicParams значения структуры. Коррекция усиления осуществляется путем выбора параметра коррекции усиления.
Параметры блока фильтра
Фильтры настраиваются с помощью свойств соответствующих системных объектов. Фильтры CIC Compensation, Halfband Decimation и Final Decimation работают с эффективной частотой дискретизации, которая ниже тактовой частоты (Fclk) на 8, 16 и 32, соответственно. Эти частоты дискретизации реализуются с использованием действительного сигнала для указания того, какие выборки действительны на конкретной скорости. Сигналы в цепочке фильтров имеют одинаковое время выборки Simulink.
Каждый из фильтров CIC Compensation, Halfband Decimation и Final Decimation реализуется функциональным блоком MATLAB и двумя блоками HDL, оптимизированными для дискретного FIR-фильтра, в многофазном разложении. Многофазная декомпозиция реализует функцию преобразования,
где и
.
Многофазная декомпозиция является ресурсосберегающим способом реализации прореживающих фильтров. Функциональный блок MATLAB содержит две входные выборки каждые два цикла и передает их одновременно в параллельную пару блоков HDL-оптимизации дискретного КИХ-фильтра и.
Каждый из нижнего субфильтра и
верхнего субфильтра
содержит половину коэффициентов фильтра и обрабатывает половину входных данных.
Например, подсистема децимации компенсации CIC реализует 7-эффективный фильтр. Верхний субфильтр,,
имеет 4 коэффициенты и нижний субфильтр,,
имеет 3 коэффициенты. Каждый фильтр получает выборку и генерирует выходной сигнал каждый 16 циклов. Поскольку каждый фильтр обрабатывает одну выборку каждые 16 циклов, блоки субфильтра могут совместно использовать аппаратные ресурсы во времени. Чтобы оптимизировать аппаратные ресурсы таким образом, оба субфильтра имеют значение параметра Filter structure. Partly serial systolic.
На схеме показана подсистема децимации компенсации CIC. Подсистемы полуполосного прореживания и окончательного прореживания используют одну и ту же структуру.

Все блоки фильтров сконфигурированы с параметрами, определенными в соответствующих структурах. Например, на изображении показаны параметры блока для блока CIC Compensation Decimation. Параметр Number of cycles представляет собой минимальное количество циклов между входными выборками. Вход в блок децимации компенсации CIC дискретизируется в cicParams.DecimationFactor*compParams.R, что является 16 циклов для обоих субфильтров.

Реализация последовательного фильтра повторно использует множители во времени в течение указанного количества тактовых циклов. Без этой оптимизации фильтр CIC Compensation Decimation со сложными входными данными будет использовать 14 умножителей. После оптимизации каждый из
и
использует 2 множители для общего числа 4. Аналогично, используются подсистемы полуполосного прореживания и окончательного прореживания 4 множители каждый.
Для тестирования DDC модулируйте синусоиду 40kHz на несущей частоте и пропускайте ее через DDC. Затем измерьте паразитный свободный динамический диапазон (SFDR) результирующего тонального сигнала и SFDR выхода NCO.
% Initialize random seed before executing any simulations. rng(0); % Generate a 40kHz test tone, modulated onto the carrier. ddcIn = DDCTestUtils.GenerateTestTone(40e3,Fc); % Demodulate the test signal with the floating point DDC. ddcOut = DDCTestUtils.DownConvert(ddcIn,FsIn,Fc,ddcFilterChain); release(ddcFilterChain); % Demodulate the test signal by executing the modified Simulink model with the sim function. out = sim(modelName); % Measure the SFDR of the NCO, floating point DDC and the fixed-point DDC outputs. results.sfdrNCO = sfdr(real(out.ncoOut),FsIn/64); results.sfdrFloatDDC = sfdr(real(ddcOut),FsIn/64); results.sfdrFixedDDC = sfdr(real(out.ddcOut),FsIn/64); disp('Spurious Free Dynamic Range (SFDR) Measurements'); disp([' Floating point DDC SFDR: ',num2str(results.sfdrFloatDDC) ' dB']); disp([' Fixed-point NCO SFDR: ',num2str(results.sfdrNCO) ' dB']); disp([' Optimized Fixed-point DDC SFDR: ',num2str(results.sfdrFixedDDC) ' dB']); fprintf(newline); % Plot the SFDR of the NCO and fixed-point DDC outputs. ddcPlots.ncoOutSDFR = figure; sfdr(real(out.ncoOut),FsIn/64); DDCTestUtils.setPlotNameAndTitle(['NCO Out ' get(gca,'Title').String]); ddcPlots.OptddcOutSFDR = figure; sfdr(real(out.ddcOut),FsIn/64); DDCTestUtils.setPlotNameAndTitle(['Optimized Fixed-Point DDC Out ' get(gca,'Title').String]);
Spurious Free Dynamic Range (SFDR) Measurements Floating point DDC SFDR: 291.3483 dB Fixed-point NCO SFDR: 83.0249 dB Optimized Fixed-point DDC SFDR: 108.8419 dB


rng(0); if license('test','LTE_Toolbox') % Generate a modulated LTE test signal with LTE Toolbox [ddcIn, sigInfo] = DDCTestUtils.GenerateLTETestSignal(Fc); % Downconvert with a MATLAB Floating Point Model ddcOut = DDCTestUtils.DownConvert(ddcIn,FsIn,Fc,ddcFilterChain); release(ddcFilterChain); % Downconvert using Simulink model ddcIn=[ddcIn;zeros(320,1)]; % Adding zeros to make up propagation latency to output complete result out = sim(modelName); results.evmFloat = DDCTestUtils.MeasureEVM(sigInfo,ddcOut); results.evmFixed = DDCTestUtils.MeasureEVM(sigInfo,out.ddcOut); disp('LTE Error Vector Magnitude (EVM) Measurements'); disp([' Floating point DDC RMS EVM: ' num2str(results.evmFloat.RMS*100,3) '%']); disp([' Floating point DDC Peak EVM: ' num2str(results.evmFloat.Peak*100,3) '%']); disp([' Fixed-point HDL Optimized DDC RMS EVM: ' num2str(results.evmFixed.RMS*100,3) '%']); disp([' Fixed-point HDL Optimized DDC Peak EVM: ' num2str(results.evmFixed.Peak*100,3) '%']); fprintf(newline); end
LTE Error Vector Magnitude (EVM) Measurements Floating point DDC RMS EVM: 0.633% Floating point DDC Peak EVM: 2.44% Fixed-point HDL Optimized DDC RMS EVM: 0.731% Fixed-point HDL Optimized DDC Peak EVM: 2.69%
Для создания кода HDL в этом примере необходимо иметь продукт HDL Coder™. Используйте makehdl и makehdltb команды для генерации кода HDL и средства тестирования HDL для подсистемы HDL_DDC. DDC синтезировали на оценочной плате Xilinx ® Zynq ® -7000 ZC706. Результаты использования ресурсов после размещения и маршрутизации показаны в таблице. Конструкция отвечала таймингу с тактовой частотой 313 МГц.
T = table(... categorical({'LUT'; 'LUTRAM'; 'FF'; 'BRAM'; 'DSP'}),... categorical({'2660'; '318'; '5951'; '1.0'; '18'}),... 'VariableNames',{'Resource','Usage'})
T =
5x2 table
Resource Usage
________ _____
LUT 2660
LUTRAM 318
FF 5951
BRAM 1.0
DSP 18