moving_average.vhd


1
-- FMT FAU Erlangen -----------------------------------------------
2
-- moving_average:                                               --
3
-- this module generates a parametrized moving average over      --
4
-- two's complement dividable ranges with an parallel in parallel--
5
-- out data set.                                                 --
6
-- For the usage just set your desired data and shift width as a --
7
-- Bit statement.                                                --
8
--                                                               --
9
-------------------------------------------------------------------
10
11
-- Programming style ----------------------------------------------
12
-- parameter prefix | description                                --
13
-- g_               | generic, for entity declatation            --
14
-- i_               | input, for entity declatation              --
15
-- o_               | output, for entity declatation             --
16
-- io_              | in-/output, for entity declatation         --
17
-- c_               | constant, for architecture declatation     --
18
-- t_               | type, for architecture declatation         --
19
-- w_               | wire, used for internal signals            --
20
-- tb_              | testbench, used for internal signals       --
21
-- p_               | process, used for process labels           --
22
-- inst_            | instantiate, used fpr component instan-    --
23
--                    tiation                                    --
24
--                                                               --
25
-- parameter suffix | description                                --
26
-- _reg             | regular signal, for register (synchron)    --
27
-- _next            | next signal, for register (asynchron)      --
28
-- _s               | synchronised                               --
29
--                                                               --
30
-------------------------------------------------------------------
31
32
-- Revision History -----------------------------------------------
33
-- Version: | Author:   | Mod. Date:    | Changes Made:          --
34
-- 0.1      | Koehnen   | 05/09/17:     | Module developement    --
35
-------------------------------------------------------------------
36
37
library ieee;
38
use ieee.std_logic_1164.all;
39
use ieee.numeric_std.all;
40
use ieee.math_real.all;
41
42
43
entity moving_average is
44
  generic(
45
    g_data_width  : positive := 4;
46
    g_shift_width  : positive := 2
47
    );
48
  port(
49
    i_clk  : in  std_logic;
50
    i_clear  : in  std_logic;
51
    i_data  : in  std_logic_vector(g_data_width-1 downto 0);
52
    o_data  : out std_logic_vector(g_data_width-1 downto 0)
53
    );
54
end entity moving_average;
55
56
57
architecture behavioral of moving_average is
58
  
59
  -- constants
60
  constant c_shift_range : integer := integer(2.0**real(g_shift_width));
61
  
62
  -- typedeclaration
63
  type  t_Q_temp is array (0 to c_shift_range-1) of std_logic_vector(g_data_width-1 downto 0); 
64
  type  t_sum is array (0 to c_shift_range) of unsigned(g_data_width+g_shift_width-1 downto 0);
65
  -- g_shift_width also increments the length of guardbits which needed for the summation
66
  -- evidence: ceil(log2(2**g_shift_width)) == g_shift_width
67
  
68
  -- signals
69
  signal  w_Q_temp : t_Q_temp;
70
  signal  w_sum  : t_sum := (others => (others => '0'));
71
72
  -- components
73
  component shift_reg_pipo is
74
    generic(
75
      data_width : positive := 4
76
      );
77
    port(
78
      clk : in std_logic;
79
      clear : in std_logic;
80
      D: in std_logic_vector(g_data_width-1 downto 0);
81
      Q: out std_logic_vector(g_data_width-1 downto 0)
82
      );
83
  end component shift_reg_pipo;
84
85
  
86
begin
87
88
  -- parallel in parallel out (PIPO) shift register 
89
  p_shift_gen : for I in 1 to c_shift_range-1 generate
90
    pipo_I : shift_reg_pipo
91
    generic map(
92
      data_width => g_data_width
93
      )
94
    port map(
95
      clk => i_clk,
96
      clear => i_clear,
97
      D  => w_Q_temp(I-1), --  first element in loop is w_Q_temp(0)
98
      Q  => w_Q_temp(I)
99
      );
100
  end generate p_shift_gen;
101
  
102
  -- summation
103
  p_sum_gen : for I in 1 to c_shift_range generate
104
    w_sum(I) <= w_sum(I-1) + unsigned(w_Q_temp(I-1)); -- summs up every shifted value
105
  end generate p_sum_gen;
106
107
  -- connect shift register
108
  w_Q_temp(0) <= i_data(g_data_width-1 downto 0); -- allocates first data element to array
109
  
110
  -- divide/shift Bits
111
  o_data <= std_logic_vector(w_sum(c_shift_range)(g_data_width+g_shift_width-1 downto g_shift_width)); -- trimm last sum vector to devide by k*2
112
113
end architecture behavioral;