Wiener filtresi, gözlenen sinyalin içerisindeki istenmeyen gürültüyü azaltmak ve asıl (temiz) sinyali tahmin etmek için kullanılan doğrusal ve istatistiksel bir filtredir. Temel olarak, minimum ortalama kare hata ilkesine göre çalışır ve FIR (Finite Impulse Response) yapısını temel alır.
Bu filtre özellikle şuralarda etkilidir:
- Sinyal ve gürültünün istatistiksel özellikleri biliniyorsa
- Gürültü sabitse veya karakterize edilebiliyorsa
- Eğitim verisiyle referans sinyal tahmin edilebiliyorsa
Gözlenen sinyal şu şekilde ifade edilir:
![]()
Burada:
- x(n) : Ölçülen (gözlenen) sinyal
- s(n): Asıl (temiz) sinyal
- n(n): Gürültü bileşeni
Amaç: x(n)’den yola çıkarak s(n)’yi olabildiğince doğru şekilde tahmin etmektir.
Wiener filtresi FIR yapısındadır. Çıkış sinyali geçmiş giriş örneklerinin ağırlıklı toplamıdır:
![]()
Burada:
: Tahmin edilen sinyal- w_k: Filtre katsayıları
- M: Filtrenin derecesi (tap sayısı)
Filtrenin doğruluğu, çıkış ile gerçek sinyal arasındaki ortalama karesel hata (MSE) ile ölçülür:
![]()
Bu hata fonksiyonunu minimize eden katsayılar “optimal” olarak kabul edilir.
Optimal katsayılar şu denklemle hesaplanır:
![]()
Burada:
: Giriş sinyalinin otokorelasyon matrisi
: Giriş sinyali ile referans (temiz) sinyalin çapraz korelasyon vektörü
: Optimal filtre katsayıları
Aşağıda FIR filtre olarak katsayılaı hesaplanmış Wiener Filtrenin VHDL kodlarını görebilirsiniz.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.MATH_REAL.ALL;
use std.textio.ALL;
library work;
use work.Wiener_Filter_Package.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Wiener_Filter is
Generic(
DATA_LENGTH : integer := 16
);
Port (
in_clk : in std_logic;
in_rst : in std_logic;
in_data : in std_logic_vector(DATA_LENGTH - 1 downto 0);
in_data_vld : in std_logic;
out_data : out std_logic_vector(DATA_LENGTH - 1 downto 0);
out_data_vld : out std_logic
);
end Wiener_Filter;
architecture Behavioral of Wiener_Filter is
type t_Signal_Buf_vec is array(0 to c_TIME_samp - 1) of std_logic_vector(DATA_LENGTH - 1 downto 0);
type t_X_Shift_Ctrl is (IDLE, SHIFT_DATA);
signal r_X_Shift_Ctrl : t_X_Shift_Ctrl := IDLE;
signal r_calc_fltr_out_strt : std_logic := '0';
signal r_data : std_logic_vector(DATA_LENGTH - 1 downto 0) := (others => '0');
signal r_filter_out_vld : std_logic := '0';
signal n_i : integer := 0;
type t_data_X_buffer is array (0 to c_FILT_LEN - 1 ) of std_logic_vector(DATA_LENGTH - 1 downto 0);
signal r_data_X_buffer : t_data_X_buffer := (others => (others => '0'));
function f_Shift_X_Buf(r_data_X_buffer : t_data_X_buffer; in_data : std_logic_vector(DATA_LENGTH - 1 downto 0)) return t_data_X_buffer is
variable v_data_X_buffer : t_data_X_buffer;
begin
v_data_X_buffer := r_data_X_buffer;
for n_i in c_FILT_LEN - 2 downto 0 loop
v_data_X_buffer(n_i + 1) := v_data_X_buffer(n_i);
end loop;
v_data_X_buffer(0) := in_data;
return v_data_X_buffer;
end f_Shift_X_Buf;
signal r_filter_sum_out : std_logic_vector(COEF_LENGTH + COEF_ADD + DATA_LENGTH + 4 - 1 downto 0) := (others => '0');
signal r_filter_out : std_logic_vector(DATA_LENGTH - 1 downto 0) := (others => '0');
type t_Calc_Filter_out is (IDLE, ADD_X_BUF_PARAM , SUB_Y_BUF_PARAM, ROUND_PROCESS, DONE);
signal r_Calc_Filter_out : t_Calc_Filter_out := IDLE;
begin
out_data <= r_filter_out;
out_data_vld <= r_filter_out_vld;
process(in_clk, in_rst)
begin
if in_rst = '1' then
r_data_X_buffer <= (others => (others => '0'));
r_calc_fltr_out_strt <= '0';
r_data <= (others => '0');
elsif rising_edge(in_clk) then
r_calc_fltr_out_strt <= '0';
case r_X_Shift_Ctrl is
when IDLE =>
if in_data_vld = '1' then
r_data <= in_data;
r_X_Shift_Ctrl <= SHIFT_DATA;
end if;
when SHIFT_DATA =>
r_data_X_buffer <= f_Shift_X_Buf(r_data_X_buffer, r_data);
r_X_Shift_Ctrl <= IDLE;
r_calc_fltr_out_strt <= '1';
when others => NULL;
end case;
end if;
end process;
process(in_clk, in_rst)
begin
if in_rst = '1' then
r_Calc_Filter_out <= IDLE;
r_filter_sum_out <= (others => '0');
r_filter_out_vld <= '0';
r_filter_out <= (others => '0');
n_i <= 0;
elsif rising_edge(in_clk) then
r_filter_out_vld <= '0';
case r_Calc_Filter_out is
when IDLE =>
if r_calc_fltr_out_strt = '1' then
r_Calc_Filter_out <= ADD_X_BUF_PARAM;
end if;
when ADD_X_BUF_PARAM =>
r_filter_sum_out <= r_filter_sum_out + sxt((r_data_X_buffer(n_i)) * (r_Coef_vec(n_i)), r_filter_sum_out'length);
n_i <= n_i + 1;
if n_i = c_FILT_LEN-1 then
n_i <= 0;
r_Calc_Filter_out <= DONE;
end if;
when DONE =>
r_filter_out_vld <= '1';
r_filter_sum_out <= (others => '0');
r_filter_out <= r_filter_sum_out(COEF_LENGTH + DATA_LENGTH - 1 downto COEF_LENGTH );
r_Calc_Filter_out <= IDLE;
when others => NULL;
end case;
end if;
end process;
end Behavioral;
Filtre katsayılarının hesaplandığı ve diğer tanımalamaların yapıldığı paket dosyasını aşağıad görebilirsiniz.
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 14.06.2025 22:22:15
-- Design Name:
-- Module Name: Wiener_Filter_Package - Behavioral
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.MATH_REAL.ALL;
use std.textio.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
package Wiener_Filter_Package is
constant c_FILT_LEN : integer := 32;
constant c_FS : integer := 10_000; -- Hz - Örnekleme Frekansı
constant c_TIME : integer := 100; -- ms - Referasn sinyal süresi
constant c_FREQ_0 : integer := 2000; -- Hz referans sinyal frekansı
constant c_TIME_samp : integer := c_FS * c_TIME / 1000; -- Referans sinyal oluşturmak gerekli örnek sayısı
constant COEF_LENGTH : integer := 12;
constant COEF_ADD : integer := 4;
constant PATH_REF : string := "D:\Ref_Signal.txt";
constant PATH_SUM : string := "D:\Sum_Signal.txt";
constant PATH_COEF : string := "D:\Wiener_Coef.txt";
type t_Signal_Buf is array(0 to c_TIME_samp - 1) of real;
type t_Rxx_Buf is array(0 to c_FILT_LEN - 1, 0 to c_FILT_LEN - 1) of real;
type t_Rxd_Buf is array(0 to c_FILT_LEN - 1) of real;
type t_Ext_Rxx_Buf is array(0 to c_FILT_LEN - 1, 0 to c_FILT_LEN) of real;
function f_Rand_Noise(f_TIME_samp : integer) return t_Signal_Buf;
function f_Ref_Sin(f_FS, f_TIME_samp, f_FREQ : integer) return t_Signal_Buf;
function f_Sum_Signal(Ref_Sig, Rand_Noise : t_Signal_Buf; f_TIME_samp : integer) return t_Signal_Buf;
signal r_Ref_Signal : t_Signal_Buf := f_Ref_Sin(c_FS, c_TIME_samp, c_FREQ_0);
signal r_Noise_Signal : t_Signal_Buf := f_Rand_Noise(c_TIME_samp);
signal r_Sum_Signal : t_Signal_Buf := f_Sum_Signal(r_Ref_Signal, r_Noise_Signal, c_TIME_samp);
function f_Extend_Rxx(Rxx : t_Rxx_Buf; Rxd : t_Rxd_Buf; Filt_Len : integer) return t_Ext_Rxx_Buf;
function f_Coef_Calc(Sum_Sig, Ref_Sig : t_Signal_Buf; Filt_Len, Data_Len : integer) return t_Rxd_Buf;
signal r_Coef : t_Rxd_Buf := f_Coef_Calc(r_Sum_Signal, r_Ref_Signal, c_FILT_LEN, c_TIME_samp);
type t_Rxd_Buf_vec is array(0 to c_FILT_LEN - 1) of std_logic_vector(COEF_LENGTH + COEF_ADD - 1 downto 0);
function f_Coef_Conv( Rxd : t_Rxd_Buf; Filt_Len : integer) return t_Rxd_Buf_vec;
signal r_Coef_vec : t_Rxd_Buf_vec := f_Coef_Conv(r_Coef, c_FILT_LEN);
end Wiener_Filter_Package;
package body Wiener_Filter_Package is
function f_Rand_Noise(f_TIME_samp : integer) return t_Signal_Buf is
variable v_Noise_Signal : t_Signal_Buf := (others => 0.0);
variable seed1 : integer := 1;
variable seed2 : integer := 1;
variable r : real;
variable min_val : real := -1.0;
variable max_val : real := 1.0;
begin
for ni in 0 to f_TIME_samp - 1 loop
uniform(seed1, seed2, r);
v_Noise_Signal(ni) := r * (max_val - min_val) + min_val;
end loop;
return v_Noise_Signal;
end function;
function f_Ref_Sin(f_FS, f_TIME_samp, f_FREQ : integer) return t_Signal_Buf is
variable v_Ref_Signal : t_Signal_Buf := (others => 0.0);
begin
for ni in 0 to f_TIME_samp - 1 loop
v_Ref_Signal(ni) := sin(2.0 * MATH_PI * real(ni) * real(f_FREQ) / real(f_FS));
end loop;
return v_Ref_Signal;
end function;
function f_Sum_Signal(Ref_Sig, Rand_Noise : t_Signal_Buf; f_TIME_samp : integer) return t_Signal_Buf is
variable v_Sum_Signal : t_Signal_Buf := (others => 0.0);
begin
for ni in 0 to f_TIME_samp - 1 loop
v_Sum_Signal(ni) := Ref_Sig(ni) + Rand_Noise(ni);
end loop;
return v_Sum_Signal;
end function;
function f_Extend_Rxx(Rxx : t_Rxx_Buf; Rxd : t_Rxd_Buf; Filt_Len : integer) return t_Ext_Rxx_Buf is
variable v_Ext_Rxx_Buf : t_Ext_Rxx_Buf;
begin
for ni in 0 to Filt_Len - 1 loop
for nj in 0 to Filt_Len loop
if nj = Filt_Len then
v_Ext_Rxx_Buf(ni, nj) := Rxd(ni);
else
v_Ext_Rxx_Buf(ni, nj) := Rxx(ni, nj);
end if;
end loop;
end loop;
return v_Ext_Rxx_Buf;
end function;
function f_Coef_Calc(Sum_Sig, Ref_Sig : t_Signal_Buf; Filt_Len, Data_Len : integer) return t_Rxd_Buf is
variable v_Rxx : t_Rxx_Buf := (others => (others => 0.0));
variable v_Rxd : t_Rxd_Buf := (others => 0.0);
variable v_Ext_Rxx : t_Ext_Rxx_Buf;
variable v_factor : real;
variable v_Coef : t_Rxd_Buf := (others => 0.0);
variable v_sum : real := 0.0;
file file_s : text open write_mode is PATH_SUM;
file file_c : text open write_mode is PATH_COEF;
file file_r : text open write_mode is PATH_REF;
variable row_r : line;
variable row_s : line;
variable row_c : line;
variable data : real;
begin
for ni in 0 to Filt_Len - 1 loop
for nj in 0 to Filt_Len - 1 loop
for nn in Filt_Len - 1 to Data_Len - 1 loop
v_Rxx(ni, nj) := v_Rxx(ni, nj) + Sum_Sig(nn - ni) * Sum_Sig(nn - nj);
end loop;
end loop;
for nn in Filt_Len - 1 to Data_Len - 1 loop
v_Rxd(ni) := v_Rxd(ni) + Sum_Sig(nn - ni) * Ref_Sig(nn);
end loop;
end loop;
for ni in 0 to Filt_Len - 1 loop
for nj in 0 to Filt_Len - 1 loop
v_Rxx(ni, nj) := v_Rxx(ni, nj) / real(Data_Len - Filt_Len + 1);
end loop;
v_Rxd(ni) := v_Rxd(ni) / real(Data_Len - Filt_Len + 1);
end loop;
v_Ext_Rxx := f_Extend_Rxx(v_Rxx, v_Rxd, Filt_Len);
for ni in 0 to Filt_Len - 1 loop
for nj in ni + 1 to Filt_Len - 1 loop
v_factor := v_Ext_Rxx(nj, ni) / v_Ext_Rxx(ni, ni);
for nn in 0 to Filt_Len loop
v_Ext_Rxx(nj, nn) := v_Ext_Rxx(nj, nn) - v_factor * v_Ext_Rxx(ni, nn);
end loop;
end loop;
end loop;
for ni in Filt_Len-1 downto 0 loop
v_sum := 0.0;
for nk in ni + 1 to Filt_Len - 1 loop
v_sum := v_sum + v_Ext_Rxx(ni, nk) * v_Coef(nk);
end loop;
v_Coef(ni) := (v_Ext_Rxx(ni, Filt_Len) - v_sum) / v_Ext_Rxx(ni, ni);
end loop;
for ni in 0 to Filt_Len - 1 loop
data := v_Coef(ni);
write(row_c, data);
writeline(file_c, row_c);
end loop;
for ni in 0 to Data_Len - 1 loop
data := Sum_Sig(ni);
write(row_s, data);
writeline(file_s, row_s);
end loop;
for ni in 0 to Data_Len - 1 loop
data := Ref_Sig(ni);
write(row_r, data);
writeline(file_r, row_r);
end loop;
return v_Coef;
end function;
function f_Coef_Conv( Rxd : t_Rxd_Buf; Filt_Len : integer) return t_Rxd_Buf_vec is
variable v_Rxd_vec : t_Rxd_Buf_vec;
begin
for ni in 0 to Filt_Len - 1 loop
v_Rxd_vec(ni) := conv_std_logic_vector(integer(Rxd(ni) * real(2**COEF_LENGTH)), COEF_LENGTH + COEF_ADD);
end loop;
return v_Rxd_vec;
end function;
end Wiener_Filter_Package;
Aşağıda katsayılarının üretiminde kullanılan sinyalin hesaplanan katsayılar ile filtrelenmesinin benzetim çıktısı ve benzetim kodları verilmiştir.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.MATH_REAL.ALL;
use std.textio.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity tb_Wiener_Filter is
end tb_Wiener_Filter;
architecture Behavioral of tb_Wiener_Filter is
component Wiener_Filter
Generic(
DATA_LENGTH : integer := 16
);
Port (
in_clk : in std_logic;
in_rst : in std_logic;
in_data : in std_logic_vector(DATA_LENGTH - 1 downto 0);
in_data_vld : in std_logic;
out_data : out std_logic_vector(DATA_LENGTH - 1 downto 0);
out_data_vld : out std_logic
);
end component;
constant DATA_PATH : string := "D:\Sum_Signal.txt";
constant CLK_PERIOD : time := 100 ns;
constant SAMPLING_CNTR : integer := 1000;
constant DATA_LENGTH : integer := 24;
signal in_clk : std_logic := '0';
signal clk_cnt : integer := 0;
signal in_data : std_logic_vector(DATA_LENGTH - 1 downto 0) := (others => '0');
signal in_data_vld : std_logic := '0';
signal out_data : std_logic_vector(DATA_LENGTH - 1 downto 0) := (others => '0');
signal out_data_vld : std_logic := '0';
begin
process
begin
in_clk <= '1';
wait for CLK_PERIOD / 2;
in_clk <= '0';
wait for CLK_PERIOD / 2;
end process;
process (in_clk)
file file_s : text open read_mode is DATA_PATH ;
variable line_s : line;
variable data_s : real;
begin
if rising_edge(in_clk) then
in_data_vld <= '0';
if clk_cnt = SAMPLING_CNTR - 1 then
clk_cnt <= 0;
if not(endfile(file_s)) then
readline(file_s, line_s);
read(line_s, data_s);
in_data <= conv_std_logic_vector(integer(data_s * real(2**(DATA_LENGTH - 2))), 24) ;
in_data_vld <= '1';
end if;
else
clk_cnt <= clk_cnt + 1;
end if;
end if;
end process;
Wiener_Filter_map : Wiener_Filter
Generic map(
DATA_LENGTH => DATA_LENGTH
)
Port map(
in_clk => in_clk,
in_rst => '0',
in_data => in_data,
in_data_vld => in_data_vld,
out_data => out_data,
out_data_vld => out_data_vld
);
end Behavioral;