- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
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,
Lien copié
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
check your count becomes zero
check avg- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
--- 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?
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
The samples should end up in a memory block - with read and write pointers.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
--- 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?
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
--- 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.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
@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: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;
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.
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;
Is the number of bits for sum and sum assignment to avg is correct?
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
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- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
@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?- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
--- 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
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
@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;
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
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
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
@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).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;
Do you think it is correct?
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
--- 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.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
--- 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?
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
--- 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.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
@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.- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
--- 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.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
@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.- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
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?
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
I updated the previous post. I am posting it again.
@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. These 48 bits value represents the Current and voltage.- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
"I have two ADCs, each ADC has 12 bit inputs (you mean outputs)"
"two outputs from first ADC..."??? what is the sample width of your current ADC? is it 12 bits or 24 bits?
- S'abonner au fil RSS
- Marquer le sujet comme nouveau
- Marquer le sujet comme lu
- Placer ce Sujet en tête de liste pour l'utilisateur actuel
- Marquer
- S'abonner
- Page imprimable