усреднение 12-битных значений АЦП с использованием VHDL

У меня вопрос, связанный с непрерывным усреднением значения АЦП. Подход, который я использовал, заключается в непрерывном усреднении примеров из 256 образцов. Значение «adc_a_out» (показанное в приведенном ниже коде), которое я получаю в своем графическом интерфейсе, увеличивается медленно. Например, если я ожидаю значение 100 мА, мой графический интерфейс показывает 4 мА, 8 мА, 15 мА, ......, а затем, наконец, через 2 минуты я получаю стабильное значение 100 мА. Я хочу видеть 100 мА непосредственно в моем графическом интерфейсе из «adc_a_out» вместо увеличения значений и стабилизации через некоторое время. Другой вопрос, Можно ли как-то сделать этот процесс быстрым, чтобы не ждать 3 минуты получения стабильных 100 мА от adc_a_out. Тактовый щелчок в цифровом дизайне ниже составляет 20 МГц. Тактовая частота приема значений АЦП на плате FPGA составляет 15 кГц.

--adc_top_file.vhd

entity adc_block_1 is 
  port (
        clk      : in  std_logic;  
        reset    : in  std_logic;              

        data_in  : in  std_logic_vector (31 downto 0);
        req      : in  std_logic;
        adc_a_1    : inout std_logic_vector (11 downto 0);  
        adc_b_1    : inout std_logic_vector (11 downto 0); 
        slv_value1    : out std_logic_vector (11 downto 0);  
        slv_value2    : out std_logic_vector (11 downto 0);  

  );
end adc_block_1;

architecture adc_top_block of adc_block_1 is 

component adc is 
  port (
        clk      : in  std_logic;  
        reset    : in  std_logic;           

        data_in  : in  std_logic_vector (31 downto 0);
        req      : in  std_logic;
        adc_a_1    : inout std_logic_vector (11 downto 0);  
        adc_b_1    : inout std_logic_vector (11 downto 0);
        adc_a_1_temp: out signed(11 downto 0);
        adc_b_1_temp: out signed(11 downto 0);   
        slv_value1    : out std_logic_vector (11 downto 0);  
        slv_value2    : out std_logic_vector (11 downto 0);  

  );
end component;



component use_moving_average is

port (
        clock: in std_logic;
        reset: in std_logic;
        channel_1_sample: in signed(11 downto 0);
        channel
     data_in  : in  std_logic_vector (31 downto 0);
     adc_a_1 : inout std_logic_vector (11 downto 0);  
     adc_b_1 : inout std_logic_vector (11 downto 0);
     adc_a_1_temp: out signed(11 downto 0);
     adc_b_1_temp: out signed(11 downto 0); 
     load   : out std_logic;  

    process (clk, reset)

    begin
        if (reset = '1') then 
        state<=idle;
        adc_out1=0;
        adc_out2 <= 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;
        adc_a_1 <= data_in(11 downto 0);
        adc_a_1_temp <= signed(adc_a_1);

        state <= out_2;
        endif;

    when out_2 =>
       if done='1' then
       adc_b_1 <= data_in(11 downto 0);
       adc_b_1_temp <= signed(adc_b_1);

       state <= done_st;

    when done_st =>
        ack <='1';
        --load <='1';
        state <= idle;

    when others =>
        state <= idle;
        end case;
        end if;
        end process;

load: process (clk, reset)
  begin
    if (reset = '1') then
      load <= '0';
    elsif (rising_edge(clk)) then
        max_cnt <= 5000000;
        load <= '0';
      else
        max_cnt <= max_cnt -1;
        load <= '1';
    end if;
  end process load;
sample: in signed(11 downto 0); channel_1_average: inout signed(11 downto 0); channel
     data_in  : in  std_logic_vector (31 downto 0);
     adc_a_1 : inout std_logic_vector (11 downto 0);  
     adc_b_1 : inout std_logic_vector (11 downto 0);
     adc_a_1_temp: out signed(11 downto 0);
     adc_b_1_temp: out signed(11 downto 0); 
     load   : out std_logic;  

    process (clk, reset)

    begin
        if (reset = '1') then 
        state<=idle;
        adc_out1=0;
        adc_out2 <= 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;
        adc_a_1 <= data_in(11 downto 0);
        adc_a_1_temp <= signed(adc_a_1);

        state <= out_2;
        endif;

    when out_2 =>
       if done='1' then
       adc_b_1 <= data_in(11 downto 0);
       adc_b_1_temp <= signed(adc_b_1);

       state <= done_st;

    when done_st =>
        ack <='1';
        --load <='1';
        state <= idle;

    when others =>
        state <= idle;
        end case;
        end if;
        end process;

load: process (clk, reset)
  begin
    if (reset = '1') then
      load <= '0';
    elsif (rising_edge(clk)) then
        max_cnt <= 5000000;
        load <= '0';
      else
        max_cnt <= max_cnt -1;
        load <= '1';
    end if;
  end process load;
average: inout signed(11 downto 0); slv_value1 : out std_logic_vector (11 downto 0); slv_value2 : out std_logic_vector (11 downto 0) ); end component; signal adc_a_1_temp : std_logic_vector(11 downto 0); signal adc_b_1_temp : std_logic_vector(11 downto 0); signal adc_a_1_out : std_logic_vector(11 downto 0); signal adc_b_1_out : std_logic_vector(11 downto 0); begin inst_adc : adc port map ( clk => clk, reset => reset, req => adc_req, adc_a_1 => adc_a_1_temp, adc_b_1 => adc_b_1_temp, adc_a_1_temp => adc_a_1_temp, adc_b_1_temp => adc_b_1_temp ); inst_moving_average : use_moving_average port map ( clock => clk, reset => reset, channel_1_sample => adc_a_1_temp, channel
     data_in  : in  std_logic_vector (31 downto 0);
     adc_a_1 : inout std_logic_vector (11 downto 0);  
     adc_b_1 : inout std_logic_vector (11 downto 0);
     adc_a_1_temp: out signed(11 downto 0);
     adc_b_1_temp: out signed(11 downto 0); 
     load   : out std_logic;  

    process (clk, reset)

    begin
        if (reset = '1') then 
        state<=idle;
        adc_out1=0;
        adc_out2 <= 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;
        adc_a_1 <= data_in(11 downto 0);
        adc_a_1_temp <= signed(adc_a_1);

        state <= out_2;
        endif;

    when out_2 =>
       if done='1' then
       adc_b_1 <= data_in(11 downto 0);
       adc_b_1_temp <= signed(adc_b_1);

       state <= done_st;

    when done_st =>
        ack <='1';
        --load <='1';
        state <= idle;

    when others =>
        state <= idle;
        end case;
        end if;
        end process;

load: process (clk, reset)
  begin
    if (reset = '1') then
      load <= '0';
    elsif (rising_edge(clk)) then
        max_cnt <= 5000000;
        load <= '0';
      else
        max_cnt <= max_cnt -1;
        load <= '1';
    end if;
  end process load;
sample => adc_b_1_temp, channel_1_average => adc_a_1_out, channel
     data_in  : in  std_logic_vector (31 downto 0);
     adc_a_1 : inout std_logic_vector (11 downto 0);  
     adc_b_1 : inout std_logic_vector (11 downto 0);
     adc_a_1_temp: out signed(11 downto 0);
     adc_b_1_temp: out signed(11 downto 0); 
     load   : out std_logic;  

    process (clk, reset)

    begin
        if (reset = '1') then 
        state<=idle;
        adc_out1=0;
        adc_out2 <= 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;
        adc_a_1 <= data_in(11 downto 0);
        adc_a_1_temp <= signed(adc_a_1);

        state <= out_2;
        endif;

    when out_2 =>
       if done='1' then
       adc_b_1 <= data_in(11 downto 0);
       adc_b_1_temp <= signed(adc_b_1);

       state <= done_st;

    when done_st =>
        ack <='1';
        --load <='1';
        state <= idle;

    when others =>
        state <= idle;
        end case;
        end if;
        end process;

load: process (clk, reset)
  begin
    if (reset = '1') then
      load <= '0';
    elsif (rising_edge(clk)) then
        max_cnt <= 5000000;
        load <= '0';
      else
        max_cnt <= max_cnt -1;
        load <= '1';
    end if;
  end process load;
average => adc_b_1_out, slv_value1 => slv_value1, slv_value2 => slv_value2 );

-- файл adc.vhd находится ниже:

     data_in  : in  std_logic_vector (31 downto 0);
     adc_a_1 : inout std_logic_vector (11 downto 0);  
     adc_b_1 : inout std_logic_vector (11 downto 0);
     adc_a_1_temp: out signed(11 downto 0);
     adc_b_1_temp: out signed(11 downto 0); 
     load   : out std_logic;  

    process (clk, reset)

    begin
        if (reset = '1') then 
        state<=idle;
        adc_out1=0;
        adc_out2 <= 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;
        adc_a_1 <= data_in(11 downto 0);
        adc_a_1_temp <= signed(adc_a_1);

        state <= out_2;
        endif;

    when out_2 =>
       if done='1' then
       adc_b_1 <= data_in(11 downto 0);
       adc_b_1_temp <= signed(adc_b_1);

       state <= done_st;

    when done_st =>
        ack <='1';
        --load <='1';
        state <= idle;

    when others =>
        state <= idle;
        end case;
        end if;
        end process;

load: process (clk, reset)
  begin
    if (reset = '1') then
      load <= '0';
    elsif (rising_edge(clk)) then
        max_cnt <= 5000000;
        load <= '0';
      else
        max_cnt <= max_cnt -1;
        load <= '1';
    end if;
  end process load;

Ваш код изменен следующим образом:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity use_moving_average is
    port (
        clock: in std_logic;
        reset: in std_logic;
        channel_1_sample: in signed(11 downto 0);
        channel_2_sample: in signed(11 downto 0);
        channel_1_average: inout signed(11 downto 0);
        channel_2_average: inout signed(11 downto 0);
        slv_value1    : out std_logic_vector (11 downto 0);  
        slv_value2    : out std_logic_vector (11 downto 0)
    );
end;

architecture rtl of use_moving_average is
    signal average_1, average_2: integer;
begin

    channel_1: entity work.moving_average
        port map(
            sample  => to_integer(channel_1_sample),
            average => average_1,
            clock   => clock,
            reset   => reset
        );

    channel_2: entity work.moving_average
        port map(
            sample  => channel_2_sample,
            average => average_2,
            clock   => clock,
            reset   => reset
        );

    channel_1_average <= to_signed(average_1, 12);
    slv_value1 <= std_logic_vector(channel_1_average);
    channel_2_average <= to_signed(average_2, 12);
    slv_value2 <= std_logic_vector(channel_2_average);
end;

Окончательный вывод, который я просматриваю в своем графическом интерфейсе, - это «slv_value1» и «slv_value2».

Спасибо!


person user3008991    schedule 26.11.2013    source источник


Ответы (1)


Как насчет этого: при сбросе (или в любое другое время, если хотите) присвойте значение data_in всем элементам в вашем массиве stage. Это должно мгновенно установить ваше среднее значение на текущее значение:

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
        ...

В приведенном ниже примере показан полный код калькулятора скользящего среднего. Я предлагаю вам изучить его, пока вы не поймете его. Затем попробуйте использовать его в своем дизайне. Наконец, и только после того, как базовая схема заработала, вы можете изменить ее в соответствии с вашими проектными ограничениями (ширина данных, количество выборок, диапазон целых чисел, использование signed против integer и т. д.).

library ieee;
use ieee.std_logic_1164.all;

entity moving_average is
    generic(
        SAMPLES_COUNT: integer := 256
    );
    port (
        sample: in integer;
        average: out integer;
        clock: in std_logic;
        reset: in std_logic
    );
end;

architecture rtl of moving_average is

    signal samples_fifo: integer_vector(1 to SAMPLES_COUNT);
    signal sum: integer;

begin

    process (clock, reset) begin
        if reset then
            samples_fifo <= (others => sample);
            sum <= SAMPLES_COUNT * sample;
        elsif rising_edge(clock) then
            samples_fifo <= sample & samples_fifo(1 to SAMPLES_COUNT-1);
            sum <= sum + sample - samples_fifo(SAMPLES_COUNT);
        end if;
    end process;

    average <= sum / SAMPLES_COUNT;
end;

Наконец, если вы хотите использовать приведенный выше код для хранения двух отдельных средних значений для двух разных сигналов, просто дважды создайте экземпляр объекта усреднения:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity use_moving_average is
    port (
        clock: in std_logic;
        reset: in std_logic;
        channel_1_sample: in signed(11 downto 0);
        channel_2_sample: in signed(11 downto 0);
        channel_1_average: out signed(11 downto 0);
        channel_2_average: out signed(11 downto 0)
    );
end;

architecture rtl of use_moving_average is
    signal average_1, average_2: integer;
begin

    channel_1: entity work.moving_average
        port map(
            sample  => to_integer(channel_1_sample),
            average => average_1,
            clock   => clock,
            reset   => reset
        );

    channel_2: entity work.moving_average
        port map(
            sample  => channel_2_sample,
            average => average_2,
            clock   => clock,
            reset   => reset
        );

    channel_1_average <= to_signed(average_1, 12);
    channel_2_average <= to_signed(average_2, 12);
end;

Редактировать. Как я понял из ваших комментариев, вам может понадобиться дополнительный ввод, чтобы мгновенно установить среднее значение в соответствии с текущим входным значением. В этом случае вы можете использовать вход load, как показано ниже:

library ieee;
use ieee.std_logic_1164.all;

entity moving_average is
    generic(
        SAMPLES_COUNT: integer := 256
    );
    port (
        sample: in integer;
        average: out integer;
        clock: in std_logic;
        reset: in std_logic;
        load: in std_logic
    );
end;

architecture rtl of moving_average is

    signal samples_fifo: integer_vector(1 to SAMPLES_COUNT);
    signal sum: integer;

begin

    process (clock, reset) begin
        if reset then
            samples_fifo <= (others => sample);
            sum <= SAMPLES_COUNT * sample;
        elsif rising_edge(clock) then
            if load then
                samples_fifo <= (others => sample);
                sum <= SAMPLES_COUNT * sample;
            else
                samples_fifo <= sample & samples_fifo(1 to SAMPLES_COUNT-1);
                sum <= sum + sample - samples_fifo(SAMPLES_COUNT);
            end if;
        end if;
    end process;

    average <= sum / SAMPLES_COUNT;
end;
person rick    schedule 26.11.2013
comment
Сейчас я проверю результат на fpga и сообщу вам. Это также ускорит процесс? Я имею в виду, получу ли я значение быстро, потому что я получаю стабильное значение, например 100 мА, через 2 минуты, используя приведенный выше код. - person user3008991; 26.11.2013
comment
С приведенным выше кодом я получаю следующую ошибку: Ошибка (10327): ошибка VHDL в adc.vhd (103): не удается определить определение оператора * - найдено 0 возможных определений - person user3008991; 26.11.2013
comment
Вы пытались включить use ieee.numeric_std.all;? - person rick; 26.11.2013
comment
Да, я сделал, и я получил вышеуказанную ошибку. Я включил следующие библиотеки: библиотека ieee; используйте ieee.std_logic_1164.all; используйте ieee.std_logic_unsigned.all; используйте ieee.numeric_std.all; - person user3008991; 26.11.2013
comment
Теперь я получаю другую ошибку: Error (10344): VHDL expression error at adc.vhd(103): expression has 24 elements, but must have 20 elements речь идет о следующей строке: sum <= 255 * signed(data_in(11 downto 0)); - person user3008991; 26.11.2013
comment
Если сейчас я увеличу sum с 20 бит до 24 бит, то как мне получить требуемое значение adc: adc_a_out <= std_logic_vector(sum(19 downto 8)); - person user3008991; 26.11.2013
comment
Да, вы будете видеть такую ​​ошибку до тех пор, пока не определите точный размер ваших сигналов. Это то, что можете сделать только вы, зная, что вы хотите сохранить в каждом сигнале. Вы можете попытаться изменить размер результата с помощью sum <= resize(255 * signed(data_in(11 downto 0)), sum'length);, но только вы можете сказать, правильно ли это. - person rick; 26.11.2013
comment
это не работает для меня. Я все еще получаю тот же результат. Мой графический интерфейс показывает 4 мА, 8 мА, 15 мА, ...... и, наконец, через 2 минуты я получаю стабильное значение 100 мА. - person user3008991; 26.11.2013
comment
Я не могу опубликовать полный код, так как он очень длинный. Я добавил больше деталей в приведенный выше код с некоторыми пояснениями. Пожалуйста, дайте мне знать, если это все еще неясно - person user3008991; 26.11.2013
comment
Я добавил в ответ полный код для расчета скользящей средней. Вероятно, это проще, чем вы думаете. - person rick; 26.11.2013
comment
Я отредактировал свой код выше без усреднения выходных значений АЦП. Можете ли вы сказать мне, как я могу усреднить параллельные значения «adc_out1» и «adc_out2». Я хочу непрерывно усреднять 256 выборок каждого из этих выходов параллельно. Теперь вы можете объединить свой код с моим? - person user3008991; 26.11.2013
comment
Я не понимаю, зачем вам нужны два выходных значения. Если у вас есть два независимых значения ADC и вы хотите рассчитать два отдельных средних значения, просто создайте два экземпляра моего примера кода. В любом случае, я отредактировал ответ, включив в него пример, который усредняет два канала АЦП независимо друг от друга. - person rick; 27.11.2013
comment
Если я не ошибаюсь, я должен сделать то, что сделал выше. Я снова отредактировал свой код. Только одно, где и как я могу преобразовать свой сигнал std_logic_vector 'adc_a_1_out' в подписанный (11 до 0)? - person user3008991; 27.11.2013
comment
В вашем случае лучше избегать использования std_logic_vector и использовать signed везде, где это возможно. В любом случае, чтобы преобразовать сигнал с именем signed_value (типа signed) в сигнал с именем slv_value (типа std_logic_vector ), необходимо написать: slv_value <= std_logic_vector(signed_value);. Это называется приведением типов. - person rick; 27.11.2013
comment
Можете ли вы сказать, что такое integer_vector в вашем коде скользящего среднего. Как это будет объявлено? - person user3008991; 27.11.2013
comment
Для integer_vector включите VHDL-2008. - person user_1818839; 27.11.2013
comment
Я определил это как: тип integer_vector — это массив (от 0 до 255) целых чисел; но это не сработало в приведенном выше коде. Пожалуйста, скажите мне, что плохого в таком заявлении. - person user3008991; 27.11.2013
comment
Первый вариант — включить поддержку VHDL-2008 в вашем компиляторе. Кроме этого, попробуйте type integer_vector is array (natural range <>) of integer;. Кроме того, если что-то не работает в коде, пожалуйста, опишите сообщение об ошибке, которое вы видите. - person rick; 27.11.2013
comment
Я пытался с type integer_vector is array (0 to 255) of integer;, но это не сработало. Я получаю следующую ошибку: Error (10457): VHDL Subtype Declaration error at moving_average.vhd(18): subtype for constrained integer_vector type cannot have range - person user3008991; 27.11.2013
comment
Попробуйте type integer_vector is array (natural range <>) of integer; - person rick; 27.11.2013
comment
Это сработало для меня. Код работает сейчас. Я также вижу быстрые результаты. Проблема в том, что я не получаю правильные значения. Я разместил полный код выше в своем первом сообщении. Можете ли вы сказать мне, если я делаю что-то не так - person user3008991; 27.11.2013
comment
Я изменил ваши усредненные результаты на inout для преобразования. Пожалуйста, проверьте мой обновленный код выше с вашим кодом, если он вам кажется правильным? - person user3008991; 27.11.2013
comment
Я не буду менять код в объекте moving_average, лучше сделать преобразования в вашем файле верхнего уровня. Что касается того, почему результаты неверны, вам нужно показать результаты, которые вы получаете. Картинка с симуляционными осциллограммами была бы хороша. - person rick; 27.11.2013
comment
Я проверил результаты на ПЛИС. Я еще не делал симуляцию. Я сделаю это и дам вам знать, если в этом что-то не так. Но было ли что-то не так в приведенном выше коде? - person user3008991; 27.11.2013
comment
Ничего, что выглядит явно неправильным. Но постарайтесь выработать привычку проводить симуляции перед тестированием проекта на ПЛИС, на симуляторе гораздо проще отлавливать ошибки. - person rick; 27.11.2013
comment
@rick Я проверил в симуляции и обнаружил проблему с проводкой. Я починил это. Теперь проблема только в стабилизации. Значения после среднего блока не стабильны. В нем есть вариант 80мА. Можно ли уменьшить вариацию и получить стабильное значение после фильтра? - person user3008991; 04.12.2013
comment
Каков диапазон ваших входных значений? (максимальное значение/минимальное значение в мА) И какова шкала ваших значений АЦП? Всегда можно сделать вывод более стабильным, но это будет стоить вам более медленного времени отклика. - person rick; 04.12.2013
comment
@rick Если я установлю значение ЦАП на 1 В, мой диапазон АЦП будет между 80 мА и 140 мА. Когда я устанавливаю значение 1,2 В, мой диапазон АЦП составляет от 140 мА до 190 мА. Можете ли вы сказать мне здесь, в этом коде, как я могу сделать свои значения стабильными? - person user3008991; 05.12.2013
comment
Если вы сохранили свой код действительно общим, вам просто нужно увеличить значение SAMPLES_COUNT. Если вы используете 256, попробуйте 512 или 1024 и посмотрите, что произойдет. - person rick; 05.12.2013
comment
Я пробовал с 512, но все еще были вариации. Не было большой разницы, когда я перешел с 256 на 512. Любые другие предложения? - person user3008991; 05.12.2013
comment
Продолжайте удваивать значение, пока не заметите разницу. Насколько я понимаю, вы получаете новое значение АЦП каждые 1/15 000 секунд. Это означает, что вам, возможно, придется использовать очень большое значение количества выборок. Другой вариант — отбросить младшие значащие биты, считанные с вашего АЦП (т. е. использовать только 10 или 8 бит вместо 12). - person rick; 05.12.2013
comment
Я проверяю с 1024 сейчас. Я дам вам знать, если есть разница. Можете ли вы сказать мне, как я могу использовать только 8 или 10 бит вместо 12 бит в моем коде выше. Вы хотите сделать следующее: channel_1_average <= to_signed(average_1, 10); channel_2_average <= to_signed(average_2, 10); - person user3008991; 05.12.2013
comment
Я бы сказал, что везде, где вы используете data_in(11 downto 0), попробуйте вместо этого использовать data_in(11 downto 2) & "00". - person rick; 05.12.2013
comment
Я тоже пробовал с 1024, но все равно особой разницы нет. Также я изменил data_in(11 downto 0) на data_in(11 downto 2) & "00" и даже изменил data_in(11 downto 0) на data_in(11 downto 4) & "0000", но разницы нет вообще. - person user3008991; 05.12.2013
comment
@rick есть ли у вас какие-либо другие идеи, что можно сделать, чтобы сделать вывод стабильным? - person user3008991; 05.12.2013
comment
Значит, в вашем дизайне есть что-то, чего вы не до конца понимаете. Рекомендую пройтись по ней досконально и нарисовать схему. Я также рекомендую исключить компонент use_moving_average и перенести его функциональность на adc_block_1. Также подумайте об этом: если АЦП выдает новое значение каждые 1/15 000 секунды, то для устранения влияния последней из 15 000 выборок требуется 1 секунда. Поскольку вы используете только 1024, вы не видите большой разницы, потому что любой образец забывается уже через 68 миллисекунд. Попробуйте увеличить SAMPLES_COUNT до 16 384, если сможете. - person rick; 05.12.2013
comment
@rick Можете ли вы сказать мне, можно ли включить функциональность фильтра в блоке adc.vhd вместо adc_block_1? Как включить функциональность в блок adc_block_1.vhd? - person user3008991; 05.12.2013
comment
Да, но, возможно, вы не хотите этого делать, потому что у них разные цели. Хорошо, что вы держите модуль усреднения отдельно. И, честно говоря, я не понимаю цели вашего модуля adc. Вероятно, вам следует выбрать для него более описательное имя. И последняя рекомендация: старайтесь называть каждый файл именем объекта, который он описывает. Например, для entity moving_average сохраните его в файле с именем moving_average.vhd. - person rick; 05.12.2013
comment
Сладкий! Возможно, тогда вы могли бы обновить код в своем сообщении, потому что он показывает entity adc_block_1 в файле adc_top_file.vhd - person rick; 05.12.2013
comment
@rick Я понял, что мой средний блок вообще не работал, потому что я запускал его на частоте 20 МГц, а сигнал готовности, поступающий от блока SPI, работает на частоте 78 кГц, что означает, что я получаю следующие данные после каждых 78 кГц. Теперь я запускаю свой средний блок на CS (78 кГц), поступающем от spi master, вместо обычных часов 20 МГц. Теперь я получаю результат, например, 10 мА, 20 мА, 40 мА, ...... 100 мА, и после этого значение становится стабильным. Я хочу 100 мА напрямую. Можете ли вы сейчас сказать мне, как это возможно сделать? Должен ли я дополнительно уменьшать средний блок для этого? - person user3008991; 06.12.2013
comment
Получить мгновенное обновление среднего значения очень просто. Один из вариантов — послать объекту moving_average импульс сброса. Другой вариант — добавить дополнительный сигнал (скажем, load) и изменить архитектуру для выполнения тех же двух операторов (samples_fifo <= (others => sample); sum <= SAMPLES_COUNT * sample;), когда утверждается load. - person rick; 07.12.2013
comment
@rick Я не могу сейчас это проверить. В понедельник проверю и сообщу. Но не могли бы вы сказать мне, где добавить дополнительный сигнал «загрузки» в моем коде? Также как и в какой момент отправить импульс сброса объекту moving_average? Можете ли вы показать мне в вашем коде? Спасибо - person user3008991; 07.12.2013
comment
@rick Можете ли вы сказать, где добавить дополнительный сигнал «загрузки» в моем коде? Также как и в какой момент отправить импульс сброса объекту moving_average? Можете ли вы показать мне в вашем коде? Я проверю это завтра. Благодарность - person user3008991; 09.12.2013
comment
Я обновил свой ответ, включив в него ввод load. В вашем случае вы можете начать с подключения сигнала загрузки к кнопке на вашей плате, чтобы убедиться, что она работает должным образом. - person rick; 09.12.2013
comment
@rick, можете ли вы также сказать мне, как отправить импульс сброса в объект moving_average в коде? - person user3008991; 09.12.2013
comment
Ваша схема должна иметь сигнал сброса. Общепринятой практикой является подключение всех регистров к одному и тому же сигналу. - person rick; 09.12.2013
comment
@rick В какой момент я должен сделать сигнал «загрузки» равным «1»? - person user3008991; 09.12.2013
comment
В тот момент, когда вы хотите, чтобы ваш вывод немедленно переходил к текущему значению АЦП. Можете ли вы просто подключить его к кнопке или переключателю и сделать это вручную, по крайней мере, пока? - person rick; 09.12.2013
comment
@rick Хорошо, я проверю это. Другой вопрос касается сигнала сброса сущности moving_average. я немного смущен. Сигнал сброса уже подключен к моему блоку сущностей moving_average. Скажите, чего не хватает в коде? - person user3008991; 09.12.2013
comment
Похоже, вы подключили все порты сброса к одному и тому же сигналу, так что все должно быть в порядке. Использование другого сброса для блока moving_average было просто предложением на тот случай, если вы не хотите менять код этой сущности, но теперь, когда вы добавили порт load, вам не нужно трогать его сброс. - person rick; 09.12.2013
comment
@rick Плата не была бесплатной, но я проверю этот сигнал загрузки и включу его, но просто для уточнения и для тестирования я делаю «load = 1» в файле adc.vhd в состоянии done_st. Я прав? Я также изменил файл adc.vhd в своем сообщении выше. - person user3008991; 09.12.2013
comment
@rick Пожалуйста, дайте мне знать, правильно ли я поставил load = 1 в своем коде? - person user3008991; 09.12.2013
comment
Прочитайте в коде, что произойдет, если оставить load и постоянное значение 1. Вы придете к выводу, что усредняющая часть алгоритма никогда не будет выполнена. Ваш load должен быть коротким импульсом, как нажатие кнопки, иначе усреднение не сработает. - person rick; 09.12.2013
comment
@rick Я проверил это, и с вышеуказанной модификацией, которую я сделал, мой средний блок не работает, и я получаю старые значения с вариациями. Можете ли вы сказать мне, в какой момент в моем коде я могу сделать load=1 и load=0? - person user3008991; 09.12.2013
comment
@rick Я подал сигнал нагрузки на переключатель на плате, проверил его вручную, и он работает. Я получаю значение АЦП. Можете ли вы сказать мне сейчас, где я могу сделать load=0 и load=1 в моем коде? - person user3008991; 09.12.2013
comment
Самым простым решением было бы соединить load с reset, но вам нужно проверить, будет ли это работать для вас. В противном случае вы могли бы реализовать счетчик, чтобы через (например) полсекунды он генерировал импульс, который вы бы подключили к порту load. - person rick; 09.12.2013
comment
Нет проблем, рад быть полезным. Если вы считаете, что ответ был полезен, не могли бы вы щелкнуть галочку рядом с ним и отметить его как принятый ответ? - person rick; 10.12.2013