Перейти к содержанию
    

FFT8 синтезируемый VHDL код

Стоит задачка написать код (VHDL) для FFT32 (прореживание по времени). Поскольку структура построения такого модуля мне пока до конца не понята, то пытаюсь взять за основу структуру построения FFT8. В сети нашел пока только это http://vhdlguru.blogspot.com/2011/06/non-s...or-8-point.html. Толку с этого немного, поскольку код несинтезируемый. Но в общем понятно, что должно быть три этапа, каждый из которых это вычисление бабочки и запись результатов на место предыдущего вычисления. Для этого понадобится ram, собственно модуль бабочки, миксер для перестановки адресов при очередной записи результатов в ram и небольшая схема управления.

Для моей задачи не обязательно иметь на входе разделенный сигнал на реал и мним, поскольку выборки поступают через 90 градусов. Тоесть можно по очереди выполнять FFT сначала для реал потом для мним. На выходе после двух преобразований сложить квадраты и взять корень. Это должно дать экономию в ресурсах. В связи с этим вопросы

1. Можно-ли как-то на VHDL выполнить операцию взятия квадратного корня? Или все-же проще, как везде принято, иметь FFT который работает с реал и мним?

2. Нет-ли у кого, для примера, синтезируемого кода FFT8?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот здесь http://opencores.org/project,pipelined_fft_64 есть синтезируемый проект с описанием. В т.ч. и модуль

FFT8.

А там же рядом есть такой же проект с FFT32.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот здесь http://opencores.org/project,pipelined_fft_64 есть синтезируемый проект с описанием. В т.ч. и модуль

FFT8.

А там же рядом есть такой же проект с FFT32.

Спасибо.

Сразу не обратил внимание, что fft64 сделан на базе fft8 (прорежен по времени).

FFT32 не нашел...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот здесь кое-что есть. Это работает. Но описания нет. http://ds-dev.ru/projects/fpi-dsp

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот здесь кое-что есть. Это работает. Но описания нет. 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 это и есть результат.

Изменено пользователем Acvarif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 мним. А в коде этого не нахожу.

Изменено пользователем Acvarif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо.

Зарегистрировался. Если по ссылке то файлов там нет.

 

 

 

 

Доступ к файлам через Subversion: http://svn.1gb.ru/ds-dev-fpi

 

 

login: guest

 

password: guest

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Доступ к файлам через 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 входов?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И все же по поводу кода fft8. Судя по коду данные поступают последовательно по каждому клоку. Все поступает на сдвиговый регистр (регистровый файл). Выполнение алгоритма начинается по достижению счетчиком 5 и выше. Почему 5? Почему не загружаются все 8 данных? Не понятно. Почему данные не загружаются параллельно на все 8 + 8 входов?

Вобщем понятно. Этот код не подходит.

В моем случае нужна параллельная загрузка хотя-бы 8_ми выборок. Потом можно делать БПФ8 обычным способом (прореживание по времени).

Возник вопрос как делать БПФ. С двумя входами (реал, имаг) или с одним входом. С одним нужно по очереди подавать на него cos и sin выборки, а на выходе после двух преобразований просуммировать квадраты и взять квадратный корень. Вопрос в том как на ПЛИС взять квадратный корень?

Если делать БПФ с двумя входами, то не понимаю как для них считать поворачивающие множители. Например для БПФ8 который считает cos_нусную выборку как посчитать поворачивающий множитель W8**2? Просто взять cos 2пи*3/8? Для синусной выборки W8**2 будет sin 2пи*3/8 Получается что для БПФ реал и БПФ имаг будут свои разные поворачивающие множители?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопрос в том как на ПЛИС взять квадратный корень?

 

Квадрантый корень функция монотонная, поэтому стоит задуматься а нужно ли его вообще брать - качественный анализ и сравнение можно сделать и по сумме квадратов. Иногда вычисление квадратного корня оставляют процу - т.е. ПЛИС выдает суммы квадратов, а проц досчитывает корни.

 

Если делать БПФ с двумя входами, то не понимаю как для них считать поворачивающие множители. Например для БПФ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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поворачивающий множитель один, так же как и выборка одна - просто это комплексные числа, состоящие из вещественной ("косинусной") и мнимой ("синусной") частей. Поворачивающий множитель 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);

Можно-ли так считать? Или есть другой путь?

Изменено пользователем Acvarif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо. Я так и думал по поводу квадратного корня. Но в моем случае мне придется после БПФ искать максимум максиморум из 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. Или я все путаю с квадратурой? Если каждая выборка число комплексное то поворачивающий множитель нужно считать одинаково?

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

post-7537-1378455859_thumb.jpg

Датчики снимают профиль некой поверхности, данные каждого датчика фильтруются КИХ и выходы КИХ являются входами БПФ

 

Если так, то непонятно что означает

выборки идут через 90 градусов (синус и косинус)

если не так, то тем более нужны пояснения по тракту обработки до БПФ.

 

Пока, к сожалению, совершенно не понятно что у Вас поступает на вход БПФ.

 

Давайте пройдемся по тракту обработки от самых датчиков. Что на выходе датчиков и как это "превращается" в синусную и косинусную выборки? Как построены фильтры КИХ?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

post-7537-1378455859_thumb.jpg

Датчики снимают профиль некой поверхности, данные каждого датчика фильтруются КИХ и выходы КИХ являются входами БПФ

 

Если так, то непонятно что означает

 

если не так, то тем более нужны пояснения по тракту обработки до БПФ.

 

Пока, к сожалению, совершенно не понятно что у Вас поступает на вход БПФ.

 

Давайте пройдемся по тракту обработки от самых датчиков. Что на выходе датчиков и как это "превращается" в синусную и косинусную выборки? Как построены фильтры КИХ?

Большое спасибо. Структурная схема тракта именно такая, как на Вашей картинке.

Сигнал с каждого датчика пропускается через КИХ. Центральная частота (во всяком случае на данный момент 90 кГц) Частота выборок 360 кГц с прореживанием на 5 (вернее + прореживание на 5). Отсюда и выходит, что выборки идут со сдвигом 90 градусов, даже учитывая прореживание на 5. А значит для дальнейшей обработки (например на БПФ) можно использовать по очереди косинусную и синусную выборки. Выборки производятся одновременно на всех датчиках.

Пространственная частота на датчиках формируется только в случае наклона фронта волны. Появляется набег фаз от датчика к датчику. Вот эту частоту и должен обработать БПФ32. На одном из частотных выходов (зависит от угла наклона фронта волны) БПФ будет всплеск. Если фронт сигнала прямо на датчики (90 градусов) то набега фаз нет - пространственная часта (которой фактически нет) является постоянной величиной

Примерно так.post-39850-1378463365_thumb.jpg

Это по поводу того кто кого опережает или с какой стороны наклон фронта волны post-39850-1378464060_thumb.jpgpost-39850-1378464068_thumb.jpg

Вот другая пространственная частота post-39850-1378464882_thumb.jpg Всплеск уже на другом частотном выходе БПФ (реал)

http://sepwww.stanford.edu/oldsep/hale/FftLab.html

Здесь пространственная частота та же, но наклон фронта волны с другой стороны (косинусная и синусная выборки поменяли свою относительную фазу на 180 град) post-39850-1378465376_thumb.jpg

Изменено пользователем Acvarif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сигнал с каждого датчика пропускается через КИХ. Центральная частота (во всяком случае на данный момент 90 кГц) Частота выборок 360 кГц с прореживанием на 5 (вернее + прореживание на 5). Отсюда и выходит, что выборки идут со сдвигом 90 градусов, даже учитывая прореживание на 5. А значит для дальнейшей обработки (например на БПФ) можно использовать по очереди косинусную и синусную выборки.

 

Если я правильно понимаю, то Ваше представление ситуации следующее. Изначально Вы берете 4 отсчета на период центральной частоты и из них "в работу" идет только каждый 5-ый отсчет. Поскольку до прореживания отсчеты отстоят друг от друга на 90 градусов, то Вы их делите на синусный и косинусный. Соответственно после прореживания на 5 из-за нечетности коэффициента прореживания у Вас получается чередование синусных и косинусных отсчетов.

 

Т.е. из вашей логики следует, что если бы Вы прореживали бы на 4 или на 2, то Вы бы считали, что остается только один "тип" отсчетов - синусные, например.

 

Правильно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если я правильно понимаю, то Ваше представление ситуации следующее. Изначально Вы берете 4 отсчета на период центральной частоты и из них "в работу" идет только каждый 5-ый отсчет. Поскольку до прореживания отсчеты отстоят друг от друга на 90 градусов, то Вы их делите на синусный и косинусный. Соответственно после прореживания на 5 из-за нечетности коэффициента прореживания у Вас получается чередование синусных и косинусных отсчетов.

 

Т.е. из вашей логики следует, что если бы Вы прореживали бы на 4 или на 2, то Вы бы считали, что остается только один "тип" отсчетов - синусные, например.

 

Правильно?

Похоже, что так. Только в работу идут все отсчеты с 1_го по 5_й для сохранения энергетики. Просто результаты КИХ формируются на каждом пятом.

Сейчас перечитываю (уже не в первый раз) тему FFT2048 участника ZED.

С бабочкой Х2 разобрался. Мне она понадобится. Сейчас пытаюсь понять как посчитать и в каком виде забить в константы поворачивающие множители для fft8.

Пока остался вопрос по поводу реал и мним частей БПФ. Вроде в моем случае, при наличии косинусных и синусных входных составляющих можно обойтись одним БПФ выполняя преобразование по очереди для каждой входной составляющей. Или я не прав?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...