Forum Discussion
Altera_Forum
Honored Contributor
12 years agocontinuous averaging using VHDL
I have a question related to VHDL programming. I want to calculate the continuous average. My example code is:
process (clk, reset)
begin
if (reset = '1') then
state<=idle;
out-val=0;
elsif(rising_edge(clk)) then
case state is
when idle =>
if req='1' then
state= out-1;
end if;
when out-1 =>
if done='1' then
out-val<=data-in (11 downto 0)
state <= done-st;
endif;
when done-st =>
ack <='1';
state <= idle;
when others =>
state <= idle;
end case;
end if;
end process;
On every positive edge of clock, the value of "out-val" changes. I want to continuously take the average of "out-val". I want to take average of 32 values continuously. Is there a way where I can take average of 32 values continuously till the clock is running. Kindly let me know how can I do that. You can modify the above code as well. Many Thanks,90 Replies
- Altera_Forum
Honored Contributor
@kaz
With this approach I am getting no value. I used the following code:
The value of adc_a_out is '0' all the time. Is there any mistake in it?signal counter : integer range 0 to 1023 := 0; signal data_in_d : signed(11 downto 0) := (others => '0'); signal sum: signed(21 downto 0) := (others => '0); signal avg : std_logic_vector (11 downto 0); type type1 is array (1 to 31) of std_logic_vector(11 downto 0); signal stage: type1 := (others => (others => '0')); signal sub_result: signed(12 downto 0) := (others => '0'); signal sum_new: signed(16 downto 0) := (others => '0'); process (clk, reset) begin if (reset = '1') then out_val=0; elsif(rising_edge(clk)) then case state is when out_1 => if done='1' then data_out <= addr0 & bits; counter <= counter + 1; data_in_d <= signed(data_in(11 downto 0)); if counter /= 0 then sum <= sum + data_in_d; else sum <= (others => '0'); avg <= std_logic_vector(sum(21 downto 10)); stage(1) <= avg(11 downto 0); for i in 2 to 31 loop stage(i) <= stage(i-1); end loop; -- subtract last stage from input sub_result <= resize(signed(avg),13) - signed(stage(31)); -- accumulate sum_new <= sum_new + sub_result; adc_a_out <= std_logic_vector(sum_new(16 downto 5)); end if; state <= out_2; endif; end process; - Altera_Forum
Honored Contributor
check your count becomes zero
check avg - Altera_Forum
Honored Contributor
--- Quote Start --- check your count becomes zero check avg --- Quote End --- @kaz the counter value becomes zero and I get the adc value on the FPGA very late. I think the process is very slow because of 1024 samples. Is there a way to make it fast? - Altera_Forum
Honored Contributor
The samples should end up in a memory block - with read and write pointers.
- Altera_Forum
Honored Contributor
--- Quote Start --- @kaz the counter value becomes zero and I get the adc value on the FPGA very late. I think the process is very slow because of 1024 samples. Is there a way to make it fast? --- Quote End --- 1/1024 is the update rate of avg, this then averaged at this slow rate. That is you wanted and shouldn't be a problem , not even in simulation. What is ADC speed then? - Altera_Forum
Honored Contributor
--- Quote Start --- 1/1024 is the update rate of avg, this then averaged at this slow rate. That is you wanted and shouldn't be a problem , not even in simulation. What is ADC speed then? --- Quote End --- My ADC captures value every 312/20 KHz i-e 15.6 KHz. - Altera_Forum
Honored Contributor
@kaz
Two questions. The approach that I was using before for 32 samples, I increased that to 100 samples. I did following changes in the code:
Can you tell if the number of bits for sum and sub_result are correct for 100 samples? 2nd question is related to the block average. I changed the 1024 samples to 32 samples and then averaging 5 blocks.data_in : in std_logic_vector (99 downto 0); type type1 is array (1 to 99) of std_logic_vector(11 downto 0); signal stage: type1 := (others => (others => '0')); signal sub_result: signed(12 downto 0) := (others => '0'); signal sum: signed(19 downto 0) := (others => '0'); process (clk, reset) begin if (reset = '1') then state<=idle; out_val=0; out_val_2 <= 0; elsif(rising_edge(clk)) then case state is when idle => if req='1' then state= out_1; end if; when out_1 => if done='1' then data_out <= addr0 & bits; stage(1) <= data_in(11 downto 0); for i in 2 to 99 loop stage(i) <= stage(i-1); end loop; -- subtract last stage from input sub_result <= resize(signed(data_in),13) - signed(stage(99)); -- accumulate sum <= sum + sub_result; adc_a_out <= std_logic_vector(sum(19 downto 8)); avg_1 <= '1'; state <= out_2; endif; end case; end if; end process;
Is the number of bits for sum and sum assignment to avg is correct?signal counter : integer 0 to 31 := 0; signal data_in_d : signed(11 downto 0) := (others => '0'); signal sum: signed(16 downto 0) := (others => '0); signal avg : std_logic_vector (11 downto 0); type type1 is array (1 to 3) of std_logic_vector(11 downto 0); signal stage: type1 := (others => (others => '0')); signal sub_result: signed(12 downto 0) := (others => '0'); signal sum_new: signed(16 downto 0) := (others => '0'); process (clk, reset) begin if (reset = '1') then out_val=0; elsif(rising_edge(clk)) then case state is when out_1 => if done='1' then data_out <= addr0 & bits; counter <= counter + 1; data_in_d <= signed(data_in); if counter /= 0 then sum <= sum + data_in_d; else sum <= (others => '0'); avg <= std_logic_vector(sum(16 downto 5)); stage(1) <= avg(11 downto 0); for i in 2 to 4 loop stage(i) <= stage(i-1); end loop; -- subtract last stage from input sub_result <= resize(signed(avg),13) - signed(stage(4)); -- accumulate sum_new <= sum_new + sub_result; adc_a_out <= std_logic_vector(sum_new(16 downto 5)); end if; state <= out_2; endif; end process; - Altera_Forum
Honored Contributor
The principle is that sum width must not overflow so you are flexible here and depends on nature of your signal.
for 100 samples you can't divide easily (but you may just compare sum with sum without division). if you use 128 samples then you discard 7 bits from sum to divide it by 128. for 5 samples again you can't divide easily, make it 8 samples then discard 3 bits from sum - Altera_Forum
Honored Contributor
@kaz
Got the point. Thanks much. Another question: Why did we make the size of subtractor "sub_result" 13 bit? Can't we make it 11 bit? - Altera_Forum
Honored Contributor
--- Quote Start --- @kaz Another question: Why did we make the size of subtractor "sub_result" 13 bit? Can't we make it 11 bit? --- Quote End --- if data_in is + and last stage is - then both samples are added in effect requiring one more bit