L'erreur de synthèse Vivado [Synth 8-91] ambiguous clock in event control indique une ambiguïté dans le code Verilog concernant l'identification du signal d'horloge principal dans un bloc always. L'outil de synthèse est incapable de déterminer sans équivoque quel signal déclenche le circuit séquentiel décrit, ce qui l'empêche de générer une représentation matérielle correcte. Cette situation survient typiquement lorsque la liste de sensibilité (l'expression @(...)) contient des signaux dont le rôle n'est pas clair ou contradictoire avec leur utilisation dans le corps du bloc.
La cause la plus fréquente réside dans l'inclusion d'un signal dans la liste de sensibilité qui n'est jamais utilisé dans la logique conditionnelle du bloc always. L'outil interprète ce signal comme un déclencheur ptoentiel, mais son absence dans les opérations du registre crée une contradiction. Considérons un premier cas problématique où une horloge secondaire est listée mais ignorée.
// Exemple 1 : Signal inutilisé dans la liste de sensibilité
module ExempleAmbiguite1 (
input wire clk_principal,
input wire clk_secondaire, // Signal non utilisé dans la logique
input wire reset_n_actif_bas,
output reg [15:0] registre_etat
);
// La liste de sensibilité inclut 'clk_secondaire', mais ce signal
// n'est jamais référencé dans le corps du bloc always.
always @(posedge clk_principal or posedge clk_secondaire or negedge reset_n_actif_bas) begin
if (!reset_n_actif_bas) begin
registre_etat <= 16'h0000;
end else begin
registre_etat <= registre_etat + 1'b1;
end
end
endmodule
La correction consiste à retirer de la liste de sensibilité tout signal qui n'agit pas comme un déclencheur asynchrone (comme un reset) ou une horloge effective. Pour le reset asynchrone, il doit être correctement référencé dans la condition. Une autre source d'ambiguïté, plus subtile, provient d'un mauvais positionnement d'un signal de contrôle dans la liste d'événements, le faisant apparaître comme une horloge alors qu'il ne l'est pas.
// Exemple 2 : Mauvaise pratique - un signal de contrôle traité comme une horloge
module ExempleAmbiguite2 (
input wire clock_in,
input wire load, // Signal de contrôle synchrone
input wire [7:0] entree_donnees,
output reg [7:0] sortie_donnees
);
// ERREUR : 'load' est placé dans une détection de front, ce qui en fait
// une "horloge" ambiguë au même titre que 'clock_in'.
always @(posedge clock_in or posedge load) begin
if (load) begin
sortie_donnees <= entree_donnees;
end
end
endmodule
L'écriture ci-dessus est incorrecte pour un contrôleur synchrone. Le signal load doit être échantillonné au front de l'horloge principale, pas devenir un déclencheur indépendant. La solution est d'utiliser une détection de niveau dans la logique conditionnelle, et de n'avoir qu'une seule horloge dans la liste de sensibilité pour un design purement synchrone.
// Exemple 2 (corrigé) : Échantillonnage synchrone correct
module ExempleAmbiguite2_Corrige (
input wire clock_in,
input wire load,
input wire [7:0] entree_donnees,
output reg [7:0] sortie_donnees
);
// Le bloc est sensible uniquement au front de l'horloge.
always @(posedge clock_in) begin
// Le signal 'load' est évalué comme une condition de niveau.
if (load) begin
sortie_donnees <= entree_donnees;
end
end
endmodule
Pour les blocs combinatoires, la liste de sensibilité doit être complète, mais cela n'entraîne généralement pas une erreur d'horloge ambiguë. L'erreur [Synth 8-91] est spécifique aux blocs séquentiels. En résumé, pour éviter cette erreur : 1) N'incluez dans la liste de sensibilité d'un bloc always @(posedge...) que les signaux d'horloge et de reset asynchrone effectifs. 2) Utilisez @(*) pour les blocs combinatoires. 3) Assurez-vous que tout signal listé est véritablement exploité dans les conditions du bloc.