gosha 0 Posted December 16, 2020 · Report post На входе - сигнал с постоянной состовляющей. Необходимо получить усредненное значение сигнала (постоянную составляющую). Потеря точности НЕ допускается. Частота дискретизации 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 Quote Ответить с цитированием Share this post Link to post Share on other sites
des00 0 Posted December 16, 2020 · Report post 36 minutes ago, gosha said: Усредняем за время более периода младшей гармоники ? у вас не скользящее среднее 37 minutes ago, gosha said: Как экономичнее на verilog реализовать фильтр скользящего среднего ? CIC фильтр, одно звено, реализция без преобразования частоты Quote Ответить с цитированием Share this post Link to post Share on other sites
vitzap 0 Posted December 16, 2020 · Report post Если задача позволяет, очень просто сделать экспоненциально взвешенное скользящее среднее. https://ru.wikipedia.org/wiki/Скользящая_средняя Если a брать 1/2, 1/4, 1/8 и т.д. Quote Ответить с цитированием Share this post Link to post Share on other sites
gosha 0 Posted December 16, 2020 · Report post 35 minutes ago, des00 said: у вас не скользящее среднее CIC фильтр, одно звено, реализция без преобразования частоты Спасибо ! А точность не потеряется ? По Т.З. погрешность измерения дальности дальномером : 5 метров Задача фильтра- усреднить разность фаз фазомера. Нужен децимирующий фильтр на 30000. (30 МГц -> 1 KГц) IP Xilinx не генерит CIC с дещимацией 30_000. Только децимирующий на 8192 максимум. Еще разрядность повышается: А тама арктангенс после фильтра. Скользящее среднее не будет ли точнее ? tone_20KHz.slx Quote Ответить с цитированием Share this post Link to post Share on other sites
des00 0 Posted December 16, 2020 · Report post 29 minutes ago, gosha said: А точность не потеряется ? По Т.З. погрешность измерения дальности дальномером : 5 метров Задача фильтра- усреднить разность фаз фазомера. Нужен децимирующий фильтр на 30000. (30 МГц -> 1 KГц) IP Xilinx не генерит CIC с дещимацией 30_000. Только децимирующий на 8192 максимум. Еще разрядность повышается: А тама арктангенс после фильтра. Скользящее среднее не будет ли точнее ? вы хоть немного в ответ погрузитесь, до того как задавать вопросы и рисовать схемы в симулинке. по указанной выше ссылке в википедии, в разделе "Простое скользящее среднее, или арифметическое скользящее среднее" указана формула вот этого самого фильтра "CIC фильтр, одно звено, реализция без преобразования частоты". А децимировать можно на выходе. Но, если вам априори нужна децимация, то ваша реализация пойдет. Quote Ответить с цитированием Share this post Link to post Share on other sites
Tanya 0 Posted December 16, 2020 · Report post Автор! Вам нужно экспериментально найти подходящий метод усреднения, которых существует бесконечно много. Отбрасывая измерения, повысить точность? Трудно поверить. Quote Ответить с цитированием Share this post Link to post Share on other sites
MrGalaxy 0 Posted December 19, 2020 · Report post 16.12.2020 в 08:12, gosha сказал: Необходимо получить усредненное значение сигнала Недавно решал подобную задачу. Сделал используя мегафункцию FIFO. Прибавляется текущее значение, которое пишется в память и вычитается самое старое значение, которое в этот момент вылезает из памяти. 16.12.2020 в 08:12, gosha сказал: Усредняем за время более периода младшей гармоники ? Периодов лучше взять побольше, хотя бы 10. Quote Ответить с цитированием Share this post Link to post Share on other sites
gosha 0 Posted December 24, 2020 · Report post Спасибо !! Хорошее решение. Тогда уж кольцевой буфер на основе двухпортовой RAM: в голову пишется, суммируется, хвост вычитается? Quote Ответить с цитированием Share this post Link to post Share on other sites
des00 0 Posted December 25, 2020 · Report post On 12/19/2020 at 8:36 PM, MrGalaxy said: Прибавляется текущее значение, которое пишется в память и вычитается самое старое значение, которое в этот момент вылезает из памяти. это и есть формула из википедии, по приведенной ссылке) раздел статьи: Простое скользящее среднее, или арифметическое скользящее среднее Quote Ответить с цитированием Share this post Link to post Share on other sites
MrGalaxy 0 Posted December 25, 2020 · Report post 12 часов назад, des00 сказал: это и есть формула из википедии, по приведенной ссылке) раздел статьи: Простое скользящее среднее, или арифметическое скользящее среднее Ради формулы простейшего интегрирования в скользящем окне в Википедию лазить... Вопрос был про реализацию. 23 часа назад, gosha сказал: Тогда уж кольцевой буфер на основе двухпортовой RAM: в голову пишется, суммируется, хвост вычитается? Я про это и написал. Quote Ответить с цитированием Share this post Link to post Share on other sites
des00 0 Posted December 26, 2020 · Report post 15 hours ago, MrGalaxy said: Ради формулы простейшего интегрирования в скользящем окне в Википедию лазить... Вопрос был про реализацию. Ну это же не вам совет был, вы в этой теме гуру, а ТС изначально не был. Но прочитав все материалы по теме, в том числе y(t) = y(t-1) - x(t-N) + x(t), ТС не узнал в описании вашего устройства вот эту простую формулу. Quote Ответить с цитированием Share this post Link to post Share on other sites
Maverick_ 10 Posted December 26, 2020 · Report post 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; Quote Ответить с цитированием Share this post Link to post Share on other sites
MrGalaxy 0 Posted December 26, 2020 (edited) · Report post 9 часов назад, des00 сказал: гуру, Сами Вы это слово. Edited December 26, 2020 by MrGalaxy Quote Ответить с цитированием Share this post Link to post Share on other sites
gosha 0 Posted January 11 · Report post `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, так оптимально ? Quote Ответить с цитированием Share this post Link to post Share on other sites
des00 0 Posted January 11 · Report post 4 hours ago, gosha said: Если с двух- портовой RAM, так оптимально ? на ней и делают. но как-то у вас все сложно и для фильтра избыточно. хотя у вас может быть спец.применение и вам нужен результат на первом цикле, поэтому и делаете принудительную инициализацю. Quote Ответить с цитированием Share this post Link to post Share on other sites