Je suis un peu confus quant à la façon dont les affectations bloquantes et non bloquantes sont interprétées lors de la création d'un diagramme matériel. Faut-il en déduire qu'une cession non bloquante nous donne un registre? Ensuite, selon cette déclaration c <= a+b
, c serait un registre correct, mais pas a et 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
Il est certainement un peu difficile de comprendre les différences entre les affectations bloquantes et non bloquantes. Mais pas de peur - il existe une règle pratique:
Si vous souhaitez déduire une logique de liste déroulante avec un bloc
always
, utilisez des affectations bloquantes (=
). Si vous voulez une logique séquentielle, utilisez un blocalways
cadencé avec des affectations non bloquantes (<=
). Et essayez de ne pas mélanger les deux.
Votre code ci-dessus n'est probablement pas le meilleur exemple. Sans savoir quelle structure additionneur/bascule vous essayez de construire, vous risquez de créer des chemins de retour combo (qui sont mauvais). Et comme vous n'avez pas de bus d'entrée, vous essayez essentiellement de construire a
, b
& c
à partir de rien!
Mais pour répondre à votre question, toute variable affectée à un bloc always
cadencé déduira une bascule, sauf si elle est affectée à l'aide de l'opérateur de blocage (=
) et utilisée comme une sorte de variable locale.
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's used outside the always block
logic [7:0] c3;
always_ff @(posedge clock) begin
c3 = in1 + in2;
end
assign f5 = c3 + in1;
endmodule
L'une des principales raisons de suivre la règle empirique et de ne pas mélanger les affectations bloquantes et non bloquantes dans un bloc always
est que le mélange de vos affectations peut entraîner de graves incohérences de simulation entre les simulations RTL et les opérations matérielles gate-sims/real. Le simulateur Verilog traite =
et <=
de manière très différente. Les affectations bloquantes signifient "attribuer immédiatement la valeur à la variable à l'instant". Les affectations non bloquantes signifient «déterminez quoi attribuer à cette variable et stockez-la pour l'affecter ultérieurement». Un bon article à lire pour mieux comprendre ceci est: Voir aussi: http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
La sagesse conventionnelle de Verilog a tout faux. L'utilisation d'attributions de blocage pour une variable locale ne pose aucun problème. Cependant, vous ne devez jamais utiliser d'assignations bloquantes pour la communication synchrone, car elles ne sont pas déterministes.
Une affectation non bloquante dans un bloc toujours synchronisé induira toujours une bascule, comme dicté par la sémantique.
Qu'une affectation de blocage dans un bloc horodaté implique toujours une bascule ou non dépend entièrement de son utilisation. S'il est possible que la variable soit lue avant d'être affectée, une bascule sera déduite. Sinon, cela ressemble à une variable temporaire et il en résulte une certaine logique combinatoire.
Je veux juste ajouter à la réponse de Jan Decaluwe. Il semble qu'il y ait très peu de code dans la nature qui utilise réellement ce que décrit Jan Decaluwe, même s'il a tout à fait raison. Mélanger des déclarations bloquantes et non bloquantes est maintenant un tabou, grâce à Mr. Cummings.
Le problème est que la plupart des sites évitent d’utiliser des instructions de blocage pour les variables locales et il y a très peu de code dans l’espace de recherche immédiat de Google qui donne un exemple de la façon dont cela est fait. Le seul endroit où j'ai trouvé le style de codage mentionné par Jan est le code gagnant de cet article . Et cela, je suis tombé par hasard
J'ai eu du mal à ça aussi.
Mais tout d’abord, vous devez comprendre que ne pas bloquer ou bloquer n’a en réalité rien à voir avec la création ou non d’un verrou/ff!
Pour leur différence, vous pouvez le comprendre simplement (au début) par ce point: i. Si vous utilisez le blocage, les phrases suivantes ne pourront pas être exécutées avant la valeur attribuée à la phrase LHS de la phrase bloquée, car ce qui a été modifié en LHS pourrait être mis à jour et utilisé si la variable était utilisée. Cependant, pour le non-blocage, il ne bloque pas la phrase suivante, comme parallèle à la phrase suivante (en fait, le calcul RHS devrait être effectué en premier, mais cela n'a pas d'importance, ignorez-le lorsque vous confondez). Le LHS ne change pas/n'est pas mis à jour pour l'exécution de cette heure (mis à jour la prochaine fois quand le blocage est déclenché à nouveau). Et la phrase suivante utilise l'ancienne valeur, telle qu'elle se mettait à jour à la fin du cycle d'exécution.
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;
Un point clé consiste à déterminer si, dans votre code (toujours en mode bloc), il existe des variables de cas non associées à une valeur, mais pouvant se produire. Si vous ne lui transmettez pas de valeur et que cela se produit, latch/ff est créé pour conserver la valeur.
Par exemple,
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.
Après pourrait également créer un verrou/ff:
always @(*) begin
if(in) a = 1;
else b = 1;
end
-> latch/ffs créés pour in = 1, b aucune affectation, in = 0 a aucune affectation.
De plus, lorsque vous sentez que la fonction clk always @(posedge clk)
est posée, elle se termine forcément par latch/ff. Parce que, pour clk, il doit exister un bord négatif, et que vous ne faites rien, latch/ffs sont créés pour conserver toute l'ancienne valeur!
Je peux répondre à votre question, mais je pense qu'un document serait préférable pour cela. Je vous recommande donc de lire ce document de Clifford Cummings. Il dissipera tous vos doutes et, en plus, renforcera votre compréhension de Verilog.
http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf
s'il vous plait, vous pouvez toujours interpréter le verilog dans le domaine numérique, il vous suffit de comprendre ce qui se passera si le même code que vous avez écrit sera converti au niveau de la porte; , cela limitera votre réflexion. s'en tenir au côté numérique du code seulement voici ce qui se passera si votre code est converti au niveau de la porte, il suffit de voir que vous ne voulez que cela
merci salutations Rahul jain