Подтвердить что ты не робот

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

У меня возникли проблемы с пониманием поведения 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.

4b9b3361

Ответ 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 задержек между первым назначением и вторым. Это означает, что у вас есть импульс ширины 0, что на самом деле ничего. Это эквивалентно простому последнему присваиванию, с первым полностью опущенным. Одно из предостережений заключается в том, что если вы положили задержку на назначения, например. "после 1 нс" вы заметите первое задание, за которым следует второе в симуляции. В аппаратных средствах задержки игнорируются, и поэтому от добавления задержек не будет никаких изменений. По этой причине вставка задержек RTL, которая должна быть синтезирована, настоятельно не рекомендуется. Очень желательно, чтобы аппаратное обеспечение соответствовало симуляции, а добавление задержек может привести к несоответствиям.

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

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