Jump to content

    
Sign in to follow this  
dima_spb

БПФ

Recommended Posts

И все равно надо что-то написать
А как же )) Мы, злостные флудеры, такие ))) Расслабьтесь. Мы же сюда заходим не только работать, но и отдохнуть от работы. Лёгкий флуд - терпимо.

 

Share this post


Link to post
Share on other sites
А как же )) Мы, злостные флудеры, такие ))) Расслабьтесь. Мы же сюда заходим не только работать, но и отдохнуть от работы. Лёгкий флуд - терпимо.

 

Ах...вот оно что?!

Share this post


Link to post
Share on other sites

Уважаемые форумчане :biggrin: Возникли трудности, прошу по возможности помощи.

Речь о БПФ, если кто не в курсе.

1. Бабочка по основанию 2

2. 16 точек

3. Частота дискретизации 5 МГц

4. Прореживание во времени

5. Соответственно 8 коэффициентов

6. Реализация на ПЛИС (verilog).

7. Моделирую в Modelsim

8. Пытаюсь :smile3046: проверить работу алгоритма в Mathlab

________________________________________________________________________________

_

Я построил свою работу следующим образом:

1. Используя описание 16-ти точечного БПФ в Матлаб рассчитал коэфициенты и подставил удобные для себя входные отсчеты. В итоге построил график post-74498-1435300703_thumb.png, на котором увидел ожидаемую для себя картинку при входных отсчетах

ss = [828 1515 1943 2038 1784 1225 457 -390 -1170 -1750 -2030 -1963 -1560 -890 -68 0];

и коэффициентах

w0 = (1+0i);
w1 = (0.9239-0.3827i);
w2 = (0.7071-0.7071i);
w3 = (0.3827-0.9239i);
w4 = (0-1i);
w5 = (-0.3827-0.9239i);
w6 = (-0.7071-0.7071i);
w7 = (-0.9239-0.3827i);

 

2. После этого зная из Матлаб результаты всех вычислений я переместился в Modelsim и начал там тестировать свой БПФ описанный на Verilog. В качестве входных значений я использовал те же, что и в Матлаб представленных в дополнительном коде. т.е. мантисса занимает биты с 0 по 10, а 11 бит знаковый в итоге диапазон входных значений от -2047 до +2047.

С коэффициентами иначе. Та как коэффициенты у меня меняются от -1 до +1, тогда я их домножил на все те же 2047 и округлил, 11 битом прикрепил знак. В итоге мои коэффициенты стали иметь вид:

w0 = 2047 + 0i;
w1 = 1891-783i;
w2 = 1447-1447i;
w3 = 783-1891i;
w4 = 0-2047i;
w5 = -783-1891i;
w6 = -1447 - 1447i;
w7= -1891-783i;

 

3. И тут я как "умная Маша" :smile3046: попытался засунуть округленные коэффициенты в целочисленной форме в Матлаб. В итоге у меня на выходе ерунда вместо прежней картинки.

И я не понимаю почему????

Нужно что-то менять в матлаб? Просто мне никак не проверить корректность работы БПФ описанного verilog. Хочется иметь одни и те же коэффициенты и в Матлаб и в Моделсим.

 

Привожу код БПФ из Матлаб

 

 

ss = [828 1515 1943 2038 1784 1225 457 -390 -1170 -1750 -2030 -1963 -1560 -890 -68 0];
%k2 = [0:7];
%W2 = exp( -j*2*pi.*k2/16 );
w11 = (1+0i);
w12 = (0.9239-0.3827i);
w13 = (0.7071-0.7071i);
w14 = (0.3827-0.9239i);
w15 = (0-1i);
w16 = (-0.3827-0.9239i);
w17 = (-0.7071-0.7071i);
w18 = (-0.9239-0.3827i);

W2 = [ w11 w12 w13 w14 w15 w16 w17 w18];
s2r = [ss(1) ss(9) ss(5) ss(13) ss(3) ss(11) ss(7) ss(15) ss(2) ss(10) ss(6) ss(14) ss(4) ss(12) ss(8) ss(16)];

%первый шаг 
s11 = s2r(1) + s2r(2);
s12 = s2r(1) - s2r(2);
s13 = s2r(3) + s2r(4);
s14 = s2r(3) - s2r(4);
s15 = s2r(5) + s2r(6);
s16 = s2r(5) - s2r(6);
s17 = s2r(7) + s2r(8);
s18 = s2r(7) - s2r(8);
s19 = s2r(9) + s2r(10);
s110= s2r(9) - s2r(10);
s111= s2r(11)+ s2r(12);
s112= s2r(11)- s2r(12);
s113= s2r(13)+ s2r(14);
s114= s2r(13)- s2r(14);
s115= s2r(15)+ s2r(16);
s116= s2r(15)- s2r(16);


%второй шаг 

s21 = s11 + s13* W2(1);
s22 = s12 + s14* W2(5);
s23 = s11 - s13* W2(1);
s24 = s12 - s14* W2(5);

s25 = s15 + s17* W2(1);
s26 = s16 + s18* W2(5);
s27 = s15 - s17* W2(1);
s28 = s16 - s18* W2(5);

s29 = s19 + s111* W2(1);
s210 = s110 + s112*W2(5);
s211 = s19 - s111* W2(1);
s212 = s110 - s112*W2(5);

s213 = s113 + s115*W2(1);
s214 = s114 + s116*W2(5);
s215 = s113 - s115*W2(1);
s216 = s114 - s116*W2(5);

%шаг 3
s31 = s21 +  s25*W2(1);
s32 = s22 +  s26*W2(3);
s33 = s23 +  s27*W2(5);
s34 = s24 +  s28*W2(7);
s35 = s21 -  s25*W2(1);
s36 = s22 -  s26*W2(3);
s37 = s23 -  s27*W2(5);
s38 = s24 -  s28*W2(7);

s39 = s29 +  s213*W2(1);
s310= s210 + s214*W2(3);
s311= s211 + s215*W2(5);
s312= s212 + s216*W2(7);
s313 = s29 - s213*W2(1);
s314= s210 - s214*W2(3);
s315= s211 - s215*W2(5);
s316= s212 - s216*W2(7);

%шаг 4

s41 = s31 + s39*W2(1);
s42 = s32 + s310*W2(2);
s43 = s33 + s311*W2(3);
s44 = s34 + s312*W2(4);
s45 = s35 + s313*W2(5);
s46 = s36 + s314*W2(6);
s47 = s37 + s315*W2(7);
s48 = s38 + s316*W2(8);

s49 = s31 - s39*W2(1);
s410 = s32 - s310*W2(2);
s411 = s33 - s311*W2(3);
s412 = s34 - s312*W2(4);
s413 = s35 - s313*W2(5);
s414 = s36 - s314*W2(6);
s415 = s37 - s315*W2(7);
s416 = s38 - s316*W2(8);

%Строим график

x = [0 : 15];
y = [s41, s42, s43, s44, s45, s46, s47, s48, s49, s410, s411, s412, s413,s414, s415, s416];
plot (x, y)

 

Share this post


Link to post
Share on other sites

Предполагаю, что вы напутали со знаковой математикой. Verilog, в отличие от С, считает переменные без знаковыми, покуда не укажете обратное.

Share this post


Link to post
Share on other sites

К счастью, в доп.коде операции делаются идентично, поэтому указание знака необязательно. Лично я ставлю reg signed или wire signed только для того, чтобы в симуляторе наблюдать сразу знаковые значения.

Share this post


Link to post
Share on other sites
Да, в матлабе посчитаю и в mif засуну.

Quartus поддерживает инструкцию $readmemh для блочного ROM в Verilog. Вообще не надо париться с написанием. Забил reg. Прописал $readmemh в initial.

 

К счастью, в доп.коде операции делаются идентично, поэтому указание знака необязательно. Лично я ставлю reg signed или wire signed только для того, чтобы в симуляторе наблюдать сразу знаковые значения.

Ничего подобного. При умножении надо указывать $signed иначе будет непредсказуемая ерунда, даже если указана знаковая переменная.

Share this post


Link to post
Share on other sites

Пока тема свежая, задамка вопрос по БПФ.

 

Вот написал я свое ядро бпф.

Работает оно так, что подаю на вход N точек, оно N*log(N) тактов рассчитает результат.

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

А вот у альтеры и ксайлинка ip-ядра способны принимать новые кадры без пауз.

Как это у них реализовано?

 

Самый дубовый вариант - буферизировать входные данные. Но размер буфера будет определяться величиной log(N), а у альтеры/ксайлинкса не наблюдается, чтобы ядро требовало больше памяти, чем под один кадр.

Share this post


Link to post
Share on other sites
Пока тема свежая, задамка вопрос по БПФ.

 

Вот написал я свое ядро бпф.

Работает оно так, что подаю на вход N точек, оно N*log(N) тактов рассчитает результат.

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

А вот у альтеры и ксайлинка ip-ядра способны принимать новые кадры без пауз.

Как это у них реализовано?

 

Самый дубовый вариант - буферизировать входные данные. Но размер буфера будет определяться величиной log(N), а у альтеры/ксайлинкса не наблюдается, чтобы ядро требовало больше памяти, чем под один кадр.

Вообще-то обычный Радикс-2/4 работает именно кадрами. Накапление->вычисление->выдача результата(накопление). Есть ещё по-моему потоковый алгоритм у них, но только на небольшое число точек и с большим ресурсом..

В своё время делал FFT - при разумной полосе спектра сигнала(скажем до 50 МГц) вполне хватает буфера на N точек.

1. Ядро вполне реально разогнать до максимальной частоты BRAM/DSP - смотря что меньше. Пусть будет 500. А это сразу даёт 10 тактов вычисления на 1 такт данных.

2. Первую бабочку можно сделать сразу в момент прихода второй половины входных отсчётов, так как там коэффициенты только единицы.

3. При реализации БПФ с прореживанием по частоте довольно легко при каждом следующем проходе увеличивать число ядер вдвое(в разумных пределах), так как области данных между собой больше не пересекаются и в связи с этим можно разграничить доступ к области памяти.

Всё это конечно усложняет реализацию, но бывают случаи, когда это меньшее из зол.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Бегло читаем документ.

 

Находим в нем "The variable streaming FFTs implement either a radix-2^2 single delay feedback FFT, ..."

 

Ищем гуглом "sdf fft" или "r4sdf fft", или "r2sdf fft"

 

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

Share this post


Link to post
Share on other sites

 

Пока тема свежая, задамка вопрос по БПФ.

 

Вот написал я свое ядро бпф.

Работает оно так, что подаю на вход N точек, оно N*log(N) тактов рассчитает результат.

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

А вот у альтеры и ксайлинка ip-ядра способны принимать новые кадры без пауз.

Как это у них реализовано?

 

Самый дубовый вариант - буферизировать входные данные. Но размер буфера будет определяться величиной log(N), а у альтеры/ксайлинкса не наблюдается, чтобы ядро требовало больше памяти, чем под один кадр.

Самый дубовый вариант, это поставить N блоков БПФ и коммутировать поотсчетно, подавая их на входы со сдвигом на отсчет. А у Altera и Xilinx используется БПФ со сдвигом не на отсчет, а на 1/2... 1/4 размера блока. По сути, имеется 2... 4 БПФ блока. В результате, на выходе почти отсутствуют разрывы фазы. Но такое преобразование годится не для всех видов модуляции. Иногда приходится делать перекрытие еще меньше 1/4.

Edited by Corner

Share this post


Link to post
Share on other sites
Самый дубовый вариант, это поставить N блоков БПФ и коммутировать поотсчетно, подавая их на входы со сдвигом на отсчет. А у Altera и Xilinx используется БПФ со сдвигом не на отсчет, а на 1/2... 1/4 размера блока. По сути, имеется 2... 4 БПФ блока. В результате, на выходе почти отсутствуют разрывы фазы. Но такое преобразование годится не для всех видов модуляции. Иногда приходится делать перекрытие еще меньше 1/4.

По поводу поточного БПФ - все достаточно просто. Описано в соответствующих букварях. Небольшая заметка по этому поводу для ПЛИС http://acvarif.info/prvhdl/prvhdl25.html Такой метод довольно ресурсозатратный, но при наличии в ПЛИС аппаратных умножителей все работает неплохо.

Share this post


Link to post
Share on other sites
Ничего подобного. При умножении надо указывать $signed иначе будет непредсказуемая ерунда, даже если указана знаковая переменная.
Для сложения - без разницы. А для умножения - согласен, могут быть нюансы. И то, у Xilinx реализован аппаратный умножитель чисел дополнительного кода, так что это для него нативно.

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this