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

Скользящее среднее

На входе - сигнал с постоянной состовляющей.

Необходимо получить усредненное значение сигнала (постоянную составляющую). 

Потеря точности НЕ допускается.

Частота дискретизации 30МГц. Период сигнала - от 1Гц до 200КГц

Как экономичнее на verilog реализовать фильтр скользящего среднего ?

Усредняем за время более периода младшей гармоники ?

`include "timescale.v"
/*===========================================================*/
module mean_filter(
    input               clk_i, /* 30.72MHz */
    input               rst_i,  
    input        [23:0] dat_i,   
    input               srst_i,       
    input               valid_i,
    output signed [23:0] dat_o,   
    output reg          valid_o        
    );
/*===========================================================*/    
reg         [14:0] addr_wr, addr_rd;
reg signed  [38:0] S;
reg                wr;    
wire signed [23:0] dat_m;
reg  signed [23:0] dat_average; 
/*===========================================================*/
assign dat_o= dat_average;
mem_24x65536 mem (.clk(clk_i), .a(addr_wr), .d(dat_i), .dpra(addr_rd), .we(wr), .dpo(dat_m));
/*===========================================================*/
always @(posedge clk_i or posedge rst_i)    
begin
if(rst_i)   
     {addr_wr, addr_rd, S, wr, dat_average, valid_o, decimate}<= 0;
else
    begin
    if(srst_i)
        {addr_wr, addr_rd, S, wr, dat_average, valid_o}<= 0;
    else
        begin
        if(&addr_wr)
            valid_o<= 1'b1;
        wr <= valid_i ;
        addr_rd<= addr_rd+ 1'b1;    
        if(valid_i)
            addr_wr<= addr_wr+ 1'b1;
        if(!addr_rd)
            begin
            S<= dat_m;
            dat_average<= S[38:15];
            end
        else
            S<= S + dat_m;   
        end   
    end
end         
/*===========================================================*/   
endmodule

 

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


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

36 minutes ago, gosha said:

Усредняем за время более периода младшей гармоники ?

у вас не скользящее среднее

37 minutes ago, gosha said:

Как экономичнее на verilog реализовать фильтр скользящего среднего ?

CIC фильтр, одно звено, реализция без преобразования частоты

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


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

Гость vitzap

Если задача позволяет, очень просто сделать экспоненциально взвешенное скользящее среднее. https://ru.wikipedia.org/wiki/Скользящая_средняя

Если a брать 1/2, 1/4, 1/8 и т.д.

 

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


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

35 minutes ago, des00 said:

у вас не скользящее среднее

CIC фильтр, одно звено, реализция без преобразования частоты

Спасибо !

А точность не потеряется ?

По Т.З. погрешность измерения дальности дальномером : 5 метров

Задача фильтра- усреднить разность фаз фазомера.

Нужен децимирующий фильтр на 30000. (30 МГц -> 1 KГц)

IP Xilinx не генерит CIC с дещимацией 30_000. Только децимирующий на 8192 максимум. Еще разрядность повышается: А тама арктангенс после фильтра.

Скользящее среднее не будет ли точнее ?

phi.png

tone_20KHz.slx

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


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

29 minutes ago, gosha said:

А точность не потеряется ?

По Т.З. погрешность измерения дальности дальномером : 5 метров

Задача фильтра- усреднить разность фаз фазомера.

Нужен децимирующий фильтр на 30000. (30 МГц -> 1 KГц)

IP Xilinx не генерит CIC с дещимацией 30_000. Только децимирующий на 8192 максимум. Еще разрядность повышается: А тама арктангенс после фильтра.

Скользящее среднее не будет ли точнее ?

вы хоть немного в ответ погрузитесь, до того как задавать вопросы и рисовать схемы в симулинке. по указанной выше ссылке в википедии, в разделе "Простое скользящее среднее, или арифметическое скользящее среднее" указана формула вот этого самого фильтра "CIC фильтр, одно звено, реализция без преобразования частоты". А децимировать можно на выходе. Но, если вам априори нужна децимация, то ваша реализация пойдет.

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


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

Автор! Вам нужно экспериментально найти подходящий метод усреднения, которых существует бесконечно много.

Отбрасывая измерения, повысить точность? Трудно поверить.

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


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

16.12.2020 в 08:12, gosha сказал:

Необходимо получить усредненное значение сигнала

Недавно решал подобную задачу. Сделал используя мегафункцию FIFO. Прибавляется текущее значение, которое пишется в память и вычитается самое старое значение, которое в этот момент вылезает из памяти.

16.12.2020 в 08:12, gosha сказал:

Усредняем за время более периода младшей гармоники ?

Периодов лучше взять побольше, хотя бы 10.

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


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

Спасибо !!

Хорошее решение.

Тогда уж кольцевой буфер на основе двухпортовой RAM:  в голову пишется, суммируется, хвост вычитается?

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


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

On 12/19/2020 at 8:36 PM, MrGalaxy said:

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

это и есть формула из википедии, по приведенной ссылке) раздел статьи: Простое скользящее среднее, или арифметическое скользящее среднее

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


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

12 часов назад, des00 сказал:

это и есть формула из википедии, по приведенной ссылке) раздел статьи: Простое скользящее среднее, или арифметическое скользящее среднее

Ради формулы простейшего интегрирования в скользящем окне в Википедию лазить... :mega_shok:  

Вопрос был про реализацию.

 

23 часа назад, gosha сказал:

Тогда уж кольцевой буфер на основе двухпортовой RAM:  в голову пишется, суммируется, хвост вычитается?

Я про это и написал. 

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


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

15 hours ago, MrGalaxy said:

Ради формулы простейшего интегрирования в скользящем окне в Википедию лазить... :mega_shok:  

Вопрос был про реализацию.

Ну это же не вам совет был, вы в этой теме гуру, а ТС изначально не был. Но прочитав все материалы по теме,  в том числе y(t) = y(t-1) - x(t-N) + x(t), ТС не узнал в описании вашего устройства вот эту простую формулу.

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


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

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity delay_line is
generic(
  W                 : integer := 8;    -- data width
  L                 : integer := 1200);  -- delay length, shall be > 3
port(
  i_clk             : in  std_logic;
  i_sync_reset      : in  std_logic;
  i_data            : in  std_logic_vector(W-1 downto 0);
  o_data            : out std_logic_vector(W-1 downto 0));
end delay_line;

architecture rtl of delay_line is

type t_ram is array (L-2 downto 0) of std_logic_vector(W-1 downto 0);
signal m_ram : t_ram;

signal r_addr_wr         : integer range 0 to L-2;
signal r_addr_rd         : integer range 0 to L-2;
signal r_enable_read     : std_logic;

begin

p_write : process (i_clk)
begin
  if rising_edge(i_clk) then
    if(i_sync_reset='1') then
      r_addr_wr      <= 0;
      r_enable_read  <= '0';
    else
      m_ram(r_addr_wr) <= i_data;
      if(r_addr_wr<L-2) then
        r_addr_wr      <= r_addr_wr + 1;
      else
        r_addr_wr      <= 0;
        r_enable_read  <= '1';       -- enable reading section
      end if;
    end if;
  end if;
end process p_write;

p_read : process (i_clk)
begin
  if rising_edge(i_clk) then
    if(i_sync_reset='1') then
      r_addr_rd      <= 0;
    else
      if(r_enable_read='1') then
        o_data         <= m_ram(r_addr_rd) ; -- additional delay
        if(r_addr_rd<L-2) then
          r_addr_rd      <= r_addr_rd + 1;
        else
          r_addr_rd      <= 0;
        end if;
      end if;
    end if;
  end if;
end process p_read;


end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity moving_average is
generic (
  G_NBIT                     : integer := 8;
  G_AVG_LEN_LOG              : integer := 2 );
port (
  i_clk                      : in  std_logic;
  i_rstb                     : in  std_logic;
  i_sync_reset               : in  std_logic;
  -- input
  i_data_ena                 : in  std_logic;
  i_data                     : in  std_logic_vector(G_NBIT-1 downto 0);
  -- output
  o_data_valid               : out std_logic;
  o_data                     : out std_logic_vector(G_NBIT-1 downto 0));
end moving_average;

architecture rtl of moving_average is

type t_moving_average is array (0 to 2**G_AVG_LEN_LOG-1) of signed(G_NBIT-1 downto 0);

signal p_moving_average                 : t_moving_average;
signal r_acc                            : signed(G_NBIT+G_AVG_LEN_LOG-1 downto 0);  -- average accumulator
signal r_data_valid                     : std_logic;

begin

p_average : process(i_clk,i_rstb)
begin
  if(i_rstb='0') then
    r_acc              <= (others=>'0');
  p_moving_average   <= (others=>(others=>'0'));
  r_data_valid       <= '0';
  o_data_valid       <= '0';
  o_data             <= (others=>'0');
  elsif(rising_edge(i_clk)) then
  r_data_valid       <= i_data_ena;
  o_data_valid       <= r_data_valid;
  if(i_sync_reset='1') then
    r_acc              <= (others=>'0');
    p_moving_average   <= (others=>(others=>'0'));
  elsif(i_data_ena='1') then
    p_moving_average   <= signed(i_data)&p_moving_average(0 to p_moving_average'length-2);
    r_acc              <= r_acc + signed(i_data)-p_moving_average(p_moving_average'length-1);
  end if;
  o_data             <= std_logic_vector(r_acc(G_NBIT+G_AVG_LEN_LOG-1 downto G_AVG_LEN_LOG));  -- divide by 2^G_AVG_LEN_LOG
  
  end if;
end process p_average;

end rtl;

 

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


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

9 часов назад, des00 сказал:

 гуру, 

:blush:

Сами Вы это слово.

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

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


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

`include "timescale.v"
/*===========================================================*/
module mean_filter(
    input               clk_i, /* 30.72MHz */
    input               rst_i,  
    input signed [21:0] dat_i,  
    input               srst_i,       
    input               valid_i,
    output signed [21:0] dat_o     
    );
/*===========================================================*/    
reg  [3:0] addr_wr; 
reg  [3:0] addr_rd;
reg signed  [25:0] S;   
wire signed  [25:0] S0;   
wire signed [21:0] dat_m;
reg                init_done;
/*===========================================================*/
assign dat_o= S[25:4]; 
assign S0= S- dat_m;
mem_x22 mem (.clk(clk_i), .a(addr_wr), .d(dat_i), .dpra(addr_rd), .we(valid_i), .qdpo(dat_m));
/*===========================================================*/
always @(posedge clk_i or posedge rst_i)    
begin 
if(rst_i)   
      S<= 0;
else
    begin
    if(srst_i)
        S<= 0;
    else
        begin           
        if(valid_i)
			begin
			if(init_done)
				S<= S0 + dat_i;
			else
				S<= S+ dat_i;
			end
        end    
    end
end     
/*===========================================================*/
always @(posedge clk_i or posedge rst_i)    
begin 
if(rst_i)  
     {addr_wr, addr_rd, init_done}<= 0;
else
	begin
    if(srst_i)
        {addr_wr, addr_rd, init_done}<= 0;
	else
		begin
		if(&addr_wr)
			init_done<= 1'b1;
		if(valid_i)
			begin
			addr_rd<= addr_wr+ 2'd2;
			addr_wr<= addr_wr+ 1'b1;
			end
		end
	end
end       
/*===========================================================*/   
endmodule
On 12/26/2020 at 11:09 AM, des00 said:

Ну это же не вам совет был, вы в этой теме гуру, а ТС изначально не был. Но прочитав все материалы по теме,  в том числе y(t) = y(t-1) - x(t-N) + x(t), ТС не узнал в описании вашего устройства вот эту простую формулу.

Если с двух- портовой RAM, так оптимально ?

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


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

4 hours ago, gosha said:

Если с двух- портовой RAM, так оптимально ?

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

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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