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.
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
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
always_latch
.always @*
ou SystemVerilog always_comb
.case
doivent avoir une condition default
.if
doivent avoir un else
correspondant.case
ou if
).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.
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.
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