Jump to content

    

Halfback

Участник
  • Content Count

    378
  • Joined

  • Last visited

Posts posted by Halfback


  1. 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

     

     

     

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

    Реализовал полифазный децимирующий фильтр на 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

     

     

     

  3. разобрался, то что LVDS имеет только 5578ТС104 и 5578ТС064.

    ВОпрос к счастливым обладателям 5578ТС104 - возможна ли работа LVDS на прием на скорости 120МГц ? ЧТо с регистрами LVDS приемника? Будет всё работать как в Cyclone III ?

  4. Всем доброго дня. Скажите пожалуйста, плис 5578ТС084 имеет LVDS ?

    И еще вопрос в догонку - где можно взять документацию на 5578ТС084 ? Надо платку под эту плис спроектировать...

  5. 5 минут назад, one_eight_seven сказал:

    Это не делают в тестбенче. Откуда такие требования?

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

  6. есть еще мелкие вопросики по modelsim. 

    Есть файлик с модулем mod.v и его соотв. тесбенч mod_tb.v

    Что нужно написать в mod_tb.v чтобы

    1.График сразу стал ZoomFull

    2.Определенные регистры, обьявленные как беззнаковые, показывались как Decimal а не Bin (почему -то так по умолчанию).

  7. Господа, спасибо за помощь!!!

    Считываю файлы вот так. Проверено, работает.

    Скрытый текст
    
    	fileI  = $fopen("../../dI.txt","r");
    	fileQ  = $fopen("../../dQ.txt","r");
    
    	i=0;
    	while (! $feof(fileI)) begin
    		$fscanf(fileI,"%d,",I_value[i]);			
    		i=i+1;
    		end
    	$display("read %d I values form file",i-1);
    	i=0;
    	while (! $feof(fileQ)) begin
    		$fscanf(fileQ,"%d,",Q_value[i]);			
    		i=i+1;
    		end
    	$display("read %d Q values form file",i-1);	
    
    	$fclose(fileI);
    	$fclose(fileQ);
    	
    	for(i=0;i<=7;i=i+1) 	$display("%d %d",I_value[i],Q_value[i]); //проверка 

     

     

  8. 22 минуты назад, one_eight_seven сказал:

    Вариант 1 - считать из файла.

    варантов я так понял два,  $readmemh и $readmemb

    Первому значения в HEX надо скормить, второму в бинари

    А есть вариант считать и запихать в массив типа вот такого текстового файла? Просто переделывать 16800 точек  в другую запись не очень хочется.

    -2,-1,13,23,16,12,7,0,8,1,-18,-16,-11,-10,-3,6
  9. 9 минут назад, one_eight_seven сказал:

    Там же английским по белому написано: у вас integer там, где ожидается точка с запятой (;).  Смотрите на самый конец предыдущей строки.

    да, дейтсвительно, пятница....

    Тогда вопрос сразу - моделсим начал орать что неправильно декларировал массивы I_value Q_value. А как правильно?

    И еще вопрос - функция чтения массива из файла, допустим, вот такя $readmemb("dI.txt", I_value);

    по какому пути будет этот файл искать?

    Сунул dI.txt туда же где и файл тесбенча -ан нет, пишет

    * Warning: (vsim-7) Failed to open readmem file "dI.txt" in read mode.
    # 
    # No such file or directory. (errno = ENOENT)

     

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

    Столкнулся с непонятно проблемой

    Ругается на строку integer i;

    Пишет вот что

    Error .... near "integer": syntax error, unexpected integer, expecting ';' or ','
    Error .... (vlog-2730) Undefined variable: 'i'.

    Почему - мне не понятно. Буду благодарен за пояснения

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

     

    
    `timescale 1ns / 1ps
    
    module blablabla_tb;
    
    reg CLK_IN;
    reg signed [15:0] D_IN;
    reg signed [15:0] IN_I;
    reg signed [15:0] IN_Q;
    
    wire CLK_OUT;
    wire signed [15:0] D_OUT; 
    wire signed [15+2:0] DEB0;
    wire signed [15+2:0] DEB1;
    wire signed [15:0] DEB2;
    wire signed [15:0] DEB3;
    
    	
    blablabla u2(
    	.clkL(CLK_IN),	
    	.clkH(D_IN),
    	.inI(IN_I),
    	.inQ(IN_Q),
    	.outdata(D_OUT),
    	.outclk(CLK_OUT),
    	.deb0(),
    	.deb1(),
    	.deb2(),
    	.deb3()
    	);	
    
    always 
      begin
          CLK_IN = 0;
          #5;
          CLK_IN = 1;
          #5;
      end	
    
    reg signed [15:0] I_value[64-1:0] ={-2,-1,13,23,16,12,7,0,8,1,-18,-16,-11,-10,-3,6,
    												10,0,-9,7,24,16,-5,-15,-2,6,-5,1,16,9,-14,-29,
    												-21,-4,2,-1,2,0,-10,-5,2,-7,-14,-24,-26,-5,8,11,
    												14,10,-5,-11,1,-7,-20,-3,7,-3,-2,0,-8,2,19,6};
    reg signed [15:0] Q_value[64-1:0] ={-1,0,2,1,-3,0,6,3,-9,-20,-15,3,12,1,-4,6,
    												10,8,-9,-24,0,22,0,-21,-18,-32,-26,7,2,-7,3,-1,
    												-3,-2,-16,-14,8,10,-13,-14,16,22,1,-7,3,1,-18,-24,
    												-25,-38,-18,11,12,24,32,9,-22,-36,-33,-17,0,-3,-14,-12
    												}
    
    integer i;
      
    initial 
    	begin
    	$display("simulate start");  
    
    	for(i = 0; i < 64; i = i + 1)
    			begin
    			IN_I <= I_value [i];
    			IN_Q <= Q_value[i];
    			@(negedge CLK_IN);
    			end	
    	$stop;
    	$finish;
    	end 
     
    endmodule

     

     

     

  11. 52 минуты назад, sonycman сказал:

    Так этот код:

    
    outdata_reg <= ((indata + (32'd1<<31)) >> 16) - (16'd1<<15);

    для входного значения - 1 даст на выходе ту же - 1, а не 0.

    Это будет не indata/65536.

     Да, Вы правы.

    чтобы был "0" надо прибавить "1".

    outdata_reg <= ((indata + (32'd1<<31)) >> 16) - (16'd1<<15)+1;

     

  12. 45 минут назад, dimka76 сказал:

    Раз так, то почему нельзя просто записать ?

    
    outdata_reg[15:0] <= indata[31:16];

     

    на все отрицательные числа от -1 до -65355 результат будет "-1" а д.б. "0".

    кому это не критично - скорее всего так и делают.

  13. Всем доброго дня.

    Надо по сути 32-разрядное знаковое число сократить до 16-разрядного знакового.

    по сути это будет 

    outdata_reg <= indata/65536; 

    но поскольку на младших циклонах знак деления штука не экономная то написал так:
     

    module conv_sign_32to16 (
    	input clk, 
    	input signed   [31:0] indata,
    	output signed  [15:0] outdata
    	);
    	
    	reg [15:0] outdata_reg;
    	
    	always @ (posedge clk)
    		begin
    		outdata_reg <= ((indata + (32'd1<<31)) >> 16) - (16'd1<<15); 
    		end //always
    
    	assign outdata = outdata_reg;
    		
    endmodule

    может есть способ элегантнее? Заранее спасибо.

  14. 18 часов назад, Strob сказал:

    Полифазный децимирующий фильтр так реализуется.

    не могу понять следующее. Если я в настройках мегафункции выставляю что это дециматор на 12 то правильно ли я понимаю что никакой НЧ-фильтрации в соответствии с моими коэффициентами присходить не будет?

    Т.е. если я хочу правильно произвести децимацию сигнала то сначала надо поставить компонент с мегафункцией ФНЧ на часоту среза в два раза меньшей частоты децимации (в моем случает частота среза будет в 24 раза меньше часты семплирования), а затем ставить компонент мегафункции дециматора с  коэффициентом децимации = 12 ?

  15. есть еще вопрос по мегафункции DSP FIR Compiler II v13

    делаю ФНЧ, коэффициентов в матлабе получаю около сотни и загружаю их через текстовый  файл в модуль мегафункции. Генерирую - вроде работает, кушает много умножителей и вентилей. Как только выставляю понадобившуюся децимацию, скажем R=12 то кол-во умножителей сокращается раза в 3, вентилей также. Вопросов два -

    1. Почему включение децимации резко сокращает необходимое кол-во ресурсов и как пользоваться децимацией? В чём подвох?

    2. При включенной децимации в какой момент считывать данные? Я обратил внимание что относительно тактирования входа каждый 12-й импульс на выходе ast_source_valid возникает импульс.

  16. Прошу помоши в создании файла SDC

    Читал-перечитывал TimeQuest для чайников но всё равно не могу догнать вроде как простых вещей.

    В проекте есть блок, который из входной частоты 120МГц делает другую частоту 20Мгц. Блок описан на Verilog, там по сути деление частоты на 6.

    Далее 20МГц расходиться на несколько других блоков. 

    ВОпрос  - как правильно описать эти 20МГЦ в sdc? Вот такую запись не воспринимает и пишет ошибку:

    create_clock -name "clkD" -period 20MHz -source [get_registers {clkconv:inst50|clkout}] 

     

  17. Nick_K

    трудно поспорить с перечисленными Вами пунктами. Пока мне не очень понятно насколько корректно будет работать описание внутри posegde и negedge если их засунуть в один posegde. Надо проверять, т.к. вычисление должно происходить за один такт. Я с плисиной и verilog еще сравнительно мало работаю.

  18. 3 минуты назад, AVR сказал:

    Неужели таким способом частота 120 МГц была достижима?

    окно на 16 при таком способе худо-бедно но работает, на 32 окно пробовал - не работает.

    3 часа назад, andrew_b сказал:

    Не надо использовать задний фронт.

    почему?

  19. Оптимизировал. Проверил, работает вроде также.

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

    module MovAverageFilter
    #(
        parameter FIFO_LEN_LOG = 4//,
    )
    (
        input  clk,
        input  [15:0] datain,
        output [15:0] dataout//,
    );
        localparam FIFO_LEN = (1 << FIFO_LEN_LOG);
        
        reg [15:0] FIFO [0:FIFO_LEN-1];
         reg [FIFO_LEN_LOG+15:0] fifo_sum = 0;
        integer i;
         
         reg [FIFO_LEN_LOG-1:0] k = 0;

        initial
        begin
            for(i = FIFO_LEN-1; i >= 0; i=i-1)  FIFO = 16'd0;
        end

        
         always @(posedge clk)
            begin        
            fifo_sum <= fifo_sum + datain - FIFO[k];        
            end
            
        always @(negedge clk)
            begin        
            FIFO[k] <= datain;
            k<=k+1;        
            end
        
        assign dataout = fifo_sum >> FIFO_LEN_LOG;
        
    endmodule

     

    P.S. Бегающий указатель "к" специально не обнуляю, в железе это само собой происходит, т.е. переполнения нет.

  20. stealthisname

    спасибо большое!!!

    есть еще идея оптимизировать в части 

    for(i = FIFO_LEN-1; i > 0; i=i-1)
            begin
                FIFO[i] <= FIFO[i-1];
            end

    Идея в том чтобы этого не делать сдвиг массива а организовать кольцевой буфер как посоветовал Eddy_Em

  21. 12 часов назад, RobFPGA сказал:

    Для  скользящего  среднего при котором отсчеты приходят по одному  достаточно  одного сложения и одного вычитания  для окна любой длинны. :yes3:

    Наверное я правильно понял что вот это

    dataout <= (FIFO[0]+FIFO[1]+FIFO[2]+FIFO[3]+FIFO[4]+FIFO[5]+FIFO[6]+FIFO[7]+FIFO[8]+FIFO[9]+FIFO[10]+FIFO[11]+FIFO[12]+FIFO[13]+FIFO[14]+FIFO[15])>>4;

    надо заменить на вот это

    dataout <= (dataout + FIFO[0]-FIFO[15])>>4;

    Другой вопрос что в Си-подобном языке dataout справа в скобках будет расценено как предыдущее значение а слева - как текущее значение. Так ли это будет в верилоге? (Я всё равно в железе проверю)

  22. Доброго времени суток!

    Нужна помощь в оптимизации кода на Verilog, среда разработки Quartus II 13.0.1 , плисина Циклон 3.

    Вход/выход 16-битный, клок 120МГц

    Размер окна фильтра на 16 точек

     

    module MovAverageFilter(clk,datain,dataout);
    
    input  clk;
    input  [15:0] datain;
    output reg [15:0] dataout;
    
    
    reg [15:0] FIFO [0:15];
    integer i;
    
    initial begin
    	for(i = 15; i >= 0; i=i-1) FIFO[i] = 16'd0;
    	end
    
    
    always@(posedge clk) begin
    
    	dataout <= (FIFO[0]+FIFO[1]+FIFO[2]+FIFO[3]+FIFO[4]+FIFO[5]+FIFO[6]+FIFO[7]+FIFO[8]+FIFO[9]+ 		FIFO[10]+FIFO[11]+FIFO[12]+FIFO[13]+FIFO[14]+FIFO[15])>>4;	
    
    	end
    
    	
    always@(negedge clk) begin
          
    	for(i = 15; i > 0; i=i-1) FIFO[i] <= FIFO[i-1]; 	
    	FIFO[0] <= datain;	
    	end
    
    endmodule

     

    Есть желание увеличить размер окна с 16 до 32 или даже до 64 но тогда нужно будет больше сумматоров и я беспокоюсь за обеспечение синхронности схемы. Может есть более изящный вариант брать сумму точек в окне и делить на их кол-во?