|
|
  |
БПФ, Прошу пояснения |
|
|
|
May 20 2015, 05:20
|

Местный
  
Группа: Свой
Сообщений: 397
Регистрация: 21-11-12
Из: Россия г. Санкт-Петербург
Пользователь №: 74 498

|
Цитата(Krys @ May 19 2015, 14:37)  А как же )) Мы, злостные флудеры, такие ))) Расслабьтесь. Мы же сюда заходим не только работать, но и отдохнуть от работы. Лёгкий флуд - терпимо. Ах...вот оно что?!
--------------------
Победа - это когда N раз упал и N+1 раз встал.
|
|
|
|
|
Jun 26 2015, 07:14
|

Местный
  
Группа: Свой
Сообщений: 397
Регистрация: 21-11-12
Из: Россия г. Санкт-Петербург
Пользователь №: 74 498

|
Уважаемые форумчане  Возникли трудности, прошу по возможности помощи. Речь о БПФ, если кто не в курсе. 1. Бабочка по основанию 2 2. 16 точек 3. Частота дискретизации 5 МГц 4. Прореживание во времени 5. Соответственно 8 коэффициентов 6. Реализация на ПЛИС (verilog). 7. Моделирую в Modelsim 8. Пытаюсь  проверить работу алгоритма в Mathlab ________________________________________________________________________________ _ Я построил свою работу следующим образом: 1. Используя описание 16-ти точечного БПФ в Матлаб рассчитал коэфициенты и подставил удобные для себя входные отсчеты. В итоге построил график
, на котором увидел ожидаемую для себя картинку при входных отсчетах Код 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. И тут я как "умная Маша"  попытался засунуть округленные коэффициенты в целочисленной форме в Матлаб. В итоге у меня на выходе ерунда вместо прежней картинки. И я не понимаю почему????Нужно что-то менять в матлаб? Просто мне никак не проверить корректность работы БПФ описанного 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)
--------------------
Победа - это когда N раз упал и N+1 раз встал.
|
|
|
|
|
Sep 21 2015, 19:27
|

Профессионал
    
Группа: Участник
Сообщений: 1 072
Регистрация: 11-12-12
Пользователь №: 74 815

|
Цитата(Kapsik @ Apr 21 2015, 14:59)  Да, в матлабе посчитаю и в mif засуну. Quartus поддерживает инструкцию $readmemh для блочного ROM в Verilog. Вообще не надо париться с написанием. Забил reg. Прописал $readmemh в initial. Цитата(Krys @ Aug 25 2015, 09:59)  К счастью, в доп.коде операции делаются идентично, поэтому указание знака необязательно. Лично я ставлю reg signed или wire signed только для того, чтобы в симуляторе наблюдать сразу знаковые значения. Ничего подобного. При умножении надо указывать $signed иначе будет непредсказуемая ерунда, даже если указана знаковая переменная.
|
|
|
|
|
Sep 23 2015, 06:23
|

Местный
  
Группа: Свой
Сообщений: 375
Регистрация: 9-10-09
Из: Свердловский регион
Пользователь №: 52 845

|
Пока тема свежая, задамка вопрос по БПФ.
Вот написал я свое ядро бпф. Работает оно так, что подаю на вход N точек, оно N*log(N) тактов рассчитает результат. И получается, что пока производится расчет я не могу на вход подавать следующий кадр, так как внутри задействована память на N отсчетов, умножитель, два сумматора, и во время расчета они постоянно заняты, конвеером пустить новые данные ну ни как. А вот у альтеры и ксайлинка ip-ядра способны принимать новые кадры без пауз. Как это у них реализовано?
Самый дубовый вариант - буферизировать входные данные. Но размер буфера будет определяться величиной log(N), а у альтеры/ксайлинкса не наблюдается, чтобы ядро требовало больше памяти, чем под один кадр.
|
|
|
|
|
Sep 23 2015, 08:12
|
Частый гость
 
Группа: Свой
Сообщений: 180
Регистрация: 17-02-09
Из: Санкт-Петербург
Пользователь №: 45 001

|
Цитата(novartis @ Sep 23 2015, 09:23)  Пока тема свежая, задамка вопрос по БПФ.
Вот написал я свое ядро бпф. Работает оно так, что подаю на вход N точек, оно N*log(N) тактов рассчитает результат. И получается, что пока производится расчет я не могу на вход подавать следующий кадр, так как внутри задействована память на N отсчетов, умножитель, два сумматора, и во время расчета они постоянно заняты, конвеером пустить новые данные ну ни как. А вот у альтеры и ксайлинка ip-ядра способны принимать новые кадры без пауз. Как это у них реализовано?
Самый дубовый вариант - буферизировать входные данные. Но размер буфера будет определяться величиной log(N), а у альтеры/ксайлинкса не наблюдается, чтобы ядро требовало больше памяти, чем под один кадр. Вообще-то обычный Радикс-2/4 работает именно кадрами. Накапление->вычисление->выдача результата(накопление). Есть ещё по-моему потоковый алгоритм у них, но только на небольшое число точек и с большим ресурсом.. В своё время делал FFT - при разумной полосе спектра сигнала(скажем до 50 МГц) вполне хватает буфера на N точек. 1. Ядро вполне реально разогнать до максимальной частоты BRAM/DSP - смотря что меньше. Пусть будет 500. А это сразу даёт 10 тактов вычисления на 1 такт данных. 2. Первую бабочку можно сделать сразу в момент прихода второй половины входных отсчётов, так как там коэффициенты только единицы. 3. При реализации БПФ с прореживанием по частоте довольно легко при каждом следующем проходе увеличивать число ядер вдвое(в разумных пределах), так как области данных между собой больше не пересекаются и в связи с этим можно разграничить доступ к области памяти. Всё это конечно усложняет реализацию, но бывают случаи, когда это меньшее из зол.
|
|
|
|
|
Sep 25 2015, 08:48
|
ʕʘ̅͜ʘ̅ʔ
    
Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691

|
Бегло читаем документ. Находим в нем "The variable streaming FFTs implement either a radix-2^2 single delay feedback FFT, ..." Ищем гуглом "sdf fft" или "r4sdf fft", или "r2sdf fft" Цитата(novartis @ Sep 24 2015, 16:05)  Погонял модель бпф от альтеры и в сигналтапе на железе посмотрел. Потоком кадры друг за дружкой засылаю, на выходе результат также потоком выходит, без разрывов. Как же они это реализовали?
|
|
|
|
|
Sep 27 2015, 20:05
|

Профессионал
    
Группа: Участник
Сообщений: 1 072
Регистрация: 11-12-12
Пользователь №: 74 815

|
Цитата(novartis @ Sep 23 2015, 10:23)  Пока тема свежая, задамка вопрос по БПФ.
Вот написал я свое ядро бпф. Работает оно так, что подаю на вход N точек, оно N*log(N) тактов рассчитает результат. И получается, что пока производится расчет я не могу на вход подавать следующий кадр, так как внутри задействована память на N отсчетов, умножитель, два сумматора, и во время расчета они постоянно заняты, конвеером пустить новые данные ну ни как. А вот у альтеры и ксайлинка ip-ядра способны принимать новые кадры без пауз. Как это у них реализовано?
Самый дубовый вариант - буферизировать входные данные. Но размер буфера будет определяться величиной log(N), а у альтеры/ксайлинкса не наблюдается, чтобы ядро требовало больше памяти, чем под один кадр. Самый дубовый вариант, это поставить N блоков БПФ и коммутировать поотсчетно, подавая их на входы со сдвигом на отсчет. А у Altera и Xilinx используется БПФ со сдвигом не на отсчет, а на 1/2... 1/4 размера блока. По сути, имеется 2... 4 БПФ блока. В результате, на выходе почти отсутствуют разрывы фазы. Но такое преобразование годится не для всех видов модуляции. Иногда приходится делать перекрытие еще меньше 1/4.
Сообщение отредактировал Corner - Sep 27 2015, 20:07
|
|
|
|
|
Sep 30 2015, 16:55
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Corner @ Sep 27 2015, 23:05)  Самый дубовый вариант, это поставить N блоков БПФ и коммутировать поотсчетно, подавая их на входы со сдвигом на отсчет. А у Altera и Xilinx используется БПФ со сдвигом не на отсчет, а на 1/2... 1/4 размера блока. По сути, имеется 2... 4 БПФ блока. В результате, на выходе почти отсутствуют разрывы фазы. Но такое преобразование годится не для всех видов модуляции. Иногда приходится делать перекрытие еще меньше 1/4. По поводу поточного БПФ - все достаточно просто. Описано в соответствующих букварях. Небольшая заметка по этому поводу для ПЛИС http://acvarif.info/prvhdl/prvhdl25.html Такой метод довольно ресурсозатратный, но при наличии в ПЛИС аппаратных умножителей все работает неплохо.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|