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
@tricky
Sorry that was a mistake. You are right. I mean ('0' & data_in(11 downto 0); Sorry for the confusion. Can you tell me why I am not getting correct ADC values? I used the approach that was given to me in the previous comment by @kaz - Altera_Forum
Honored Contributor
If the direct ADC values are incorrect, isnt this something for you to Debug? it would be easy to test this code does a rolling average in a simple testbench (you just pass a set of known values into the data_in port) so you can ensure this works before debugging any upstream problems.
- Altera_Forum
Honored Contributor
--- Quote Start --- @tricky Sorry that was a mistake. You are right. I mean ('0' & data_in(11 downto 0); Sorry for the confusion. Can you tell me why I am not getting correct ADC values? I used the approach that was given to me in the previous comment by @kaz --- Quote End --- you should not put '0' unless it is unsigned but your computation is signed. This will give wrong results. if your data is 12 bits then use less bits(subtractor needs 13 bits, sum needs 18 bits). you are wasting double resource for two cases. You can use one computation section for both switching between them at input to delay section. setting data type to signed at delay stages as Tricky suggested is an option but I believe doesn't make life any easier. - Altera_Forum
Honored Contributor
An alternative is to use an 'infinite response filter' instead of a true average. This gives more weight to recent data, but is easier to calculate since it doesn't require all the old values be stored.
Basically calculate 'new_irf = old_irf * 31/32 + sample'. - Altera_Forum
Honored Contributor
@kaz
If I dont put '0', I get the following error. Should I reduce subtractor bits? Error (10344): VHDL expression error at adc_cntrl.vhd(160): expression has 12 elements, but must have 13 elements. Can you tell me how can I use one computation section for both switching between them at input to delay section? Can you modify my code? Many Thanks - Altera_Forum
Honored Contributor
@dsl
Can you modify my code with your approach? - Altera_Forum
Honored Contributor
--- Quote Start --- @kaz If I dont put '0', I get the following error. Should I reduce subtractor bits? Error (10344): VHDL expression error at adc_cntrl.vhd(160): expression has 12 elements, but must have 13 elements. --- Quote End --- sub_result <= resize(signed(data_in),13) - signed(stage(31)); if you are not averaging both ADC data in parallel then you can switch between them at signal stage:if avg_1 then stage(1) <= adc1; elsif avg_2 then stage(1) <= adc2; end if; - Altera_Forum
Honored Contributor
--- Quote Start --- An alternative is to use an 'infinite response filter' instead of a true average. This gives more weight to recent data, but is easier to calculate since it doesn't require all the old values be stored. Basically calculate 'new_irf = old_irf * 31/32 + sample'. --- Quote End --- you are using an integrator of equation: y(n) = 31/32*y(n-1) + x(n); This has a different response from running average filter and is not functionally equivalent. The post is focused on running average. If it is ok then why not just use: y(n) = y(n-1) + x(n) i.e. just an accumulator: sum <= sum + data_in; - Altera_Forum
Honored Contributor
@kaz
What if I want to converge to a single value with continuous averaging? Is it possible? As an example if I average first 32 samples and the averaged value used in the next averaged 32 samples. In the end I will converge to some stable ADC value. In this way I will have less fluctuation in my ADC values. - Altera_Forum
Honored Contributor
@kaz
I am averaging both the adc data in parallel. That is why I used 2 computations.