web-dev-qa-db-fra.com

Qu'est-ce qu'un verrou inféré et comment il est créé lorsqu'il manque l'instruction else dans la condition if. Quelqu'un peut-il expliquer brièvement?

J'ai essayé de comprendre le verrou inféré et pourquoi il est nécessaire en interne, mais je n'ai trouvé aucune ressource avec suffisamment de détails.

12
user3429606

Un verrou est déduit dans un bloc combinatoire où le filet n'est pas affecté à une valeur connue. Attribuer un filet à lui-même déduira toujours un verrou. Les verrous peuvent également être déduits de signaux manquants dans une liste de sensibilité et de boucles de rétroaction.

La manière appropriée d'inférer un verrou prévu dans Verilog/SystemVerilog est:

/* Verilog */       ////    /* SystemVerilog */
always @*           ////    always_latch
begin               ////    begin
  if (en) q = d;    ////      if (en) q = d;
end                 ////    end

Façons dont les verrous sont accidentellement déduits:

  • Signal (s) manquant (s) pour la liste de sensibilité (c'est pourquoi @* Devrait être utilisé):

    always @(a or b) // inferred latch :: "c" missing for the sensitivity list.
    begin
      out = a + b + c;
    end
    
  • État manquant:

    always @*
    begin
      case(in[1:0])
       2'b00:  out = 1'b0;
       2'b01:  out = 1'b1;
       2'b10:  out = 1'b1;
       // inferred latch "out" :: missing condition 2'b11/default
     endcase
    end
    always @*
    begin
      next0 = flop0;
      next1 = flop1;
      // inferred latch "next2" :: missing initial condition
      next3 = flop3;
      case(a[2:0])
       3'b001:             next0 = in;
       3'b010:  if(b)      next1 = in;
       3'b100:  if(c)      next2 = in;
       default: if(!b&&!c) next3 = in;
     endcase   
    end
    
  • Boucle de rétroaction:

    assign out = en ? in : out; // inferred latch "out" :: feedback to mux
    assign a = en ? z : c;
    // ... any amount of code between ...
    assign z = en ? a : y; // inferred latch "a" :: feedback chain
    
    • Les boucles de rétroaction peuvent parcourir la hiérarchie et la conception.

Comment atténuer le risque de verrous involontaires:

  • Rendre les verrous prévus simples et identifiables:
    • Mettez les verrous prévus dans leurs propres blocs toujours avec le moins de logique combinatoire possible; Idéalement, placez la logique combinatoire des verrous dans son propre bloc toujours séparé. Soyez aussi explicite et identifiez les verrous prévus. Utilisez des commentaires, des étiquettes et, si possible, utilisez SystemVerilog always_latch.
  • Tous les blocs de logique combinatoire doivent être définis avec always @* ou SystemVerilog always_comb.
  • Assurez-vous que toutes les variables affectées dans un bloc logique combinatoire ont une affectation initiale ou par défaut.
    • Les instructions case doivent avoir une condition default.
    • Les instructions if doivent avoir un else correspondant.
    • Lorsque les blocs de logique combinatoire affectent de nombreuses variables, en donnant à chaque variable une valeur initiale au début du bloc (avant tout case ou if).
  • Sachez d'où viennent les entrées et où vont les sorties.
    • Les entrées de la logique combinatoire doivent être des flops o les sorties de la logique combinatoire doivent être des flops.
  • Examinez le code, utilisez des outils de peluchage et des outils de vérification d'équivalence logique.
    • La révision du code nécessite que le ou les réviseurs sachent où les verrous peuvent se cacher.
    • Utilisation de SystemVerilog always_comb peut aider à identifier les verrous présumés à l'aide d'outils de peluchage et de vérification d'équivalence logique.

Dans le pire des cas, placez toute la logique dans des blocs synchrones. Tous les verrous déduits deviennent des bascules déduites. C'est généralement une mauvaise idée car cela peut augmenter inutilement le nombre de portes, créer plus de routage et avoir un impact sur le timing.

17
Greg

Un verrou est déduit lorsque la sortie de la logique combinatoire a des états indéfinis, c'est-à-dire qu'elle doit conserver sa valeur précédente.

La logique combinatoire n'a pas de bascule pour maintenir l'état, la sortie doit donc toujours être définie par les entrées.

Un court exemple pourrait être:

always @* begin
  if (a == 1'b1) begin
    b =  x|y|z;
  end
end

Qu'est-ce que b quand a == 1'b0. b n'est pas écrasé, il conserverait donc sa valeur. Comment quelque chose peut-il avoir sa valeur alors qu'il n'a pas le concept d'État. Vous devez introduire l'état en déduisant un verrou. C'est normalement une très mauvaise chose.

Vous pouvez impliquer des verrous et faire attention au timing, etc., mais les verrous déduits proviennent nominalement du code buggy.

2
Morgan

Les verrous ne sont générés qu'avec des blocs toujours combinatoires. La logique séquentielle ne générera jamais de verrou.

Pour plus d'informations, consultez comment les verrous transparents sont créés et comment éviter de déduire les verrous

2
Russell