acvarif 0 1 сентября, 2013 Опубликовано 1 сентября, 2013 · Жалоба Стоит задачка написать код (VHDL) для FFT32 (прореживание по времени). Поскольку структура построения такого модуля мне пока до конца не понята, то пытаюсь взять за основу структуру построения FFT8. В сети нашел пока только это http://vhdlguru.blogspot.com/2011/06/non-s...or-8-point.html. Толку с этого немного, поскольку код несинтезируемый. Но в общем понятно, что должно быть три этапа, каждый из которых это вычисление бабочки и запись результатов на место предыдущего вычисления. Для этого понадобится ram, собственно модуль бабочки, миксер для перестановки адресов при очередной записи результатов в ram и небольшая схема управления. Для моей задачи не обязательно иметь на входе разделенный сигнал на реал и мним, поскольку выборки поступают через 90 градусов. Тоесть можно по очереди выполнять FFT сначала для реал потом для мним. На выходе после двух преобразований сложить квадраты и взять корень. Это должно дать экономию в ресурсах. В связи с этим вопросы 1. Можно-ли как-то на VHDL выполнить операцию взятия квадратного корня? Или все-же проще, как везде принято, иметь FFT который работает с реал и мним? 2. Нет-ли у кого, для примера, синтезируемого кода FFT8? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aser 0 1 сентября, 2013 Опубликовано 1 сентября, 2013 · Жалоба Вот здесь http://opencores.org/project,pipelined_fft_64 есть синтезируемый проект с описанием. В т.ч. и модуль FFT8. А там же рядом есть такой же проект с FFT32. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 1 сентября, 2013 Опубликовано 1 сентября, 2013 · Жалоба Вот здесь http://opencores.org/project,pipelined_fft_64 есть синтезируемый проект с описанием. В т.ч. и модуль FFT8. А там же рядом есть такой же проект с FFT32. Спасибо. Сразу не обратил внимание, что fft64 сделан на базе fft8 (прорежен по времени). FFT32 не нашел... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dsmv 0 2 сентября, 2013 Опубликовано 2 сентября, 2013 · Жалоба Вот здесь кое-что есть. Это работает. Но описания нет. http://ds-dev.ru/projects/fpi-dsp Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 2 сентября, 2013 Опубликовано 2 сентября, 2013 (изменено) · Жалоба Вот здесь кое-что есть. Это работает. Но описания нет. http://ds-dev.ru/projects/fpi-dsp Спасибо. Зарегистрировался. Если по ссылке то файлов там нет. Но меня пока все устроит и с фиксированной точкой. Пара вопросов по алгоритму. Для 128 точек алгоритм такой: The basis of the FFT is that a DFT can be divided into smaller DFTs. In the processor FFT128 a mixed radix 8 and 16 FFT algorithm is used. It divides DFT into two smaller DFTs of the length 8 and 16, as it is shown in the formula: 15 mr ms 7 sl X(k) = X(16r+s) = ∑ W16 W128 ∑ x(16l + m) W8 r = 0 to 15, s = 0 to 7 m=0 l=0 which shows that 128-point DFT is divided into two smaller 8- and16-point DFTs. This algorithm is illustrated by the graph which is shown in the Fig.1. The input complex data x(n) are represented by the 2-dimensional array of data x(16l+m). The columns of this array are computed by 8-point DFTs. The results of them are multiplied by the twiddle factors W128ms . And the resulting array of data X(16r+s) is derived by 16-point DFTs of rows of the intermediate result array. Тогда для 32_х точек можно пойти таким путем: 8 mr ms 4 sl X(k) = X(8r+s) = ∑ W8 W32 ∑ x(8l + m) W4 r = 0 to 8, s = 0 to 4 m=0 l=0 Из этого выходит, что сначала вычисляются четыре 8_ми точечных БПФ. Все результаты (32) умножаются на поворачивающий множитель W32/ms. А как дальше? Что нужно еще для получения результата? Ага, понятно. Дальше вычисляются 8 штук 4_х точечных БПФ. Их выходная матрица 4 на 8 это и есть результат. Изменено 2 сентября, 2013 пользователем Acvarif Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 3 сентября, 2013 Опубликовано 3 сентября, 2013 (изменено) · Жалоба Cинтезируемый код fft8 с opencores компилируется нормально. ///////////////////////////////////////////////////////////////////// // FUNCTION: 8-point FFT // FILES: FFT8.v - 1-st stage, contains // MPU707.v - multiplier to the factor 0.707. // PROPERTIES:1) Fully pipelined // 2) Each clock cycle complex datum is entered // and complex result is outputted // 3) Has 8-clock cycle period starting with the START // impulse and continuing forever // 4) rounding is not used // 5)Algorithm is from the book "H.J.Nussbaumer FFT and // convolution algorithms". // 6)IFFT is performed by substituting the output result // order to the reversed one // (by exchanging - to + and + to -) ///////////////////////////////////////////////////////////////////// //Algorithm: // procedure FFT8( // D: in MEMOC8; -- input array // DO:out MEMOC8) -- output ARRAY // is // variable t1,t2,t3,t4,t5,t6,t7,t8,m0,m1,m2,m3,m4,m5,m6,m7: complex; // variable s1,s2,s3,s4: complex; // begin // t1:=D(0) + D(4); // m3:=D(0) - D(4); // t2:=D(6) + D(2); // m6:=CBASE_j*(D(6)-D(2)); // t3:=D(1) + D(5); // t4:=D(1) - D(5); // t5:=D(3) + D(7); // t6:=D(3) - D(7); // t8:=t5 + t3; // m5:=CBASE_j*(t5-t3); // t7:=t1 + t2; // m2:=t1 - t2; // m0:=t7 + t8; // m1:=t7 - t8; // m4:=SQRT(0.5)*(t4 - t6); // m7:=-CBASE_j*SQRT(0.5)*(t4 + t6); // s1:=m3 + m4; // s2:=m3 - m4; // s3:=m6 + m7; // s4:=m6 - m7; // DO(0):=m0; // DO(4):=m1; // DO(1):=s1 + s3; // DO(7):=s1 - s3; // DO(2):=m2 + m5; // DO(6):=m2 - m5; // DO(5):=s2 + s4; // DO(3):=s2 - s4; // end procedure; ///////////////////////////////////////////////////////////////////// `timescale 1ps / 1ps `include "FFT64_CONFIG.inc" module fft8 ( DOR ,DII ,RST ,ED ,CLK ,DOI ,START ,DIR ,RDY ); `USFFT64paramnb input ED; wire ED; input RST; wire RST; input CLK; wire CLK; input [nb-1:0] DII; wire [nb-1:0] DII; input START; wire START; input [nb-1:0] DIR; wire [nb-1:0] DIR; output [nb+2:0] DOI; wire [nb+2:0] DOI; output [nb+2:0] DOR; wire [nb+2:0] DOR; output RDY; reg RDY; reg [2:0] ct; //main phase counter reg [3:0] ctd; //delay counter always @( posedge CLK) begin //Control counter // if (RST) begin ct<=0; ctd<=15; RDY<=0; end else if (START) begin ct<=0; ctd<=0; RDY<=0; end else if (ED) begin RDY<=0; ct<=ct+1; if (ctd !=4'b1111) ctd<=ctd+1; if (ctd==12 ) RDY<=1; end end reg signed [nb-1: 0] dr,d1r,d2r,d3r,d4r,di,d1i,d2i,d3i,d4i; always @(posedge CLK) // input register file begin if (ED) begin dr<=DIR; d1r<=dr; d2r<=d1r; d3r<=d2r; d4r<=d3r; di<=DII; d1i<=di; d2i<=d1i; d3i<=d2i; d4i<=d3i; end end reg signed [nb:0] s1r,s2r,s1d1r,s1d2r,s1d3r,s2d1r,s2d2r,s2d3r; reg signed [nb:0] s1i,s2i,s1d1i,s1d2i,s1d3i,s2d1i,s2d2i,s2d3i; always @(posedge CLK) begin // S1,S2 =t1-t6,m3 and delayed if (ED && ((ct==5) || (ct==6) || (ct==7) || (ct==0))) begin s1r<=d4r + dr; s1i<=d4i + di; s2r<=d4r - dr; s2i<= d4i - di; end if (ED) begin s1d1r<=s1r; s1d2r<=s1d1r; s1d1i<=s1i; s1d2i<=s1d1i; if (ct==0 || ct==1) begin //## note for vhdl s1d3r<=s1d2r; s1d3i<=s1d2i; end if (ct==6 || ct==7 || ct==0) begin s2d1r<=s2r; s2d2r<=s2d1r; s2d1i<=s2i; s2d2i<=s2d1i; end if (ct==0) begin s2d3r<=s2d2r; s2d3i<=s2d2i; end end end reg signed [nb+1:0] s3r,s4r,s3d1r,s3d2r,s3d3r; reg signed [nb+1:0] s3i,s4i,s3d1i,s3d2i,s3d3i; always @(posedge CLK) begin //ALU S3: if (ED) case (ct) 0: begin s3r<= s1d2r+s1r; //t7 s3i<= s1d2i+ s1i;end 1: begin s3r<= s1d3r - s1d1r; //m2 s3i<= s1d3i - s1d1i; end 2: begin s3r<= s1d3r +s1r; //t8 s3i<= s1d3i+ s1i; end 3: begin s3r<= s1d3r - s1r; // s3i<= s1d3i - s1i; end endcase if (ED) begin if (ct==1 || ct==2 || ct==3) begin s3d1r<=s3r; //t8 s3d1i<=s3i; end if ( ct==2 || ct==3) begin s3d2r<=s3d1r; //m2 s3d3r<=s3d2r; //t7 s3d2i<=s3d1i; s3d3i<=s3d2i; end end end always @ (posedge CLK) begin // S4 if (ED) begin if (ct==1) begin s4r<= s2d2r + s2r; s4i<= s2d2i + s2i; end else if (ct==2) begin s4r<=s2d2r - s2r; s4i<= s2d2i - s2i; end end end assign em = ((ct==2 || ct==3 || ct==4)&& ED); wire signed [nb+1:0] m4m7r,m4m7i; MPU707 #(nb) UMR( .CLK(CLK),.EI(em),.DI(s4r),.DO(m4m7r)); // UMR MPU707 #(nb) UMI( .CLK(CLK),.EI(em),.DI(s4i), .DO(m4m7i)); // UMR reg signed [nb+1:0] sjr,sji, m6r,m6i; always @ (posedge CLK) begin //multiply by J if (ED) begin case (ct) 3: begin sjr<= s2d1i; //m6 sji<=0 - s2d1r; end 4: begin sjr<= m4m7i; //m7 sji<=0 - m4m7r;end 6: begin sjr<= s3i; //m5 sji<=0 - s3r; end endcase if (ct==4) begin m6r<=sjr; //m6 m6i<=sji; end end end reg signed [nb+2:0] s5r,s5d1r,s5d2r,q1r; reg signed [nb+2:0] s5i,s5d1i,s5d2i,q1i; always @ (posedge CLK) // S5: if (ED) case (ct) 5: begin q1r<=s2d3r +m4m7r; // S1 q1i<=s2d3i +m4m7i; s5r<=m6r + sjr; s5i<=m6i + sji; end 6: begin s5r<=m6r - sjr; s5i<=m6i - sji; s5d1r<=s5r; s5d1i<=s5i; end 7: begin s5r<=s2d3r - m4m7r; s5i<=s2d3i - m4m7i; s5d1r<=s5r; s5d1i<=s5i; s5d2r<=s5d1r; s5d2i<=s5d1i; end endcase reg signed [nb+3:0] s6r,s6i; `ifdef paramifft always @ (posedge CLK) begin // S6-- result adder if (ED) case (ct) 5: begin s6r<=s3d3r +s3d1r; // -- D0 s6i<=s3d3i +s3d1i;end //-- D0 6: begin s6r<=q1r - s5r; s6i<=q1i - s5i; end 7: begin s6r<=s3d2r - sjr; s6i<=s3d2i - sji; end 0: begin s6r<=s5r + s5d1r; s6i<= s5i +s5d1i; end 1:begin s6r<=s3d3r - s3d1r; //-- D4 s6i<=s3d3i - s3d1i; end 2: begin s6r<= s5r - s5d1r; // D5 s6i<= s5i - s5d1i; end 3: begin // D6 s6r<=s3d3r + sjr; s6i<=s3d3i + sji; end 4: begin // D0 s6r<= q1r + s5d2r; s6i<= q1i + s5d2i; end endcase end `else always @ (posedge CLK) begin // S6-- result adder if (ED) case (ct) 5: begin s6r<=s3d3r +s3d1r; // -- D0 s6i<=s3d3i +s3d1i;end //-- D0 6: begin s6r<=q1r + s5r; //-- D1 s6i<=q1i + s5i; end 7: begin s6r<=s3d2r +sjr; //-- D2 s6i<=s3d2i +sji; end 0: begin s6r<=s5r - s5d1r; // -- D3 s6i<= s5i - s5d1i;end 1:begin s6r<=s3d3r - s3d1r; //-- D4 s6i<=s3d3i - s3d1i; end 2: begin s6r<=s5r + s5d1r; //-- D5 s6i<=s5i + s5d1i; end 3: begin s6r<= s3d3r - sjr; // D6 s6i<=s3d3i - sji; end 4: begin s6r<= q1r - s5d2r; // D0 s6i<= q1i - s5d2i; end endcase end `endif assign #1 DOR=s6r[nb+2:0]; assign #1 DOI= s6i[nb+2:0]; endmodule module MPU707 ( CLK ,DO ,DI ,EI ); `USFFT64paramnb input CLK; wire CLK; input [nb+1:0] DI; wire signed [nb+1:0] DI; input EI; wire EI; output [nb+1:0] DO; reg [nb+1:0] DO; reg signed [nb+5 :0] dx5; reg signed [nb+2 : 0] dt; wire signed [nb+6 : 0] dx5p; wire signed [nb+6 : 0] dot; always @(posedge CLK) begin if (EI) begin dx5<=DI+(DI <<2); //multiply by 5 dt<=DI; DO<=dot >>>4; end end `ifdef USFFT64bitwidth_0707_high assign dot= (dx5p+(dt>>>4)+(dx5>>>12)); // multiply by 10110101000000101 `else assign dot= (dx5p+(dt>>>4) ); // multiply by 10110101 `endif assign dx5p=(dx5<<1)+(dx5>>>2); // multiply by 101101 endmodule Понять-бы как все работает. Кто работает в verilog, если не лень, прокомментируйте пожалуйста код, хотя-бы в общих чертах. Как все крутится. Предполагается, что данные на вход поступают в бит-инверсном порядке. Не понятно уже в самом начале, почему входные данные (DIR, DII) каждый CLK продвигаются по регистрам? На вход должно поступить 8 реал и 8 мним. А в коде этого не нахожу. Изменено 3 сентября, 2013 пользователем Acvarif Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dsmv 0 3 сентября, 2013 Опубликовано 3 сентября, 2013 · Жалоба Спасибо. Зарегистрировался. Если по ссылке то файлов там нет. Доступ к файлам через Subversion: http://svn.1gb.ru/ds-dev-fpi login: guest password: guest Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 3 сентября, 2013 Опубликовано 3 сентября, 2013 · Жалоба Доступ к файлам через Subversion: <a href="http://electronix.ru/redirect.php?http://svn.1gb.ru/ds-dev-fpi" target="_blank">http://svn.1gb.ru/ds-dev-fpi</a> login: guest password: guest Да, получилось. Полезные файлы. И все же по поводу кода fft8. Судя по коду данные поступают последовательно по каждому клоку. Все поступает на сдвиговый регистр (регистровый файл). Выполнение алгоритма начинается по достижению счетчиком 5 и выше. Почему 5? Почему не загружаются все 8 данных? Не понятно. Почему данные не загружаются параллельно на все 8 + 8 входов? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 4 сентября, 2013 Опубликовано 4 сентября, 2013 · Жалоба И все же по поводу кода fft8. Судя по коду данные поступают последовательно по каждому клоку. Все поступает на сдвиговый регистр (регистровый файл). Выполнение алгоритма начинается по достижению счетчиком 5 и выше. Почему 5? Почему не загружаются все 8 данных? Не понятно. Почему данные не загружаются параллельно на все 8 + 8 входов? Вобщем понятно. Этот код не подходит. В моем случае нужна параллельная загрузка хотя-бы 8_ми выборок. Потом можно делать БПФ8 обычным способом (прореживание по времени). Возник вопрос как делать БПФ. С двумя входами (реал, имаг) или с одним входом. С одним нужно по очереди подавать на него cos и sin выборки, а на выходе после двух преобразований просуммировать квадраты и взять квадратный корень. Вопрос в том как на ПЛИС взять квадратный корень? Если делать БПФ с двумя входами, то не понимаю как для них считать поворачивающие множители. Например для БПФ8 который считает cos_нусную выборку как посчитать поворачивающий множитель W8**2? Просто взять cos 2пи*3/8? Для синусной выборки W8**2 будет sin 2пи*3/8 Получается что для БПФ реал и БПФ имаг будут свои разные поворачивающие множители? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sefo 0 5 сентября, 2013 Опубликовано 5 сентября, 2013 · Жалоба Вопрос в том как на ПЛИС взять квадратный корень? Квадрантый корень функция монотонная, поэтому стоит задуматься а нужно ли его вообще брать - качественный анализ и сравнение можно сделать и по сумме квадратов. Иногда вычисление квадратного корня оставляют процу - т.е. ПЛИС выдает суммы квадратов, а проц досчитывает корни. Если делать БПФ с двумя входами, то не понимаю как для них считать поворачивающие множители. Например для БПФ8 который считает cos_нусную выборку как посчитать поворачивающий множитель W8**2? Просто взять cos 2пи*3/8? Для синусной выборки W8**2 будет sin 2пи*3/8 Получается что для БПФ реал и БПФ имаг будут свои разные поворачивающие множители? Поворачивающий множитель один, так же как и выборка одна - просто это комплексные числа, состоящие из вещественной ("косинусной") и мнимой ("синусной") частей. Поворачивающий множитель C =1*(cos( φ1) + i* sin( φ1) ). Выборка D = I + i*Q. Cоответственно, умножается C * D. При этом расчет поворачивающего множителя не зависит от "количества входов". Независимо от последовательности ввода I и Q компонент выборки (по очереди или оба сразу) в БПФ Вы должна посчитать произведение C * Q Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 5 сентября, 2013 Опубликовано 5 сентября, 2013 (изменено) · Жалоба Поворачивающий множитель один, так же как и выборка одна - просто это комплексные числа, состоящие из вещественной ("косинусной") и мнимой ("синусной") частей. Поворачивающий множитель C =1*(cos( φ1) + i* sin( φ1) ). Выборка D = I + i*Q. Cоответственно, умножается C * D. При этом расчет поворачивающего множителя не зависит от "количества входов". Независимо от последовательности ввода I и Q компонент выборки (по очереди или оба сразу) в БПФ Вы должна посчитать произведение C * Q Спасибо. Я так и думал по поводу квадратного корня. Но в моем случае мне придется после БПФ искать максимум максиморум из 32 частотных выходов (потом на комп уже пойдет информация только о номере частотного выхода). Можно-ли в этом случае обойтись без корня? Хотя стоп... При чем тут корень? Если выполнить БПФ для четных выборок, затем для нечетных (выорки (все 32 штуки) идут через 90 градусов). То потом для получения частотного отсчета результаты нужно будет просто сложить. Опережение либо отставание по фазе четных от нечетных определит место частотного всплеска - справа от центра (N/2) или слева. Вроде так. Или нет? По поводу поворачивающих множителей не врубился. Дело в том, что у меня выборки разделены на косинусную и синусную (идут через 90 градусов). Думаю, что комплексным числом будет то, что получится за две выборки. А значит для первой выборки поворачивающий множитель будет cos, для второй sin. Или я все путаю с квадратурой? Если каждая выборка число комплексное то поворачивающий множитель нужно считать одинаково? Поскольку пишу FFT8 (в дальнейшем FFT32 по алгоритму представленному формулой выше) (код потом представлю) под свою конкретную задачу по ходу так и не врубился с поворачивающими множителями и реальной и мнимой частями FFT. FFT у меня имеет один вход. Поскольку выборки идут через 90 градусов (синус и косинус) то делаю так: Например четные подаю на FFT (будем считать вход реал FFT) результат сохраняю в буфере, затем FFT с нечетными выборками (считаю как вход имаг FFT). Достаю из буфера то, что рассчитано первым и дальше сумма первого и второго. Для информации: у нас выборки не по синусоиде, а по пространственной частоте которая формируется на 32_ух отдельных датчиках гидроакустической антенны. Каждая выборка это сразу 32 входных точки БПФ (выборки сразу на 32_ух синусоидах). С поворачивающими множителями не врублюсь как их посчитать (на калькуляторе, что-ли). Чему например равен поворачивающий множитель W8/2. Как его посчитать? Я так понимаю все будет дробным. Очевидно в VHDL придется все умножить хотя-бы на 1024. На vhdl пытаюсь делать так (пов. множителя взяты от балды). Сигналы с буквой t (например s_st2t_0) имеют 24 бита, без буквы (например s_st2_0) имеют 12 бит входные сигналы(например s_st1_0) все 12 бит -- первый этап FFT8 (прореживание по времени) constant w8_0 : integer :=1; constant w8_1 : integer :=14; constant w8_2 : integer :=28; constant w8_3 : integer :=42; s_st2t_0 <= signed(s_st1_0) + (signed(s_st1_2)*signed(conv_std_logic_vector(w8_0, 12))); s_st2_0 <= s_st2t_0(21 downto 10); s_st2t_1 <= signed(s_st1_1) + (signed(s_st1_3)*signed(conv_std_logic_vector(w8_2, 12))); s_st2_1 <= s_st2t_1(21 downto 10); s_st2t_2 <= signed(s_st1_0) - (signed(s_st1_2)*signed(conv_std_logic_vector(w8_0, 12))); s_st2_2 <= s_st2t_2(21 downto 10); s_st2t_3 <= signed(s_st1_1) - (signed(s_st1_3)*signed(conv_std_logic_vector(w8_2, 12))); s_st2_3 <= s_st2t_3(21 downto 10); s_st2t_4 <= signed(s_st1_4) + (signed(s_st1_6)*signed(conv_std_logic_vector(w8_0, 12))); s_st2_4 <= s_st2t_4(21 downto 10); s_st2t_5 <= signed(s_st1_5) + (signed(s_st1_7)*signed(conv_std_logic_vector(w8_2, 12))); s_st2_5 <= s_st2t_5(21 downto 10); s_st2t_6 <= signed(s_st1_4) - (signed(s_st1_6)*signed(conv_std_logic_vector(w8_0, 12))); s_st2_6 <= s_st2t_6(21 downto 10); s_st2t_7 <= signed(s_st1_5) - (signed(s_st1_7)*signed(conv_std_logic_vector(w8_3, 12))); s_st2_7 <= s_st2t_7(21 downto 10); Можно-ли так считать? Или есть другой путь? Изменено 5 сентября, 2013 пользователем Acvarif Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sefo 0 6 сентября, 2013 Опубликовано 6 сентября, 2013 · Жалоба Спасибо. Я так и думал по поводу квадратного корня. Но в моем случае мне придется после БПФ искать максимум максиморум из 32 частотных выходов (потом на комп уже пойдет информация только о номере частотного выхода). Можно-ли в этом случае обойтись без корня? Нужно - для такой обработки в нем просто нет необходимости. Хотя стоп... При чем тут корень? Если выполнить БПФ для четных выборок, затем для нечетных (выорки (все 32 штуки) идут через 90 градусов). То потом для получения частотного отсчета результаты нужно будет просто сложить. Опережение либо отставание по фазе четных от нечетных определит место частотного всплеска - справа от центра (N/2) или слева. Вроде так. Или нет? Нет. Причем настолько "нет", что даже прокомментировать трудно. На vhdl пытаюсь делать так (пов. множителя взяты от балды). Сигналы с буквой t (например s_st2t_0) имеют 24 бита, без буквы (например s_st2_0) имеют 12 бит входные сигналы(например s_st1_0) все 12 бит -- первый этап FFT8 (прореживание по времени) .... Можно-ли так считать? Или есть другой путь? Это совсем не похоже на бабочку. Возьмите, для примера бабочку из ветки обсуждения БПФ автора ZED (http://electronix.ru/forum/index.php?showtopic=58026). По поводу поворачивающих множителей не врубился. Дело в том, что у меня выборки разделены на косинусную и синусную (идут через 90 градусов). Думаю, что комплексным числом будет то, что получится за две выборки. А значит для первой выборки поворачивающий множитель будет cos, для второй sin. Или я все путаю с квадратурой? Если каждая выборка число комплексное то поворачивающий множитель нужно считать одинаково? Похоже, что Вы запутались с пространственной частотой. Из ваших пояснений я прихожу к выводу, больше правда интуитивному, что схема вашей системы примерно следующая: Датчики снимают профиль некой поверхности, данные каждого датчика фильтруются КИХ и выходы КИХ являются входами БПФ Если так, то непонятно что означает выборки идут через 90 градусов (синус и косинус) если не так, то тем более нужны пояснения по тракту обработки до БПФ. Пока, к сожалению, совершенно не понятно что у Вас поступает на вход БПФ. Давайте пройдемся по тракту обработки от самых датчиков. Что на выходе датчиков и как это "превращается" в синусную и косинусную выборки? Как построены фильтры КИХ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 6 сентября, 2013 Опубликовано 6 сентября, 2013 (изменено) · Жалоба Похоже, что Вы запутались с пространственной частотой. Из ваших пояснений я прихожу к выводу, больше правда интуитивному, что схема вашей системы примерно следующая: Датчики снимают профиль некой поверхности, данные каждого датчика фильтруются КИХ и выходы КИХ являются входами БПФ Если так, то непонятно что означает если не так, то тем более нужны пояснения по тракту обработки до БПФ. Пока, к сожалению, совершенно не понятно что у Вас поступает на вход БПФ. Давайте пройдемся по тракту обработки от самых датчиков. Что на выходе датчиков и как это "превращается" в синусную и косинусную выборки? Как построены фильтры КИХ? Большое спасибо. Структурная схема тракта именно такая, как на Вашей картинке. Сигнал с каждого датчика пропускается через КИХ. Центральная частота (во всяком случае на данный момент 90 кГц) Частота выборок 360 кГц с прореживанием на 5 (вернее + прореживание на 5). Отсюда и выходит, что выборки идут со сдвигом 90 градусов, даже учитывая прореживание на 5. А значит для дальнейшей обработки (например на БПФ) можно использовать по очереди косинусную и синусную выборки. Выборки производятся одновременно на всех датчиках. Пространственная частота на датчиках формируется только в случае наклона фронта волны. Появляется набег фаз от датчика к датчику. Вот эту частоту и должен обработать БПФ32. На одном из частотных выходов (зависит от угла наклона фронта волны) БПФ будет всплеск. Если фронт сигнала прямо на датчики (90 градусов) то набега фаз нет - пространственная часта (которой фактически нет) является постоянной величиной Примерно так. Это по поводу того кто кого опережает или с какой стороны наклон фронта волны Вот другая пространственная частота Всплеск уже на другом частотном выходе БПФ (реал) http://sepwww.stanford.edu/oldsep/hale/FftLab.html Здесь пространственная частота та же, но наклон фронта волны с другой стороны (косинусная и синусная выборки поменяли свою относительную фазу на 180 град) Изменено 6 сентября, 2013 пользователем Acvarif Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sefo 0 6 сентября, 2013 Опубликовано 6 сентября, 2013 · Жалоба Сигнал с каждого датчика пропускается через КИХ. Центральная частота (во всяком случае на данный момент 90 кГц) Частота выборок 360 кГц с прореживанием на 5 (вернее + прореживание на 5). Отсюда и выходит, что выборки идут со сдвигом 90 градусов, даже учитывая прореживание на 5. А значит для дальнейшей обработки (например на БПФ) можно использовать по очереди косинусную и синусную выборки. Если я правильно понимаю, то Ваше представление ситуации следующее. Изначально Вы берете 4 отсчета на период центральной частоты и из них "в работу" идет только каждый 5-ый отсчет. Поскольку до прореживания отсчеты отстоят друг от друга на 90 градусов, то Вы их делите на синусный и косинусный. Соответственно после прореживания на 5 из-за нечетности коэффициента прореживания у Вас получается чередование синусных и косинусных отсчетов. Т.е. из вашей логики следует, что если бы Вы прореживали бы на 4 или на 2, то Вы бы считали, что остается только один "тип" отсчетов - синусные, например. Правильно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
acvarif 0 6 сентября, 2013 Опубликовано 6 сентября, 2013 · Жалоба Если я правильно понимаю, то Ваше представление ситуации следующее. Изначально Вы берете 4 отсчета на период центральной частоты и из них "в работу" идет только каждый 5-ый отсчет. Поскольку до прореживания отсчеты отстоят друг от друга на 90 градусов, то Вы их делите на синусный и косинусный. Соответственно после прореживания на 5 из-за нечетности коэффициента прореживания у Вас получается чередование синусных и косинусных отсчетов. Т.е. из вашей логики следует, что если бы Вы прореживали бы на 4 или на 2, то Вы бы считали, что остается только один "тип" отсчетов - синусные, например. Правильно? Похоже, что так. Только в работу идут все отсчеты с 1_го по 5_й для сохранения энергетики. Просто результаты КИХ формируются на каждом пятом. Сейчас перечитываю (уже не в первый раз) тему FFT2048 участника ZED. С бабочкой Х2 разобрался. Мне она понадобится. Сейчас пытаюсь понять как посчитать и в каком виде забить в константы поворачивающие множители для fft8. Пока остался вопрос по поводу реал и мним частей БПФ. Вроде в моем случае, при наличии косинусных и синусных входных составляющих можно обойтись одним БПФ выполняя преобразование по очереди для каждой входной составляющей. Или я не прав? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться