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

Как интерпретировать блокировку против неблокирующих присвоений в Verilog?

Я немного запутался в том, как интерпретируются блокирующие и неблокирующие назначения, когда дело доходит до построения аппаратной диаграммы. Должны ли мы заключить, что неблокирующее присвоение дает нам регистр? Тогда согласно этому утверждению c <= a+b , c будет правом регистра, но не a и b?

module add (input logic clock,  
output logic[7:0] f);   

logic[7:0] a, b, c;  

always_ff @(posedge clock)  
begin   
  a = b + c;   
  b = c + a;   
  c <= a + b;  
end   

assign f = c;  

endmodule
4b9b3361

Ответ 1

Это определенно немного сложно понять, как начать блокирование и неблокировать назначения. Но нет страха - есть удобное эмпирическое правило:

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

Ваш код выше, вероятно, не лучший пример. Не зная, какую структуру сумматора/флипфлопа вы пытались построить, существует опасность наличия комбинированных путей обратной связи (что плохо). И поскольку у вас нет входных шин, вы пытаетесь построить a, b и c из воздуха!

Однако, чтобы ответить на ваш вопрос, любая переменная, назначенная в пределах тактового блока always, выведет триггер, если только он не назначен с использованием оператора блокировки (=) и не используется как своего рода локальная переменная.

module add
  (
   input clock,
   input [7:0] in1,
   input [7:0] in2,
   output logic [7:0] f1, f2, f3, f4, f5
   );   


   // f1 will be a flipflop
   always_ff @(posedge clock) begin
      f1 = in1 + in2;
   end


   // f2 will be a flipflop
   always_ff @(posedge clock) begin
      f2 <= in1 + in2;
   end


   // f3 will be a flipflop
   // c1 will be a flipflop
   logic [7:0] c1;
   always_ff @(posedge clock) begin
      c1 <= in1 + in2;
      f3 <= c1 + in1;
   end


   // f4 will be a flipflop
   // c2 is used only within the always block and so is treated
   // as a tmp variable and won't be inferred as a flipflop
   logic [7:0] c2;
   always_ff @(posedge clock) begin
      c2 = in1 + in2;
      f4 = c2 + in1;
   end


   // c3 will be a flipflop, as it used outside the always block
   logic [7:0] c3;
   always_ff @(posedge clock) begin
      c3 = in1 + in2;
   end

   assign f5 = c3 + in1;

endmodule

Большая причина для соблюдения эмпирического правила, а не смешения блокировки и неблокирования в блоке always, заключается в том, что смешивание ваших назначений может вызвать серьезные несоответствия моделирования между симуляторами RTL и симуляторами gate-sims/real hardware. Симулятор verilog относится к = и <= совершенно по-другому. Блокирующие присвоения означают "присваивать значение переменной сразу же в этот момент". Неблокирующие назначения означают "выяснить, что назначить этой переменной, и сохранить ее для назначения в будущем". Хорошая статья, чтобы понять это лучше: Смотрите также: http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf

Ответ 2

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

Неблокируемое присваивание в блоке всегда всегда будет вызывать флип-флоп, как это продиктовано семантикой.

Независимо от того, полностью ли оно связано с тем, связано ли блокирующее присвоение в тактическом блоке всегда, что происходит с триггером или нет. Если возможно, что переменная считывается перед назначением, будет выведен триггер. В противном случае это как временная переменная, и это приведет к некоторой комбинаторной логике.

Ответ 3

Просто хочу добавить к ответу Jan Decaluwe. Похоже, что в дикой природе очень мало кода, который фактически использует то, что описывает Ян Декалуэ, хотя это абсолютно правильно. Смешивание блокировки и неблокирующие заявления теперь являются табу, благодаря Mr.Cummings.

Проблема в том, что большинство мест избегают использования операторов блокировки для локальных переменных, и в ближайшем пространстве поиска Google очень мало кода, который выглядит как пример того, как это делается. Единственное место, где я нашел стиль кодирования, как упоминал Ян, - выигрышный код в этой статье. И это, я случайно наткнулся

Ответ 4

Мне тоже было непросто.

Но, во-первых, вы должны понимать, что неблокирование или блокировка на самом деле не имеет никакого отношения к тому, будет ли создана защелка /ff!

По их разнице вы могли бы понять это просто (в начале) к этому моменту: i. Если блокировка использования, предложения после того, как она не может быть выполнена до тех пор, пока не будет присвоено значение блока LHS, так как то, что изменилось на LHS, может быть обновлено и использовано, если эта переменная используется. Тем не менее, для неблокирования он не блокирует следующее предложение, подобное параллельному следующему предложению (на самом деле расчет RHS должен выполняться первым, но это не имеет значения, игнорируйте его, когда вы путаете). LHS не изменяет/не обновляется для выполнения этого времени (обновляется в следующий раз, когда всегда снова запускается блок). И следующее предложение использует старое значение, так как оно обновляется в конце цикла выполнения.

a = 0; b= 0;
a = 1;
b = a;
--> output a = 1, b = 1;
a = 0; b= 0;
a <= 1;
b = a;
--> output a = 1, b = 0;

Один из ключевых моментов состоит в том, чтобы определить, есть ли в вашем коде (всегда блок) какая-либо переменная случая, но не может быть назначена, но может произойти. Если вы не передадите ему значение, и в этом случае создается защелка /ff, чтобы сохранить значение.

Например,

always @(*) begin
    if(in) out = 1;
    else out = 0;
end
--> this end without latch/ff
always @(*) begin
    if(in) out = 1;
end
--> this end with one latch/ff to keep value when in = 0, as it might happen and you didn't assign value to out as in=1 do. 

Далее можно создать запирание /ff:

always @(*) begin
    if(in) a = 1;
    else b = 1;
end

- > latch/ffs, созданный для in = 1, b no assign, in = 0 a no assign.

Кроме того, когда вы чувствуете posedge clk always @(posedge clk), он должен заканчиваться защелкой /ff. Потому что для clk должно существовать отрицательное ребро, и вы ничего не делаете, защелки /ffs созданы, чтобы сохранить все старое значение!

Ответ 5

пожалуйста, вы всегда можете интерпретировать verilog в цифровом домене, просто вам нужно понять, что произойдет, если тот же код, который вы написали, будет преобразован в уровень ворот, я лично не пойду по правилу, чтобы использовать не блокировку в seq или использовать блокирование в комбинационном, это ограничит ваше мышление. придерживаться только цифровой стороны кода вот что произойдет, если ваш код будет преобразован в уровень ворот, просто посмотрите, хотите ли вы это только

  • сначала будет создан полный сумматор - входы a и b
    1. выводится вывод flip flop, создающий выход a, имеющий синхронизацию с clk
    2. теперь, поскольку назначение блокируется, поэтому новый a будет затем применен к следующему полному добавленному, добавив этот новый a и c как вход, вывод которого будет передан dffcsync в clk, создавая новый b
    3. теперь, так как b = c + a; есть блокировка statment, поэтому b обновляется до этого нового b
    4. теперь его c <= a + b теперь, когда происходит полный сумматор, содержащий a и b как входной сигнал, который переходит в dff sync к clk, теперь есть другое условие, например, снова скажите a = c;
    5. тогда будет создан dff, имеющий старый c, а не новый, созданный неблокирующим оператором, и вывод этой dff-синхронизации в clk переходит к a, а a обновляется.

спасибо С уважением Рахул джайн

Ответ 6

Я могу ответить на ваш вопрос, но я думаю, что для этого лучше всего подходит один документ, поэтому я рекомендую вам прочитать эту статью Клиффорда Каммингса. Это очистит все ваши сомнения, и в дополнение к этому укрепит ваше понимание verilog.

http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf