Странное поведение в VHDL - PullRequest
0 голосов
/ 27 мая 2018

Я пытаюсь интегрировать (суммировать) 14-битный сигнал АЦП на частоте 50 МГц.Интеграция начинается с нарастающего фронта сигнала «триггер».Если интеграл достигает определенного порога (6000000), цифровой сигнал («dout») должен быть установлен в 0 (который стал 1 с «триггером», становящимся 1).Пока задача довольно легкая.Хотя на самом оборудовании (Cyclone V) я понял странное поведение.Хотя я держал уровень напряжения на постоянном АЦП, ширина импульса выходного сигнала «dout» иногда колеблется (хотя он должен оставаться почти постоянным для постоянного 14-разрядного значения на АЦП, который имеет низкий уровень шума).Ширина импульса уменьшается с ростом уровня напряжения, поэтому сама интеграция работает нормально.Но он продолжает колебаться.

Вот мой код:

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

entity integrator is
port(
  trigger:  in std_logic;
  adc:  in std_logic_vector(13 downto 0);
  clk:  in std_logic;
  dout: out std_logic);
end integrator ;

architecture rtl of integrator is
  signal sum : integer;
begin
  process(clk) is
  begin     
        if rising_edge(clk) then                
            if (trigger='1') and (sum<6000000) then
                sum<=sum+to_integer(unsigned(adc));
                dout<='1';
            else
                dout<='0';
                if (trigger='0') then
                    sum<=0;
                end if;
            end if;
        end if;
  end process;
end rtl;

Я проверил сигналы, используя SignalTab II от Quartus Prime.Я понял, что значение «сумма» растет, но не совсем правильно (по сравнению с суммой, которую я вычислил вручную по значениям «АЦП».

Я использовал ФАПЧ для сдвига фазы тактового сигнала 50 МГц ("clk ") около 90 градусов. Полученные часы послужили входом для тактовых импульсов АЦП. Я пропустил ФАПЧ и значение" сумма "совпало. Тем не менее я вижу колебания в сигнале" dout "(осциллограф).

Еще более странно: я изменил тип "суммы" на unsigned и, наконец, флуктуации исчезли. Но только без использования PLL! Но при внесении изменений в код ниже флуктуации вернулись. Может быть, сумма целых и беззнаковых этилированныхв другое время?!?

Теперь возникают вопросы: - Почему значение «сумма» является неправильным при использовании PLL (хотя значение «adc» должно оставаться постоянным в течение половины такта при сдвиге фазы90 градусов)? - Почему я вижу колебания в "dout"? Что-то не так с кодом?

EDIT1: Добавить testbench

Вот мой тестовый стенд:

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

entity testbench is
end testbench; 

architecture tb of testbench is


component integrator is
port(
  trigger:  in std_logic;
  adc:  in std_logic_vector(13 downto 0);
  clk:  in std_logic;
  dout: out std_logic);
end component;


signal trigger_in, clk_in, dout_out: std_logic;
signal adc_in:  std_logic_vector(13 downto 0);
begin

  DUT: integrator port map(trigger_in, adc_in, clk_in, dout_out);

  process
  begin
    for I in 1 to 4500 loop
      clk_in <= '0';
      wait for 10 ns;
      clk_in <= '1';
      wait for 10 ns;
    end loop; 
    wait;
  end process;

  process
  begin
      trigger_in <= '0';
      wait for 10 us;
      trigger_in <= '1';
      wait for 30 us;
      trigger_in <= '0';
      wait for 10 us;
      trigger_in <= '1';
      wait for 30 us;
      trigger_in <= '0';
      wait for 10 us;
      wait;
  end process;

  process
  begin
      adc_in <= (others => '0');
      wait for 10 us;
      adc_in <= std_logic_vector(to_unsigned(6000, 14));
      wait for 30 us;
      adc_in <= (others => '0');
      wait for 10 us;
      adc_in <= std_logic_vector(to_unsigned(6000, 14));
      wait for 30 us;
      adc_in <= (others => '0');
      wait for 10 us;
      wait;
  end process;


end tb;

И полученный результат: Simultation output

Ответы [ 3 ]

0 голосов
/ 05 июня 2018

спасибо за все ответы.Это помогло мне продвинуться немного дальше.Я проверил сигнал АЦП, но есть только шум около 10 (из 14 бит) и никаких неожиданных значений.Кроме того, все остальные сигналы (пробные без логики) в порядке.

Я также нашел решение для непоследовательного поведения суммы.Я просто сохранил его в temp_adc перед вычислениями.Я пробовал переменную и сигнал, но я иду с сигналом, потому что я могу визуализировать его в SignalTap (конечно, теперь есть задержка в один тактовый цикл):

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

entity integrator is
port(
  trigger:  in std_logic;
  adc:  in std_logic_vector(13 downto 0);
  clk:  in std_logic;
  dout: out std_logic);
end integrator ;

architecture rtl of integrator is
  signal sum : integer;
  signal temp_adc : unsigned(13 downto 0);
begin
  process(clk) is
  begin     
        temp_adc<=unsigned(adc);
        if rising_edge(clk) then                
            if (trigger='1') and (sum<6000000) then
                sum<=sum+to_integer(tem_adc);
                dout<='1';
            else
                dout<='0';
                if (trigger='0') then
                    sum<=0;
                end if;
            end if;
        end if;
  end process;
end rtl;

В SignalTap теперь он хорошо подходит (sum =sum + temp_adc) большую часть времени.Возвращаясь к проблеме: я нашел способ в SignalTap вызывать неожиданные события.Я обнаружил одно очень странное поведение:

Позволяет t = 0 быть циклом, в котором trigger идет '1'.Выходные данные выглядят так:

simulation

Это означает, что dout просто идет '1' в течение одного такта из-за высокого значения в sum.Это происходит случайно, но примерно с каждым 300-м импульсом.Похоже, что-то вроде переполнения с одним adc, добавленным к sum.У вас есть идеи, откуда это взялось?

Кроме того, я поиграл с PLL для часов АЦП.Я пробовал разные фазовые сдвиги (0 °, 90 °, 180 °), но результат более или менее одинаков.

0 голосов
/ 12 июня 2018

Простите, ребята.Проблема была в неверно сконфигурированном проекте Quartus с ошибкой

0 голосов
/ 28 мая 2018

Я попросил тестовый стенд, потому что ваш код выглядит немного странно.Так же, как user1155120, я заметил, что суммирование происходит вне любого условия, которое может вызвать переполнение.Вы не видите этого переполнения, потому что вы не тестируете его в своем тестовом стенде.

Я могу предложить изменить код, но проблема заключается в спецификации:

Если интеграл достигает определенного порога (6000000), ...

Вы не указываете, что должна делать сумма в этом случае.Продолжить?Держать?Если вы позволите этому продолжаться, он в какой-то момент изменится и станет отрицательным.

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

if sum<some_maximum_value_you_define then
   sum<=sum+to_integer(unsigned(adc));
end if;

Возможное максимальное значение будет 2 31 -2 * 1 016 * 14 -1.

В качестве альтернативы вы должны убедиться, что trigger_in происходит достаточно быстро, чтобы сумма никогда не переполнялась.С частотой дискретизации 50 МГц и 14-битным АЦП, что означает, по крайней мере, 382 Гц.


Я бы добавил код VHDL для проверки сигнала АЦП.например, максимальные и минимальные значения.Сравните их с фактическим (более или менее постоянным) входным значением.Это может дать вам представление о стабильности / надежности выборки.

...