VHDL ile Kayan Toplayıcı (Moving Sum) Tasarımı
Şekil 1’de gösterilen N adet örneğe sahip bir örneklem penceresinin toplam değerinin hesaplanma işlemleri Denklem (1) ve Denklem (2)’de gösterildiği gibi yapılmaktadır.
Şekil 1 . N adet örneğe sahip örneklem penceresi
Daha az toplama işlemi yapabilmek amacıyla, yeni toplam değerini bulmak için bir önceki toplam değerini kullanarak elde etmek için N+1 adet örneğe sahip bir örneklem penceresi kullanmak gerekmektedir (Şekil 2). Matematiksel hesaplama da Denklem (3)’deki gibi yapılmaktadır.
Şekil 2 . N +1 adet örneğe sahip örneklem penceresi
Aşağıda kayan toplayıcı VHDL kodu verilmiştir. Generic parametreler olarak 8. satırda veri uzunluğu tanımlanmaktadır. 9. satırda ise kaç adet verinin toplanacağına ait tanımlama yapılmaktadır. 23. satırda buffer tanımlaması yapılmaktadır. Tanımlamadan da görüleceği üzere Generic olarak tanımlanan parametreler kullanılarak SUM_SIZE + 1 uzunluğunda DATA_WIDTH genişliğinde buffer tanımlanmıştır. 26-35 satırları arasında ise buffer içerisinde ki dataların kaydırılması işleminin gerçekleştirildiği fonksiyon tanımlanmaktadır. 46-60 satırları arasında yukarıda (2) nolu denklemde tanımlanan işlemler gerçekleştirilmektedir. 62-75 satırları arasında ise giriş datasının hafızaya yazılma işlemi gerçekleştirilmektedir.
- library IEEE;
- use IEEE.STD_LOGIC_1164.ALL;
- use IEEE.STD_LOGIC_SIGNED.ALL;
- use IEEE.STD_LOGIC_ARITH.ALL;
- entity moving_sum 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_sum_value : out std_logic_vector(DATA_WIDTH - 1 downto 0);
- out_sum_value_vld : out std_logic
- );
- end moving_sum;
- architecture Behavioral of moving_sum is
- type t_SUM_BUFFER is array (0 to SUM_SIZE)
- of std_logic_vector(DATA_WIDTH - 1 downto 0);
- signal r_SUM_BUFFER : t_SUM_BUFFER :=
- (others => (others => '0'));
- function f_shift_data_left
- (in_BUFFER : t_SUM_BUFFER;
- in_data : std_logic_vector(DATA_WIDTH - 1 downto 0))
- return t_SUM_BUFFER is
- variable v_SUM_BUFFER : t_SUM_BUFFER;
- begin
- v_SUM_BUFFER := in_BUFFER;
- for n_i in 0 to SUM_SIZE - 1 loop
- v_SUM_BUFFER(n_i) := v_SUM_BUFFER(n_i + 1);
- end loop;
- v_SUM_BUFFER(SUM_SIZE) := in_data;
- return v_SUM_BUFFER;
- end function;
- signal r_strt_calc : std_logic := '0';
- signal r_sum_value :
- std_logic_vector(DATA_WIDTH - 1 downto 0)
- := (others => '0');
- signal r_sum_value_vld : std_logic;
- begin
- out_sum_value <= r_sum_value;
- out_sum_value_vld <= r_sum_value_vld;
- process(in_clk)
- begin
- if in_rst = '1' then
- r_sum_value <= (others => '0');
- r_sum_value_vld <= '0';
- elsif rising_edge(in_clk) then
- r_sum_value_vld <= '0';
- if r_strt_calc = '1' then
- r_sum_value_vld <= '1';
- r_sum_value <= r_sum_value
- + r_SUM_BUFFER(SUM_SIZE) - r_SUM_BUFFER(0);
- end if;
- end if;
- end process;
- process(in_clk)
- begin
- if in_rst = '1' then
- r_SUM_BUFFER <= (others => (others => '0'));
- r_strt_calc <= '0';
- elsif rising_edge (in_clk) then
- r_strt_calc <= '0';
- if in_data_vld = '1' then
- r_SUM_BUFFER <= f_shift_data_left(r_SUM_BUFFER, in_data);
- r_strt_calc <= '1';
- end if;
- end if;
- end process;
- end Behavioral;
Aşağıda moving_sum varlığının test işlemlerinin yapılabilmesi için sınama kodu verilmiştir. Sınama kodunda girişe 1’den 20’ye kadar sıralı olarak veriler verilmektedir. Benzetim elde edilen sonuçlar aşağıdaki şekilde gösterilmektedir.
- library IEEE;
- use IEEE.STD_LOGIC_1164.ALL;
- use IEEE.STD_LOGIC_SIGNED.ALL;
- use IEEE.STD_LOGIC_ARITH.ALL;
- entity tb_moving_sum is
- end tb_moving_sum;
- architecture Behavioral of tb_moving_sum 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;
- constant DATA_WIDTH : integer := 12;
- constant SUM_SIZE : integer := 10;
- constant CLK_PERIOD : time := 10 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 out_sum_value : std_logic_vector(DATA_WIDTH - 1 downto 0);
- signal out_sum_value_vld : std_logic;
- 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;
- moving_sum_map : moving_sum
- 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_sum_value => out_sum_value,
- out_sum_value_vld => out_sum_value_vld
- );
- end Behavioral;