Jump to content

    
Sign in to follow this  
Halfback

Реализация на Verilog полифазного фильтра, борьба со слэками

Recommended Posts

Всем доброго времени суток!

Реализовал полифазный децимирующий фильтр на 70 точек (на выходе каждая 10-я точка относительно входа), в моделсиме показывает всё как надо, в железе на столе тоже работает, но квартус валит слэки по Setup (Slow 1200mV 0C и +85С, по Fast - слэков нет). 

Причем в sdc когда ставлю 80МГц - слэков нет, на 100МГц еже есть.

Буду очень признателен если поможете найти плохое место в коде. Может есть возможность что-то поправить/улучшить?

Скрытый текст

 


module PoliPhaseFilter_70
(
    input  clk,
    input  signed [15:0] datain,
	 input nreset,
	 output signed [15:0] dataout,
	 output clkDec // выходной клок синхр. данных
);
	 
localparam BANK_NUM = 10;
localparam VALUE_NUM = 7;	 

//регистры с входными данные
reg signed [15:0] BANK_D0[BANK_NUM-1:0];
reg signed [15:0] BANK_D1[BANK_NUM-1:0];
reg signed [15:0] BANK_D2[BANK_NUM-1:0];
reg signed [15:0] BANK_D3[BANK_NUM-1:0];
reg signed [15:0] BANK_D4[BANK_NUM-1:0];
reg signed [15:0] BANK_D5[BANK_NUM-1:0];
reg signed [15:0] BANK_D6[BANK_NUM-1:0];

reg signed [15:0] BANK_C [BANK_NUM-1:0][VALUE_NUM-1:0]; //коэффициенты полифазного фильтра

reg signed [31+3+4:0] RESSUMM = 0; // промежуточная сумма
reg signed [31+3+4:0] RESSUMM_out = 0; // итоговая сумма -> на выход фильтра

reg rclkDec = 0;

integer i;

reg [3:0] step=0; // 10 шагов

//результаты перемножений значений данных на коэфф фильтра
wire signed [15:0] mult0_1, mult0_2, mult1_1, mult1_2, mult2_1, mult2_2, mult3_1, mult3_2, mult4_1,mult4_2,mult5_1,mult5_2,mult6_1,mult6_2;
//сумма результатов перемножений
wire signed [31+3:0] resmult1;

assign resmult1 = mult0_1*mult0_2 + mult1_1*mult1_2 + mult2_1*mult2_2 + mult3_1*mult3_2 + mult4_1*mult4_2 + mult5_1*mult5_2 + mult6_1*mult6_2;

initial
   begin //обнуление всех регистров, формирование коэффициентов
	for(i = 0; i < BANK_NUM; i=i+1)  begin
		BANK_D0[i]<=0; BANK_D1[i]<=0; BANK_D2[i]<=0; BANK_D3[i]<=0; BANK_D4[i]<=0; BANK_D5[i]<=0; BANK_D6[i]<=0; 
		end
	RESSUMM <= 0;
	RESSUMM_out <= 0;
	
	BANK_C[0][0]= -16'd293; BANK_C[0][1]= -16'd1513;BANK_C[0][2] = 16'd3442; BANK_C[0][3] = 16'd16735;BANK_C[0][4] = 16'd15664;BANK_C[0][5] = 16'd2358; BANK_C[0][6] = -16'd1445;
	BANK_C[1][0]= -16'd278; BANK_C[1][1]= -16'd1518;BANK_C[1][2] = 16'd4646; BANK_C[1][3] = 16'd17631;BANK_C[1][4] = 16'd14446;BANK_C[1][5] = 16'd1407; BANK_C[1][6] = -16'd1331;
	BANK_C[2][0]= -16'd396; BANK_C[2][1]= -16'd1446;BANK_C[2][2] = 16'd5952; BANK_C[2][3] = 16'd18326;BANK_C[2][4] = 16'd13114;BANK_C[2][5] = 16'd596;  BANK_C[2][6] = -16'd1185;
	BANK_C[3][0]= -16'd534; BANK_C[3][1]= -16'd1279;BANK_C[3][2] = 16'd7340; BANK_C[3][3] = 16'd18800;BANK_C[3][4] = 16'd11702;BANK_C[3][5] = -16'd74;  BANK_C[3][6] = -16'd1022;	
	BANK_C[4][0]= -16'd688; BANK_C[4][1]= -16'd1003;BANK_C[4][2] = 16'd8781; BANK_C[4][3] = 16'd19041;BANK_C[4][4] = 16'd10247;BANK_C[4][5] = -16'd604; BANK_C[4][6] = -16'd854;	
	BANK_C[5][0]= -16'd854; BANK_C[5][1]= -16'd604; BANK_C[5][2] = 16'd10247;BANK_C[5][3] = 16'd19041;BANK_C[5][4] = 16'd8781; BANK_C[5][5] = -16'd1003;BANK_C[5][6] = -16'd688;	
	BANK_C[6][0]= -16'd1022;BANK_C[6][1]= -16'd74;  BANK_C[6][2] = 16'd11702;BANK_C[6][3] = 16'd18800;BANK_C[6][4] = 16'd7340; BANK_C[6][5] = -16'd1279;BANK_C[6][6] = -16'd534;	
	BANK_C[7][0]= -16'd1185;BANK_C[7][1]= 16'd596;  BANK_C[7][2] = 16'd13114;BANK_C[7][3] = 16'd18326;BANK_C[7][4] = 16'd5952; BANK_C[7][5] = -16'd1446;BANK_C[7][6] = -16'd396;
	BANK_C[8][0]= -16'd1331;BANK_C[8][1]= 16'd1407; BANK_C[8][2] = 16'd14446;BANK_C[8][3] = 16'd17631;BANK_C[8][4] = 16'd4646; BANK_C[8][5] = -16'd1518;BANK_C[8][6] = -16'd278;	
	BANK_C[9][0]= -16'd1445;BANK_C[9][1]= 16'd2358; BANK_C[9][2] = 16'd15664;BANK_C[9][3] = 16'd16735;BANK_C[9][4] = 16'd3442; BANK_C[9][5] = -16'd1513;BANK_C[9][6] = -16'd293;		 
   end //initial
	
always @ (posedge clk)
	begin
	if(nreset==1'b0) begin
		RESSUMM <= 0;
		RESSUMM_out <= 0;
		step <= 0;
		for(i = 0; i < BANK_NUM; i=i+1)  
			begin
			BANK_D0[i]<=0; BANK_D1[i]<=0; BANK_D2[i]<=0; BANK_D3[i]<=0; BANK_D4[i]<=0; BANK_D5[i]<=0; BANK_D6[i]<=0;
			end
		end
	else begin
		//формирование строба для чтения выходного регистра
        if(step==0) rclkDec <= 1;
		if(step==5) rclkDec <= 0; 

		BANK_D0[step] <= datain; //
       
        // сдвигаем данные
		BANK_D6[step]<=BANK_D5[step];BANK_D5[step]<=BANK_D4[step];BANK_D4[step]<=BANK_D3[step];
		BANK_D3[step]<=BANK_D2[step];BANK_D2[step]<=BANK_D1[step];BANK_D1[step]<=BANK_D0[step];
		
		case (step)
			0,1,2,3,4,5,6,7,8: begin
				step <= step + 4'd1;	
				RESSUMM <= RESSUMM + resmult1;
				end
			9: begin
				step <= 4'd0;
				RESSUMM_out <= RESSUMM + resmult1;// формируем выход
				RESSUMM <= 0;
				end
		endcase
		end //else if
	end //always
	
assign clkDec = rclkDec;
	
assign mult0_1 = BANK_D0[step];	
assign mult0_2 = BANK_C[step][6];
assign mult1_1 = BANK_D1[step];	
assign mult1_2 = BANK_C[step][5];
assign mult2_1 = BANK_D2[step];
assign mult2_2 = BANK_C[step][4];
assign mult3_1 = BANK_D3[step];
assign mult3_2 = BANK_C[step][3];
assign mult4_1 = BANK_D4[step];
assign mult4_2 = BANK_C[step][2];
assign mult5_1 = BANK_D5[step];
assign mult5_2 = BANK_C[step][1];
assign mult6_1 = BANK_D6[step];
assign mult6_2 = BANK_C[step][0];
	
assign 	dataout = RESSUMM_out[33:18]; // обрезаем выходной регистр сверху и снизу для получения нужных 16 бит

endmodule

 

 

 

Edited by Halfback

Share this post


Link to post
Share on other sites
assign resmult1 = mult0_1*mult0_2 + mult1_1*mult1_2 + mult2_1*mult2_2 + mult3_1*mult3_2 + mult4_1*mult4_2 + mult5_1*mult5_2 + mult6_1*mult6_2;
assign mult0_1 = BANK_D0[step]

как минимум после этого, удивительно что это еще на 80МГц работает

ЗЫ. Скачайте учебник по ЦОС от альтеры, там в разделе фильтров много крайне полезной информации

43 minutes ago, Halfback said:

Может есть возможность что-то поправить/улучшить?

что-то мне подсказывает что BANK_D у вас будет реализован на регистрах, если с памятью проблем нет, то я бы переделал все на блочную память)

Share this post


Link to post
Share on other sites
11.11.2021 в 09:55, des00 сказал:

ЗЫ. Скачайте учебник по ЦОС от альтеры, там в разделе фильтров много крайне полезной информации

Не поделитесь ссылкой или как в гугле поискать? Пока в поисковике вижу только Altera DSP Builder, но как я понимаю это не то что мне нужно...

  

10 часов назад, Maverick_ сказал:

обратите внимание еще на

обратил. У меня для Cyclone III (Quartus 13.0.1) нет такого примера, но есть вот такой темплейт  для  DSP Features/Sum of Four Multipliers  (Stratix V, Arria-V, Cyclone-V and later device families)

Мне не совсем понятно чем эта реализация отличается от моей. Если разница есть то ткните пожалуйста.

Скрытый текст

// Quartus II Verilog Template
// Sum of four multipliers
// For use with the Stratix V, Arria-V, Cyclone-V and later device families

module sum_of_4(a1, b1, a2, b2, a3, b3, a4, b4, p);
//This template is applicable to sum-of-4 18x18 mode on Stratix-V
parameter a_width = 18;
parameter b_width = 18;
input	[a_width-1:0] a1;
input	[b_width-1:0] b1;
input	[a_width-1:0] a2;
input	[b_width-1:0] b2;
input	[a_width-1:0] a3;
input	[b_width-1:0] b3;
input	[a_width-1:0] a4;
input	[b_width-1:0] b4;
output	[a_width+b_width+1:0] p;

wire signed	[a_width-1:0] a1;
wire signed	[b_width-1:0] b1;
wire signed	[a_width-1:0] a2;
wire signed	[b_width-1:0] b2;
wire signed	[a_width-1:0] a3;
wire signed	[b_width-1:0] b3;
wire signed	[a_width-1:0] a4;
wire signed	[b_width-1:0] b4;
wire signed	[a_width+b_width+1:0] p;

//Static add/sub is supported
assign p = a1 * b1 + a2 * b2 - a3 * b3 + a4 * b4;

endmodule

 

 

 есть еще вот такой темплейт Sums of Multipliers (я так понял для плис помедленнее). Я таким образом тоже реализовывал - умножение с суммированием в виде отдельного модуля, где то-же самое делалось по клоку.  Но ситуация со слеками никак не изменилась. Еще непонятно - целенаправлено ли  скобки т.о. расставлены или нет.

Скрытый текст

 


// Quartus II Verilog Template
// Sum of four multipliers

module sum_of_four_multipliers
#(parameter WIDTH=18)
(
	input clk, ena,
	input [WIDTH-1:0] dataa, datab, datac, datad,
	input [WIDTH-1:0] datae, dataf, datag, datah,
	output reg [2*WIDTH+1:0] dataout
);

	always @ (posedge clk)
	begin
		if (ena == 1)
		begin
			dataout <= (dataa * datab + datac * datad) + (datae * dataf + datag * datah);
		end
	end
endmodule

 

 

 

Edited by Halfback

Share this post


Link to post
Share on other sites
1 hour ago, Halfback said:

Не поделитесь ссылкой или как в гугле поискать? Пока в поисковике вижу только Altera DSP Builder, но как я понимаю это не то что мне нужно...

https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/manual/stx_cookbook.pdf

1 hour ago, Halfback said:

обратил. У меня для Cyclone III (Quartus 13.0.1) нет такого примера, но есть вот такой темплейт  для  DSP Features/Sum of Four Multipliers  (Stratix V, Arria-V, Cyclone-V and later device families)

Мне не совсем понятно чем эта реализация отличается от моей. Если разница есть то ткните пожалуйста.

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

cyclone3mult.png

57 minutes ago, blackfin said:

Adder Trees, page 17: Advanced Synthesis Cookbook

это как раз сорцы к доке)

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