# VHDL FSM Moving Average

I'm trying to write a VHDL moving average (evenly weighted) module that uses FSMD(ata). From what I understand, the states needed would be something like fetch, divide, output. Below is the process I wrote, but I feel like my logic is a bit off. Note that the data I'm averaging is just a constant array of 8 bit numbers, so I figured it should be fine to use a non-causal design.

The data has 64 entries, and at the moment the window for the average is 4.

process (clk,rst) is

variable temp : integer range 0 to 1020;
begin
if rst = '1' then
count  <= 0;
n_state <= s0;
elsif (clk'event and clk = '1') then
c_state <= n_state;
case c_state is
when s0 =>
for i in 0 to (len) loop
temp := temp + pattern(count+i);
end loop;
n_state <= s1;
when s1 =>
temp := temp/4;
n_state <= s2;
when s2 =>
data <= std_logic_vector(to_unsigned(pattern(count),8));
data_avg <= std_logic_vector(to_unsigned(temp,8));
n_state <= s0;
count <= count+1;
end case;
end if;
end process;


How wrong does this look?

A few problems I can see right away:

1. You don't [re-]initialize temp anywhere.
2. You don't have any limit checks for count (is it a subtype or just a natural/integer? What happens with pattern(count+i) when you approach the limit? How do you roll over?)
3. Your for-loop is 0 to len - are you sure you didn't mean 0 to (len - 1)?
4. Since your entire state decode process is clocked, you don't really need n_state at all. Note that you're not even initializing c_state (but you're still decoding it). Either make your state decode a separate combinational process or just get rid of n_state and assign to c_state directly.

Otherwise, it depends on your design goals. If you don't care about throughput but need to run at a very high clock rate, you might want to perform your addition sequentially instead of in parallel, for example.

• thanks, that definitely does make things better. about the count rollover, I'm not sure really how to do it because for each pattern(count) up to 63, I want to display its value and the average of the window around it. so if i rollover at coun-len, it shouldn't go out of bounds but it will not show full data. if i was doing a causal implementation i would have some delay at the start, is it a similar thing I need here but at the end? Commented Sep 5, 2014 at 23:23
• my solution was: elsif (clk event) then if count = 64 then count <= 0; else calculate end if .And in the for loop i put an exit if count + i was greater than 63. Commented Sep 6, 2014 at 0:05

Is it an exercise about using a FSM, or you just need to generate a vector containing the averages ? If the input data are constants, all the calculations can be done during synthesis or at the beginning of simulation.

You can therefore write it as a simple function, as you would do in a 'normal' software programming language.

Here is an example :

TYPE array_byte IS ARRAY(natural RANGE <>) OF unsigned(7 DOWNTO 0);

CONSTANT pattern : array_byte(0 TO 63):=(0 => x"00",1 => x"10",2 => x"20",
OTHERS => x"30");

FUNCTION average4(CONSTANT v : array_byte) RETURN array_byte IS
VARIABLE vo : array_byte(0 TO v'length-5);
VARIABLE temp : unsigned(9 DOWNTO 0);
BEGIN
FOR i IN 0 TO v'length-5 LOOP
temp:=(OTHERS =>'0');
FOR j IN 0 TO 3 LOOP
temp:=temp + v(i+j);
END LOOP;
temp:=temp / 4;
vo(i):=temp(7 DOWNTO 0);
END LOOP;
RETURN vo;
END FUNCTION;

CONSTANT vout : array_byte(0 TO 59):=average4(pattern);