Несколько присвоений одному и тому же регистру в блоке RTL с помощью Kansas Lava

У меня возникают проблемы с пониманием поведения Канзас Лава, когда RTL Блок содержит несколько присвоений одному и тому же регистру. Вот версия № 1:

foo :: (Clock c) => Signal clk Bool
foo = runRTL $ do
    r <- newReg True
    r := low    
    return $ var r

Это ведет себя так, как я ожидал:

*Main> takeS 10 foo :: Seq Bool
low | low | low | low | low | low | low | low | low | low | ? .

Сгенерированный VHDL является:

architecture str of assignments is
  signal sig_2_o0 : std_logic;
begin
  sig_2_o0 <= '0';
  OUTPUT <= sig_2_o0;
end architecture str;

Однако я надеялся, что эта другая версия также будет работать:

foo = runRTL $ do
    r <- newReg True

    r := low
    r := high
    return $ var r

Но это не так, и второе назначение не учитывается:

*Main> takeS 10 foo :: Seq Bool
low | low | low | low | low | low | low | low | low | low | ? .

Причина, по которой я смущен, заключается в том, что reg а также var определены в терминах полного тактового цикла, поэтому я не могу сделать невозможные для синтеза вещи, такие как ветвь на основе r а затем переназначить ему новое значение. Так почему же эта вторая форма не работает?

Это не просто проблема моделирования: сгенерированный VHDL для второй версии ясно видно, что второе назначение выбрасывается во время генерации:

architecture str of assignments2 is
  signal sig_2_o0 : std_logic;
begin
  sig_2_o0 <= '0';
  OUTPUT <= sig_2_o0;
end architecture str;

В общем, я бы ожидал, что результат будет больше похож на

architecture str of assignments2 is
  signal sig_2_o0 : std_logic;
begin
  sig_2_o0 <= '0';
  sig_2_o0 <= '1';
  OUTPUT <= sig_2_o0;
end architecture str;

но я не уверен, что это будет / должно значить в VHDL.

1 ответ

Решение

Проблема в том, что вы используете несколько неблокирующих операторов для назначения сигнала.

  sig_2_o0 <= '0';
  sig_2_o0 <= '1';

Это переводится как:

at next event assign '0' to sig_2_o0.
at next event assign '1' to sig_2_o0.

Это отличается от использования блокирующих назначений:

  sig_2_o0 := '0';
  sig_2_o0 := '1';

Что бы перевести на:

assign '0' to sig_2_o0.
assign '1' to sig_2_o0.

Блокировка назначений

При использовании назначений блокировки значение четко определено. Сначала он будет установлен на "0", затем переопределит его на "1". В этом примере не должно быть никакого эффекта от первого назначения блокировки для симуляции или синтезированного оборудования. Вы можете думать об этом как о нулевой задержке между первым назначением и вторым. Это означает, что у вас импульс 0, который на самом деле ничто. Это эквивалентно только последнему назначению, первое полностью пропущено. Одно предостережение заключается в том, что если вы установите задержку для назначений, например, "после 1 нс", то вы заметите первое назначение, а затем второе в симуляции. В аппаратном обеспечении задержки игнорируются, поэтому добавление задержек не изменилось бы. Фактически, вставка задержек в RTL, которая предназначена для синтеза, настоятельно не рекомендуется по этой причине. Крайне желательно, чтобы аппаратное обеспечение соответствовало моделированию, а добавление задержек могло привести к несоответствиям.

Неблокирующие назначения

Но когда вы используете неблокирующие назначения, у симулятора есть два назначения, запланированные для следующего события времени. Установите сигнал на "1" и одновременно установите на "0". Так какое запланированное назначение будет принимать сигнал? Там нет никакого способа узнать. Это может быть любое значение, поскольку оно назначено неправильно. Каждый инструмент проверки и синтеза на планете должен выдавать ошибку, когда сталкивается с несколькими неблокирующими заданиями, подобными этому. Может быть возможно смоделировать это, но есть ясно проблема с RTL.

Другие вопросы по тегам