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
Thanks for your answer above. Actually everything is working good for me. Now there are only two issues. The first approach that I used which is continuous averaging of example 256 samples. The ''adc_a_out'' value that I receive on my GUI increments slowly. As an example, if I am expecting value 100mA, My GUI shows 4mA, 8mA, 15mA,...... and then finally after 2 minutes I get stable 100mA value. I want to see the 100mA directly on my GUI from 'adc_a_out' instead of increment values and stabilizing after sometime. Another question is that, Can I somehow make this process fast so that I don't have to wait for 3 minutes for receiving stable 100 mA from adc_a_out. I am copying the code again that I used for testing. The clock 'clk' in the digital design below is 20 MHz. The clock for receiving ADC values on the FPGA board is 15 KHz.data_in : in std_logic_vector (31 downto 0); type type1 is array (1 to 255) 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 out_val=0; elsif(rising_edge(clk)) then case state is when out_1 => if done='1' then data_out <= addr0 & bits; stage(1) <= data_in(11 downto 0); for i in 2 to 255 loop stage(i) <= stage(i-1); end loop; -- subtract last stage from input sub_result <= resize(signed(data_in),13) - signed(stage(255)); -- accumulate sum <= sum + sub_result; adc_a_out <= std_logic_vector(sum(19 downto 8)); state <= out_2; endif; end process; - Altera_Forum
Honored Contributor
Your code looks ok. Delay of 2 minutes is too much on 15KHz ADC signal. Either your adc doesn't build up that fast or your state changes and doesn't track adc correctly
- Altera_Forum
Honored Contributor
@kaz
For getting the stable value directly instead of increasing slowly, I did the following change in the code (The change is only when reset = 1).
Do you think it is correct?data_in : in std_logic_vector (31 downto 0); type type1 is array (1 to 255) 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 out_val=0; stage <= (others => data_in(11 downto 0)); sum <= resize(255 * signed(data_in(11 downto 0)), sum'length); elsif(rising_edge(clk)) then case state is when out_1 => if done='1' then data_out <= addr0 & bits; stage(1) <= data_in(11 downto 0); for i in 2 to 255 loop stage(i) <= stage(i-1); end loop; -- subtract last stage from input sub_result <= resize(signed(data_in),13) - signed(stage(255)); -- accumulate sum <= sum + sub_result; adc_a_out <= std_logic_vector(sum(19 downto 8)); state <= out_2; endif; end process; - Altera_Forum
Honored Contributor
--- Quote Start --- @kaz For getting the stable value directly instead of increasing slowly, I did the following change in the code (The change is only when reset = 1). Do you think it is correct? --- Quote End --- That is naughty. You are faking the initial value of sum using 255*sum at reset. - Altera_Forum
Honored Contributor
--- Quote Start --- That is naughty. You are faking the initial value of sum using 255*sum at reset. --- Quote End --- What else should I do in order to achieve for example 100mA instead of 4 mA, 8 mA, 15 mA,.......100mA. I need stable value directly. What else can I do in the code? - Altera_Forum
Honored Contributor
--- Quote Start --- What else should I do in order to achieve for example 100mA instead of 4 mA, 8 mA, 15 mA,.......100mA. I need stable value directly. What else can I do in the code? --- Quote End --- your running average should work. Are you sampling eacg adc sample through it. What is that done = '1' for and do you stay in state out_1 enough to do the job. Your adc data rate of 15KHz should be averaged sooner unless it starts low. - Altera_Forum
Honored Contributor
@kaz
'done' is coming from the SPI master block indicating valid transfer. Yes I am sampling each adc sample through it. Also as I told you before there are two outputs of ADC. i-e 'adc_a_out' and 'adc_b_out' 12 bit each. In the end I do the 'and' of both of these outputs and I have 24 bit value of ADC and then send to GUI via USB interface. - Altera_Forum
Honored Contributor
--- Quote Start --- @kaz 'done' is coming from the SPI master block indicating valid transfer. Yes I am sampling each adc sample through it. Also as I told you before there are two outputs of ADC. i-e 'adc_a_out' and 'adc_b_out' 12 bit each. In the end I do the 'and' of both of these outputs and I have 24 bit value of ADC and then send to GUI via USB interface. --- Quote End --- I don't get it. Do you have one or two adc. if two independant adc then why you AND (or possibly you mean concatenate them) into 24 bit. The proper value of adc should enter the filter. If the two values are one adc sample then you should pass that into the filter. - Altera_Forum
Honored Contributor
@kaz
Yes I mean to concatenate them. I have two ADCs. Each ADC has two 12 bit inputs that captures the value. One ADC is for current measurement and the other for voltage measurement. The voltage measurement ADC is fine and I don't need filter for that. I need the filter for current measurement ADC. I concatenate the four outputs (two from first ADC and two outputs from second ADC) into 48 bits. I am doing the 'and' or concatenate on the top level. Then I am passing the concatenated value to the GUI via USB interface. - Altera_Forum
Honored Contributor
So they are two independent samples, each one from its own adc then why concatenate them as 24 bits value? what does this 24 bit value represent then?