Конечный автомат процесса VHDL 2 и инициализация вывода

Таким образом, Altera предоставляет пример конечного автомата с двумя процессами по этой ссылке.

Мне нравится этот стиль, но я не понимаю, что если «вход» остается равным «0», второй процесс никогда не запускается, поскольку состояние никогда не меняется, и поэтому «выход» никогда не назначается и не инициализируется... Или это ?

Насколько я понимаю, должен быть переход на один из сигналов списка чувствительности (в данном примере «состояние»), который здесь никогда не может произойти.

Может кто-нибудь прояснить, в чем здесь дело?

Вот код:

ENTITY state_machine IS
   PORT(
      clk      : IN   STD_LOGIC;
      input    : IN   STD_LOGIC;
      reset    : IN   STD_LOGIC;
      output   : OUT  STD_LOGIC_VECTOR(1 downto 0));
END state_machine;
ARCHITECTURE a OF state_machine IS
   TYPE STATE_TYPE IS (s0, s1, s2);
   SIGNAL state   : STATE_TYPE;
BEGIN
   PROCESS (clk, reset)
   BEGIN
      IF reset = '1' THEN
         state <= s0;
      ELSIF (clk'EVENT AND clk = '1') THEN
         CASE state IS
            WHEN s0=>
               IF input = '1' THEN
                  state <= s1;
               ELSE
                  state <= s0;
               END IF;
            WHEN s1=>
               IF input = '1' THEN
                  state <= s2;
               ELSE
                  state <= s1;
               END IF;
            WHEN s2=>
               IF input = '1' THEN
                  state <= s0;
               ELSE
                  state <= s2;
               END IF;
         END CASE;
      END IF;
   END PROCESS;

   PROCESS (state)
   BEGIN
      CASE state IS
         WHEN s0 =>
            output <= "00";
         WHEN s1 =>
            output <= "01";
         WHEN s2 =>
            output <= "10";
      END CASE;
   END PROCESS;

END a;

EDIT: Просто чтобы уточнить, мой вопрос: мне кажется, что «выход» будет в неопределенном состоянии, пока «вход» не перейдет в «1». Разве это не плохая практика, учитывая, что это официальный пример от Altera? И, кстати, как здесь правильно инициализировать «выход»? С асинхронным сбросом?


person Ril Dank    schedule 19.06.2017    source источник
comment
Каждый процесс будет выполняться до тех пор, пока не будет приостановлен во время инициализации (IEEE Std 1076-2008 14.7.5.2 Initialization). Начальное значение state будет равно s0 независимо от сброса (14.4 Разработка декларативной части, 14.4.2.5 Объявления объектов, 6.4.2.3 Объявления сигналов). Во время инициализации присвоение output запланирует обновление значения на 00 в момент времени 0. В первом цикле моделирования изменение действующего значения с UU на 00 вызовет событие на output. (14.7.3.2 Управляющие значения, 14.7.3.3 Действующие значения, 14.7.3.4 Обновление сигнала, 14.7.5.3 Цикл моделирования).   -  person    schedule 20.06.2017
comment
пользователь 1155120 прав. Хотя для полноты кода (т. е. сделать код более читабельным) я бы написал SIGNAL state : STATE_TYPE := s0;   -  person JHBonarius    schedule 20.06.2017


Ответы (1)


... мне кажется, что «выход» будет в неопределенном состоянии, пока «вход» не перейдет в «1».

Нет (см. ниже). В начале симуляции output сразу примет значение "00", даже если не установлен сброс и нет перехода на input.

Разве это не плохая практика, учитывая, что это официальный пример от Altera?

Нет, этот код подходит. Регистр состояния (state) может быть правильно инициализирован благодаря сбросу, а output комбинаторно зависит от state. Эта модель будет вести себя так, как ожидается, как в симуляции, так и в аппаратном обеспечении.

И, кстати, как здесь правильно инициализировать «выход»? С асинхронным сбросом?

Вы не инициализируете выходные данные комбинаторики с помощью сброса. Сбросы (асинхронные или синхронные) используются для инициализации регистров (в вашем примере state).

Списки конфиденциальности — это просто синтаксический сахар. Процесс со списком конфиденциальности эквивалентен тому же процессу без списка конфиденциальности и с wait on <sensitivity-list>; в качестве последнего оператора. Пример:

PROCESS (state)
BEGIN
  CASE state IS
     WHEN s0 =>
        output <= "00";
     WHEN s1 =>
        output <= "01";
     WHEN s2 =>
        output <= "10";
  END CASE;
END PROCESS;

эквивалентно:

PROCESS
BEGIN
  CASE state IS
     WHEN s0 =>
        output <= "00";
     WHEN s1 =>
        output <= "01";
     WHEN s2 =>
        output <= "10";
  END CASE;
  WAIT ON state;
END PROCESS;

Итак, этот процесс запускается (как и все процессы) в начале симуляции и присваивает значение output. В вашем конкретном случае это значение будет "00", потому что начальное значение state является самым левым значением его перечисляемого типа, то есть s0. В общем, output инициализируется значением "UU" (U — самое левое значение перечисляемого типа std_logic) и после самого первого шага симуляции (при T=0) принимает значение "00".

Примечание: этот код в порядке и является хорошим представителем кодирования для конечного автомата Мура (не Мили, как утверждают другие ответы: выходные данные зависят только от текущего состояния). Но у него есть (как минимум) две небольшие проблемы:

  1. Он использует разрешенный тип std_logic для сигналов с одним приводом, что не очень хорошая идея. std_ulogic и std_ulogic_vector было бы намного лучше и безопаснее.
  2. Он использует имена input и output, которые, хотя и не являются зарезервированными словами языка, следует избегать: они являются стандартными входными и выходными потоками, определенными в std.textio.
person Renaud Pacalet    schedule 20.06.2017
comment
output не примет значение 00 немедленно, если сброс никогда не переключается. - person Javia1492; 20.06.2017
comment
Прошу прощения, Javia1492, но вы не правы. Вы должны лучше взглянуть на семантику VHDL. Или попробуйте сами, моделирование этого дизайна занимает 2 минуты. - person Renaud Pacalet; 20.06.2017
comment
Хорошо, спасибо, Рено. Я не знал, что процесс состояния будет запущен один раз, даже без перехода в само состояние. Я вполне доволен этим ответом. И я думал, что увидел "UU" в своем симуляторе, но только что сделал это заново, и он с самого начала выводит "00". Спасибо ;) - person Ril Dank; 20.06.2017
comment
Он не запущен, он инициализирован, и существует зависимость порядка, которая требует, чтобы state был инициализирован до того, как процесс, назначающий output, будет выполнен во время инициализации. Каждый процесс выполняется во время инициализации, пока не приостановится. Любые транзакции в спроецированных драйвером выходных сигналах в текущее или будущее время моделирования, которые вызовут события, стимулируют модель проекта к продолжению моделирования. Ваш UU будет обновлен до 00 в первом цикле симуляции, происходящем без увеличения времени симуляции, элемент формы волны после time_expression по умолчанию равен 0. - person ; 20.06.2017
comment
Увидев ваш ответ об использовании std_ulogic: хотя это может быть лучше/мудрее, я столкнулся с проблемами при интеграции с инструментами EDA и особенно при подключении к сторонним IP. Все используют std_logic и делают это уже несколько десятилетий, так что переключиться на него не так-то просто. Я бы не советовал так делать. - person JHBonarius; 21.06.2017
comment
@JHBonarius Я понимаю твою точку зрения. Обычно я решаю это с помощью оболочки верхнего уровня, которая просто преобразует std_ulogic в std_logic. Это еще один уровень в иерархии, но он простой и ограничивает риски. Более того, эта оболочка также может делать другие полезные вещи, такие как 1) создание экземпляров макросов, зависящих от поставщика (IOBUF...), и, таким образом, поддерживать более низкие уровни более независимыми от поставщика, 2) преобразование структурированных типов (запись axi_master2slave) в отдельные порты, 3 ) позволяют синтезировать нижние уровни с помощью стороннего инструмента и верхний уровень с помощью инструмента вашего поставщика... - person Renaud Pacalet; 21.06.2017