2015-05-08 2 views
0

У меня возникли проблемы с пониманием такой простой вещи: блокировки и неблокирующие назначения.Неблокирующие и блокирующие назначения не работают должным образом

Я создал небольшой тестовый стенд просто имитировать поведение этого кода:

module ATest(clk, out); 
    input wire clk; 
    output reg [7:0] out; 
    reg [7:0] A; 

    initial begin 
     A <= 8'b0; 
    end 

    always @(posedge clk) begin 
     A = A + 1; 
     out = A; 
    end 
endmodule 

После моделирования, я получил эту волну: What is that red line(8'hxx)?

Я ожидал, что такое же значение при обоих A и out , поскольку я присваивал им значения последовательно. Почему out «не волнует» во время первых часов?

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

always @(posedge clk) begin 
     A <= A + 1; 
     out <= A; 
end 

И я получил эту волну: Why is everything set to "don't care" now?

Я ничего здесь не ожидал, потому что неблокирующие заявления являются своего рода загадкой для меня. Почему оба A и out настроены на «не заботятся»?

Кроме того, я нашел разные имена на каждой странице я делся, поэтому, пожалуйста, помогите мне: ли блокирования и неблокирующий взаимозаменяем с последовательными и параллельным как терминов? Какой из них является правильным: неблокирующее заявление или параллельное заявление?

спасибо.

ответ

1

Без дайвинга слишком глубоко в циклы моделирования, используемых Verilog симуляторов, вы можете думать о неблокирующем против блокировки назначения просто, как это:

Блокировки назначение происходит встроенное в то время данного задание выполняется, так что означает, что если у меня есть строка, такая как A = A + 1, это означает, что мы берем текущее значение A, добавляем 1 и присваиваем A это новое значение. Таким образом, назначение «блокирует» выполнение до тех пор, пока оно не будет выполнено.

Неблокирующее назначение (NBA) происходит в то время немного позже, чем при выполнении строки. Вы можете думать о неблокирующих назначениях как о строках, которые говорят симулятору планировать это назначение немного позже (обратите внимание, что в дальнейшем все еще остается тот же шаг времени моделирования, поэтому все это происходит в simtime t). Итак, если у вас есть что-то вроде A <= A + 1, это означает, что во время выполнения этой строки выберете значение A, добавьте 1 и заплатите A, чтобы немного обновить это значение, но продолжайте движение по линиям, следующим за этим , Итак, если следующая строка после равна out = (A == 1) ? 1 : 0, эта строка будет выполняться с использованием старого значения A, а не приращенного.После того, как симулятор закончил с активным кодом, он может перейти к выполнению всех неблокирующих назначений. Теперь A получит добавочное значение, и все другие неблокирующие назначения вступят в силу.

Итак, к вашим примерам. В случае одного мы видим замедленный эффект NBA. В блоке initialA присваивается 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 и что действительно происходит, но я надеюсь, что это поможет вам лучше понять разницу!

+0

Спасибо! Долгий, но тщательный пост! Кажется, я понимаю это сейчас ... :) Еще раз спасибо. – user35443

+0

@ user35443 Ну, блокировка против неблокирующего назначения не простая вещь для объяснения и может занять немного мысли, чтобы понять :) – Unn

0

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

Есть ли положительный фронт часов в момент 0 в вашей симуляции?

+0

Да, есть. Отключение или изменение его на отрицательный фронт помогло (?). Как насчет этого параллельного кода? – user35443

+0

Как насчет параллельного кода? –

+0

Почему он остается в моем случае «8'ххх»? – user35443

1

Ваш вопрос исходит из использования неблокирующего назначения в вашем блоке initial. Вместо этого используйте initial A = 8'b0;.

Казус для этого, скорее всего, будет обработан двумя заданиями. = присвоения выполняются постепенно, при этом любые новые значения доступны для последующих присвоений. Изменения, внесенные с помощью назначений <=, доступны только после обработки всех заданий.

Поскольку ваш первый край при Т = 0 (когда intial блоки обрабатываются), в первом примере A назначается 0, но 0 пока не доступен out только после его обработки. Это в то время как первый цикл выглядит странно, но все остальное в порядке.Во втором, A назначается как 0, так и A+1, поэтому симулятор использует блок always вместо initial, исходящий с A+1, когда A все еще остается неизвестным. Таким образом, значения для A и out никогда не известны.

Смежные вопросы