Несколько присвоений одному и тому же регистру в блоке 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.