Без дайвинга слишком глубоко в циклы моделирования, используемых Verilog симуляторов, вы можете думать о неблокирующем против блокировки назначения просто, как это:
Блокировки назначение происходит встроенное в то время данного задание выполняется, так что означает, что если у меня есть строка, такая как A = A + 1
, это означает, что мы берем текущее значение A
, добавляем 1 и присваиваем A
это новое значение. Таким образом, назначение «блокирует» выполнение до тех пор, пока оно не будет выполнено.
Неблокирующее назначение (NBA) происходит в то время немного позже, чем при выполнении строки. Вы можете думать о неблокирующих назначениях как о строках, которые говорят симулятору планировать это назначение немного позже (обратите внимание, что в дальнейшем все еще остается тот же шаг времени моделирования, поэтому все это происходит в simtime t). Итак, если у вас есть что-то вроде A <= A + 1
, это означает, что во время выполнения этой строки выберете значение A
, добавьте 1 и заплатите A
, чтобы немного обновить это значение, но продолжайте движение по линиям, следующим за этим , Итак, если следующая строка после равна out = (A == 1) ? 1 : 0
, эта строка будет выполняться с использованием старого значения A
, а не приращенного.После того, как симулятор закончил с активным кодом, он может перейти к выполнению всех неблокирующих назначений. Теперь A
получит добавочное значение, и все другие неблокирующие назначения вступят в силу.
Итак, к вашим примерам. В случае одного мы видим замедленный эффект NBA. В блоке initial
A
присваивается 0, что означает, что A
будет принимать значение 0 немного позже (все еще в течение sim time 0 помнить); т.е. назначение запланировано после выполнения всех назначений блокировки (не строго верно, но в этом случае оно работает). Кроме того, у вас есть posedge часов, так что выполняется блок always
. Здесь A
принимает значение A + 1
, но помните, что назначение A
на 0 не произошло, поэтому A
все еще имеет начальное значение 8'bx
. поэтому A + 1
также является 8'bx
. И поскольку это блокировка, это происходит сразу. Итак, A
не меняется, не заботясь. Продолжается, out
получает текущее значение A
, которое составляет 8'bx
. Итак, мы не заботимся о out
. После того, как эти и другие блокировки будут выполнены, теперь мы закончим NBA, в этом случае A
, чтобы стать 0. Итак, все еще в пределах sim time 0, A
становится 0, и мы закончили. В следующем задаче часов A
равен 0, out
не имеет значения, и ваш блок always
работает как ожидалось, увеличивая A
и присваивая out
тому же значению.
Если вы изменили блок always
, чтобы использовать NBA (что должно быть, если оно должно быть регистром), все немного меняется. Блок initial
по-прежнему приводит к тому, что NBA запланировано на A
, чтобы стать 0. Но теперь блок always
делает что-то другое. Теперь, A <= A + 1
вместо того, чтобы назначать A
, чтобы не беспокоиться сразу, он составляет A
, чтобы стать 8'bx
(помните, что правое выражение для того, какое значение назначать, оценивается в строке, поэтому A + 1
по-прежнему использует A
, так как все равно как и раньше, что изменилось, когда A
берет на себя это новое значение), и это запланировано после A
, чтобы стать 0. Итак, установлены NBA A
, но один из них сообщает A
, чтобы быть первым, и был уничтожен более позднее назначение A
- 8'bx
. out
также планируется принять на 8'bx
, но теперь A
никогда не становится 0. Как таковые, A
и out
застряли в 8'bx
.
Вы можете просмотреть LRM Verilog или SystemVerilog, чтобы лучше понять циклы sim и что действительно происходит, но я надеюсь, что это поможет вам лучше понять разницу!
Спасибо! Долгий, но тщательный пост! Кажется, я понимаю это сейчас ... :) Еще раз спасибо. – user35443
@ user35443 Ну, блокировка против неблокирующего назначения не простая вещь для объяснения и может занять немного мысли, чтобы понять :) – Unn