Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Реализация AGC на FPGA
Форум разработчиков электроники ELECTRONIX.ru > Цифровая обработка сигналов - ЦОС (DSP) > Алгоритмы ЦОС (DSP)
vea
Здравствуйте!
Попробовал смоделировать схему (с целью дальнейшей реализации в FPGA), предложенную в статье Carrier Recovery and Automatic Gain Control on
FPGA’s based platform
, рис. 8.
Результат неадекватный (начиная с некоторого момента алгоритм расходится). Менял параметры (наугад, поскольку никакой понятной теории не нашел), результата нет.
Может быть, кто-то сталкивался с этим?
Для сравнения - код по Незами (рис. 4-27). Тут все нормально, но это для double точности.
Или посоветуйте другие варианты - поиск пока лучших результатов не дал.
Спасибо!
Код
% input signal gereration start
N=5*1000; % length of input signal
ft=N/5;
fs=(1-1/5)*N;
A(1:N/5)= 2^5; % max values
A(N/5+1:2*N/5)  = 2^5;
A(2*N/5+1:3*N/5)= 2^8;
A(3*N/5+1:4*N/5)= 2^11;
A(4*N/5+1:5*N/5)= 2^7;
x= A.*exp(2*pi*j*ft*[1:N]/fs);
x=x.';
% input signal end
% initialization start
y1   = zeros(1,length(x));
y2   = zeros(1,length(x));
norm = zeros(1,length(x));
A1(1)= 0;  % Gain for exp
A2(1)= 1;  % Gain for linear
avg  = 0;
acc  = 0;
% initialization end

% PARAMETERS of AGC
R  = 10;     % reference
a1 = 0.0001; % for exp
K  = 9;
B  = 2^3; % length of buffer
% ---------

% main
for k=1:length(x)-1
% exp AGC (Nezami)
    y1(k) = 2^[A1(k)] * x(k);
    A1(k+1) = A1(k) + a1*(2^R - [abs(real(y1(k))) + abs(imag(y1(k)))]);
% linear AGC
    y2(k) = A2(k) * x(k);
    norm(k) = abs(real(y2(k))) + abs(imag(y2(k)));
    if (k<=B) % AVG in buffer
        avg = avg + norm(k);
    else
        avg = avg + norm(k)-norm(k-B);
    end
    diff    = 2^R - floor(avg/B);   % 2^R is reference level
    acc     = acc + diff;           % accumulator
    result  = floor(acc/2^K);      
    A2(k+1) = result;  
end
figure
subplot(311); plot([ real(x).' ]); grid;shg
subplot(312); plot([ real(y1).']); grid;shg
subplot(313); plot([ real(y2).']); grid;shg
andyp
У Вас две стандартные ошибки (по степени важности)-
1. Не ослеживаете макс и мин значение усиления (у Вас оно даже отрицательным может быть, что очень весело возбуждает петлю)
2. Не учитываете задержку в детекторе, что может сделать петлю нестабильной.

Вот код, в котором я попытался устранить эти недостатки (да и вычислений делается меньше)

Код
% input signal generation start
N=5*1000; % length of input signal
ft=N/5;
fs=(1-1/5)*N;
A(1:N/5)= 2^5; % max values
A(N/5+1:2*N/5)  = 2^5;
A(2*N/5+1:3*N/5)= 2^8;
A(3*N/5+1:4*N/5)= 2^11;
A(4*N/5+1:5*N/5)= 2^7;
x= A.*exp(2*pi*j*ft*[1:N]/fs);
x=x.';
% input signal end
% initialization start
y1   = zeros(1,length(x));
y2   = zeros(1,length(x));
norm = zeros(1,length(x));
A1(1)= 0;  % Gain for exp
A2(1)= 1;  % Gain for linear
avg  = 0;
acc  = 0;
% initialization end

% PARAMETERS of AGC
R  = 10;     % reference
a1 = 0.0001; % for exp
K  = 8; %error signal scaling
min_gain = 1/64;
max_gain = 64;
B  = 2^3; % length of buffer
% ---------

% main
result = 1;
for k=1:length(x)-1
% exp AGC (Nezami)
    y1(k) = 2^[A1(k)] * x(k);
    A1(k+1) = A1(k) + a1*(2^R - [abs(real(y1(k))) + abs(imag(y1(k)))]);
% linear AGC
    y2(k) = A2(k) * x(k);
    norm(k) = abs(real(y2(k))) + abs(imag(y2(k)));
    if (k<=B) % AVG in buffer
           avg = avg + norm(k);
    else
           avg = avg + norm(k)-norm(k-B);
    end
    if mod(k-1,B)==0    
    diff = fix(2^R - avg/B)/(2^K);
    if (acc + diff) > min_gain;
        acc = acc + diff;
        if(acc > max_gain)
            acc = max_gain;    
        end    

    else
        acc = min_gain;
        end        
        
        result  = acc;      
    else
        result = result;
    end            
    A2(k+1) = result;  
end
figure(1)
subplot(311); plot([ real(x).' ]); grid;shg
subplot(312); plot([ real(y1).']); grid;shg
subplot(313); plot([ real(y2).']); grid;shg
%subplot(313); plot([ real(A2).']); grid;shg


Аккумулятор работает в режиме fractional арифметики (K бит после двоичной точки и log2(max_gain) до точки). Еще стоит проверять, что diff не сильно отличается от эталона и в этом случае не трогать усиление. Это избавит от паразитной АМ.
Что-то типа if(diff < threshold_diff)... - думать лень.
vea
Цитата(andyp @ Jan 8 2014, 22:35) *
У Вас две стандартные ошибки (по степени важности)-
1. Не ослеживаете макс и мин значение усиления (у Вас оно даже отрицательным может быть, что очень весело возбуждает петлю)
2. Не учитываете задержку в детекторе, что может сделать петлю нестабильной.

Вот код, в котором я попытался устранить эти недостатки (да и вычислений делается меньше)



Ух ты!
andyp, спасибо!
С отрицательными значениями просто не знал, что делать. Теперь-то очевидно, что введение макс и мин значений решает эту проблему, но это только теперь sm.gif
Вникаю дальше.
vea
Возникли еще вопросы:
1. Про учет задержки не понимаю. Что имеется в виду?
Детектор выдает результат по В входным значениям и он применяется к (B+1)-ому элементу. Эта задержка имеется в виду?
Из-за этого добавлено сравнение по модулю?
2. Основная проблема при реализации - деление на 2^K. Как Вы указали, результат должен быть дробным (floor, то есть сдвиг, все портит). Не очень представляю, как это деление можно реализовать в FPGA.
Может быть, есть другие пути?

Спасибо.

Вот часть кода, который достаточно понятно реализуется аппаратно (если B - степень двойки) - кроме вычисления diff:
Код
    if mod(k-1,B)==0
        avg2 = floor(avg/B);
        if ( avg2<0 )  
            avg2 = avg2+1; % imitation of "fix" function
        end
        avg3 = 2^R-avg2;
        diff = avg3/2^K; % floor(avg3/2^K) is not work!
        acc = acc + diff;
        if(acc > max_gain)
            acc = max_gain;
        end
        if (acc < min_gain);
            acc = min_gain;
        end
        result  = acc;
    end


Меня не покидает ощущение, что эти вопросы должны быть где-то подробно описаны.
Но поиски дают только общие схемы (аналогичные приведённым в книге Незами).
Никакой конкретики. Никаких примеров выбора коэффициентов.
Никакого учета запаздывания детектора sm.gif
Посоветуйте, пожалуйста, источники.
andyp
На счет литературы посоветовать не могу - набирался понемногу из разных книжек и собственных шишек sm.gif, используя здравый смысл и немного элементарной математики.

На счет задержки - детектор в петле АРУ использует усреднение для получения оценки мощности входного сигнала. Т.е. если мощность меняется в окне усреднения, то детектор выдаст нечто среднее для отсчетов, попавших в окно, соответствующее оценке мощности для одного из прошлых отсчетов. Рассмотрим почему это может быть плохо - если мощность меняется по синусоидальному закону, то оценка, полученная для "ямы" синуса будет в худшем случае из-за задержки применяться к "горбу" - на выходе получим большие колебания мощности, чем на входе. Т.е. петля может стать нестабильной. Обычно это не проблема в системах АРУ (мощность меняется медленно), но все-же... Это все можно почерпнуть из науки Control Systems, где рассуждают об устойчивости и phase margin. Поэтому разумно сузить полосу петли АРУ реже обновляя значение усиления (вовсе не обязательно обновлять усиление для каждого входного отсчета и использовать скользящую оценку мощности - можно просто взять кусочек сигнала, подсчитать оценку мощности, применить ее для следующего кусочка и т.п. - фактически, для оценки мощности используем интегратор со сбросом)

На счет деления - аккумулятор должен использовать т.н. fractional arithmetic (можно почитать wiki про fixed-point arithmetic и Q (number format)). Это просто - внутри разрядов аккумулятора ставим точку. Разряды до точки соответствуют целой части, после точки - дробной (т.е. фактически при использовании таких чисел оставляем сколько нам нужно дробных разрядов). Положение точки нужно учитывать при умножении и делении, нужным образом сдвигая результат. Точка не влияет на реализацию сложения и вычитания (оно такое же как и для обычных fixed-point целых чисел) . Про это есть в книжке Koren Computer Arithmetic Algorithms, но я бы не стал ее читать только ради этого sm.gif
vea
С задержкой прояснилось, спасибо за объяснение.
С делением тоже разобрался - не сразу понял, что имелось в виду под fractional арифметикой.
Большое спасибо за помощь!

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.