VHDL ile Değişinti (Variance) Hesaplama

Verilen bir dizinin değişintisinin (varyansının) hesaplanması Denkelm (1)’de gösterilmiştir. Denklem (1)’de X diziyi, µ dizinin ortalama değerini, N dizi boyunu ve σ2 değişinti değerini göstermektedir. Denklem (1)’de verilen denklemlerde öncelikle dizinin ortalama değerinin hesaplanması gerekmektedir.

Denklem (2)’de varyans hesaplama için kullanılabilecek farklı bir hesaplama yöntemi gösterilmiştir. Denklem 2’de dizi içerisinde bulunan sayıların karelerinin toplamının ortalamasından, dizinin ortalama değerinin karesi çıkartılarak varyans değeri hesaplanmaktadır.

Aşağıda verilen şekilde 1’den 20’ye kadar olan sayıların 10’luk bir diziye sırasıyla yazılması ile elde edilen değişinti sonuçlarının hesaplanmasına ilişkin benzetim sonucu gösterilmiştir. Benzetim sonucu verileri sayfanın sonunda verilen MATLAB kodu ile doğrulanmıştır.

Değişinti hesaplama işlemlerini gerçekleştirilen variance.vhd VHDL kodu kullanulmıştır. Kod içerisinde tanımlı moving_sum alt devresi blog mevctut olan VHDL ile Kayan Toplayıcı (Moving Sum) Tasarımı yazısında bulabilirsiniz.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
 
entity tb_variance is
end tb_variance;
 
architecture Behavioral of tb_variance is
    component variance
    Generic(
        DATA_WIDTH : integer := 12;
        SUM_SIZE : integer := 10
    );
    Port (
        in_clk : in std_logic;
        in_rst : in std_logic;
        in_data : in std_logic_vector(DATA_WIDTH - 1 downto 0);
        in_data_vld : in std_logic;
        out_data : out std_logic_vector(2 * DATA_WIDTH - 1 downto 0);
        out_data_vld : out std_logic
    );
    end component;
   
    constant DATA_WIDTH : integer := 12;
    constant SUM_SIZE : integer := 10;
    constant CLK_PERIOD : time := 1 us;
   
    signal in_clk : std_logic;
    signal in_data : std_logic_vector(DATA_WIDTH - 1 downto 0) := (others => '0');
    signal in_data_vld : std_logic;
    signal r_variance : std_logic_vector(2 * DATA_WIDTH - 1 downto 0) := (others => '0');
   
   
begin
 
 
    process
    begin
        in_clk <= '1';
        wait for CLK_PERIOD / 2;
        in_clk <= '0';
        wait for CLK_PERIOD / 2;
    end process;
   
    process
    begin
        in_data_vld <= '0';
        wait for  9 * CLK_PERIOD;
        if in_data = 20 then
            in_data <= conv_std_logic_vector(1, DATA_WIDTH);
        else
            in_data <= in_data + 1;
        end if;
        in_data_vld <= '1';
        wait for  CLK_PERIOD;
    end process;
   
    variance_map : variance
        Generic map(
            DATA_WIDTH => DATA_WIDTH,
            SUM_SIZE => SUM_SIZE
        )
        Port map(
            in_clk => in_clk,
            in_rst => '0',
            in_data => in_data,
            in_data_vld => in_data_vld,
            out_data => r_variance,
            out_data_vld => open
    );
 
end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
 
entity variance is
    Generic(
        DATA_WIDTH : integer := 12;
        SUM_SIZE : integer := 10
    );
    Port (
        in_clk : in std_logic;
        in_rst : in std_logic;
        in_data : in std_logic_vector(DATA_WIDTH - 1 downto 0);
        in_data_vld : in std_logic;
        out_data : out std_logic_vector(2 * DATA_WIDTH - 1 downto 0);
        out_data_vld : out std_logic
    );
end variance;
 
architecture Behavioral of variance is
 
    component moving_sum
    Generic(
        DATA_WIDTH : integer := 12;
        SUM_SIZE : integer := 10
    );
    Port (
        in_clk : in std_logic;
        in_rst : in std_logic;
        in_data : in std_logic_vector(DATA_WIDTH - 1 downto 0);
        in_data_vld : in std_logic;
        out_sum_value : out std_logic_vector(DATA_WIDTH - 1 downto 0);
        out_sum_value_vld : out std_logic
    );
    end component;
   
    component integer_divider
    Generic(
        DATA_WIDTH : integer := 12;
        DIV_PARAM : integer := 10
    );
    Port (
        in_clk : in std_logic;
        in_rst : in std_logic;
        in_data : in std_logic_vector(DATA_WIDTH - 1 downto 0);
        in_data_vld : in std_logic;
        out_data : out std_logic_vector(DATA_WIDTH - 1 downto 0);
        out_data_vld : out std_logic
    ); 
    end component;
   
    component integer_multiplier
    Generic(
        DATA_WIDTH : integer := 12
    );
    Port (
        in_clk : in std_logic;
        in_rst : in std_logic;
        in_data : in std_logic_vector(DATA_WIDTH - 1 downto 0);
        in_data_vld : in std_logic;
        out_data : out std_logic_vector(2 * DATA_WIDTH - 1 downto 0);
        out_data_vld : out std_logic
    );
    end component;
   
    signal r_data : std_logic_vector(2 * DATA_WIDTH - 1 downto 0);
    signal r_data_vld : std_logic;
    --
    signal r_ex : std_logic_vector(DATA_WIDTH - 1 downto 0);
    signal r_ex_vld : std_logic;
    signal r_ex_mean : std_logic_vector(DATA_WIDTH - 1 downto 0);
    signal r_ex_mean_vld : std_logic;
    signal r_ex2 : std_logic_vector(2 * DATA_WIDTH - 1 downto 0);
    signal r_ex2_vld : std_logic;      
    --
    signal r_e2x : std_logic_vector(2 * DATA_WIDTH - 1 downto 0);
    signal r_e2x_vld : std_logic;
    signal r_e2x_mean : std_logic_vector(2 * DATA_WIDTH - 1 downto 0);
    signal r_e2x_mean_vld : std_logic;
    signal r_e2x_mean_dly : std_logic_vector(2 * DATA_WIDTH - 1 downto 0);
    signal r_e2x_mean_dly_vld : std_logic;
   
begin
 
    out_data <= r_data;
    out_data_vld <= r_data_vld;
   
    process(in_clk, in_rst)
    begin
        if in_rst = '1' then
            r_data <= (others => '0');
            r_data_vld <= '0';
        elsif rising_edge(in_clk) then 
            r_data_vld <= '0';
            if r_ex2_vld = '1' then
                r_data <= r_e2x_mean_dly - r_ex2;
                r_data_vld <= '1';
            end if;
        end if;
    end process;
 
---
    ex_sum_map : moving_sum
        Generic map(
            DATA_WIDTH => DATA_WIDTH,
            SUM_SIZE => SUM_SIZE
        )
        Port map (
            in_clk => in_clk,
            in_rst => in_rst,
            in_data => in_data,
            in_data_vld => in_data_vld,
            out_sum_value => r_ex,
            out_sum_value_vld => r_ex_vld
        ); 
       
    ex_divider_map : integer_divider
        Generic map(
            DATA_WIDTH => DATA_WIDTH,
            DIV_PARAM => SUM_SIZE
        )
        Port map (
            in_clk => in_clk,
            in_rst => in_rst,
            in_data => r_ex,
            in_data_vld => r_ex_vld,
            out_data => r_ex_mean,
            out_data_vld => r_ex_mean_vld
        );     
   
    ex_multiplier_map : integer_multiplier
        Generic map(
            DATA_WIDTH => DATA_WIDTH
        )
        Port map(
            in_clk => in_clk,
            in_rst => in_rst,
            in_data => r_ex_mean,
            in_data_vld => r_ex_mean_vld,
            out_data => r_ex2,
            out_data_vld => r_ex2_vld
        );
       
----------------------     
    e2x_sum_map : moving_sum
        Generic map(
            DATA_WIDTH => 2* DATA_WIDTH,
            SUM_SIZE => SUM_SIZE
        )
        Port map (
            in_clk => in_clk,
            in_rst => in_rst,
            in_data => in_data * in_data,
            in_data_vld => in_data_vld,
            out_sum_value => r_e2x,
            out_sum_value_vld => r_e2x_vld
        ); 
       
    e2x_divider_map : integer_divider
        Generic map(
            DATA_WIDTH => 2 * DATA_WIDTH,
            DIV_PARAM => SUM_SIZE
        )
        Port map (
            in_clk => in_clk,
            in_rst => in_rst,
            in_data => r_e2x,
            in_data_vld => r_e2x_vld,
            out_data => r_e2x_mean,
            out_data_vld => r_e2x_mean_vld
        );     
 
    process(in_clk, in_rst)
    begin
        if in_rst = '1' then
            r_e2x_mean_dly <= (others => '0');
            r_e2x_mean_dly_vld <= '0';
        elsif rising_edge(in_clk) then
            r_e2x_mean_dly_vld <= '0';
            if r_e2x_mean_vld = '1' then
                r_e2x_mean_dly <= r_e2x_mean;
                r_e2x_mean_dly_vld <= '1';
            end if;
        end if;
    end process;       
       
end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
 
entity integer_divider is
    Generic(
        DATA_WIDTH : integer := 12;
        DIV_PARAM : integer := 10
    );
    Port (
        in_clk : in std_logic;
        in_rst : in std_logic;
        in_data : in std_logic_vector(DATA_WIDTH - 1 downto 0);
        in_data_vld : in std_logic;
        out_data : out std_logic_vector(DATA_WIDTH - 1 downto 0);
        out_data_vld : out std_logic
    );
end integer_divider;
 
architecture Behavioral of integer_divider is
 
    signal r_data : std_logic_vector(DATA_WIDTH - 1 downto 0) := (others => '0');
    signal r_data_vld : std_logic := '0';
   
    function f_Int_Divider (in_data : std_logic_vector(DATA_WIDTH - 1 downto 0); DIV_PARAM : integer ) return std_logic_vector is
    begin
        return conv_std_logic_vector((conv_integer(in_data) / DIV_PARAM), DATA_WIDTH);
    end f_Int_Divider;
 
begin
 
    out_data <= r_data;
    out_data_vld <= r_data_vld;
   
    process(in_clk, in_rst)    
    begin
        if in_rst = '1' then
            r_data <= (others => '0');
            r_data_vld <= '0';
        elsif rising_edge(in_clk) then
            r_data_vld <= '0';
            if in_data_vld = '1' then
                r_data <= f_Int_Divider(in_data, DIV_PARAM);
                r_data_vld <= '1';
            end if;
        end if;
    end process;
 
end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
 
entity integer_multiplier is
    Generic(
        DATA_WIDTH : integer := 12
    );
    Port (
        in_clk : in std_logic;
        in_rst : in std_logic;
        in_data : in std_logic_vector(DATA_WIDTH - 1 downto 0);
        in_data_vld : in std_logic;
        out_data : out std_logic_vector(2 * DATA_WIDTH - 1 downto 0);
        out_data_vld : out std_logic
    );
end integer_multiplier;
 
architecture Behavioral of integer_multiplier is
 
    signal r_data : std_logic_vector(2 * DATA_WIDTH - 1 downto 0) := (others => '0');
    signal r_data_vld : std_logic := '0';
 
begin
 
    out_data <= r_data;
    out_data_vld <= r_data_vld;
   
    process(in_clk, in_rst)    
    begin
        if in_rst = '1' then
            r_data <= (others => '0');
            r_data_vld <= '0';
        elsif rising_edge(in_clk) then
            r_data_vld <= '0';
            if in_data_vld = '1' then
                r_data <= in_data * in_data;
                r_data_vld <= '1';
            end if;
        end if;
    end process;
 
 
end Behavioral;

Aşağıda sınama kodlarının doğruluk kontrolünün yapıldığı MATLAB kodu verilmiştir.

clc, clear all, close all;
 
Buffer_length = 10;
Buffer = zeros(1, Buffer_length);
 
for n_j = 0 : 1
    for n_i = 1 : 20
        Buffer(1 : Buffer_length - 1) = Buffer(2 : Buffer_length);
        Buffer(Buffer_length) = n_i;
        Var(n_j * 20 + n_i) = fix(sum(Buffer.^2) / Buffer_length) - ...
                   fix(sum(Buffer) / Buffer_length)^2;
    end
end

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir