Introduction
Cette page aborde les sorties de données synchrones à la source (source-synchronous outputs). Cette technique signifie que les sorties de données sont synchronisées avec une horloge que le FPGA génère en parallèle de ces sorties.
Cette approche est le choix évident si l’interface avec un composant externe ne comporte que des ports de sortie du FPGA. Elle convient également si l’E/S est bidirectionnelle, comme cela est discuté en bas de cette page. Il existe aussi une page séparée qui traite des relations entre l’horloge et les données en général.
L’application de base
Considérons cet exemple Verilog :
module top (
input clk,
output reg [7:0] data_out,
output reg sync_clk_out
);
always @(posedge clk)
begin
sync_clk_out <= !sync_clk_out;
if (sync_clk_out)
data_out <= data_out + 1;
end
endmodule
Notez que @data_out change de valeur en même temps que le front descendant de @sync_clk_out : lorsque @sync_clk_out est à l’état bas, @data_out ne change pas. Lorsque @sync_clk_out est à l’état haut, @data_out prend une nouvelle valeur en réponse au front montant de @clk.
Si des registres IOB sont utilisés pour @data_out et @sync_clk_out, tous ces signaux de sortie changent de valeur pratiquement au même instant. Le composant externe qui reçoit ces signaux peut donc utiliser @sync_clk_out comme horloge. Il est généralement facile de satisfaire ainsi les exigences temporelles du composant externe (en supposant que l’échantillonnage (sampling) de @data_out soit synchronisé avec le front montant de @sync_clk_out).
Utiliser des registres DDR
L’exemple ci-dessus présente un inconvénient majeur : la fréquence de @sync_clk_out est égale à la moitié de celle de @clk. Par conséquent, le débit de données de @data_out est lui aussi limité à la moitié de la fréquence de @clk. La seule exception est si le composant externe est sensible aux deux fronts de @sync_clk_out (c’est-à-dire s’il possède une entrée DDR). Ce n’est généralement pas le cas.
Il est possible d’utiliser un registre DDR de sortie pour générer une horloge de sortie alignée sur les sorties de données. L’idée est d’employer une bascule qui change d’état sur les deux fronts d’horloge. Une telle bascule se comporte donc ainsi :
always @(posedge clk or negedge clk)
if (clk)
sync_clk_out <= 0;
else
sync_clk_out <= 1;
@sync_clk_out passe à l’état bas en réponse au front montant de @clk. L’inverse se produit lors d’un front descendant. Le résultat est une horloge de sortie ayant la même fréquence.
Cependant, ce code Verilog ne fonctionnera pas avec la plupart des synthétiseurs (synthesizers), car les bascules du tissu logique ne sont généralement pas capables d’être sensibles aux deux fronts d’horloge. Seuls les registres IOB en ont la capacité, et le synthétiseur est rarement assez astucieux pour comprendre cette possibilité.
Il faut donc passer par une instanciation (instantiation) d’une primitive (primitive) logique. La primitive est spécifique au FPGA utilisé. L’exemple suivant montre comment procéder pour un Kintex Ultrascale :
ODDRE1 ODDR_ins
(.C(clk), .Q(sync_clk_out),
.D1(1'b0), .D2(1'b1),
.SR(1'b0));
Mais maintenant, l’horloge est générée par un registre DDR de sortie alors que les données sont générées par des registres IOB ordinaires. L’alignement entre les données et l’horloge n’est plus aussi évident qu’avant. Il est donc important de consulter les rapports de timing pour toutes les sorties et de vérifier que l’écart entre les délais est suffisamment faible.
Il est également possible d’utiliser des registres DDR de sortie pour les données : si la même valeur est appliquée sur D1 et D2, la sortie ne change qu’une fois par cycle d’horloge :
module top (
input clk,
output [7:0] data_out,
output sync_clk_out
);
reg [7:0] data;
ODDRE1 ODDR_ins
(.C(clk), .Q(sync_clk_out),
.D1(1'b0), .D2(1'b1),
.SR(1'b0));
ODDRE1 ODDR_data_ins [7:0]
(.C(clk), .Q(data_out),
.D1(data), .D2(data),
.SR(1'b0));
always @(posedge clk)
data <= data + 1;
endmodule
Cette méthode garantit que les données et l’horloge sont alignées. L’instanciation explicite des registres DDR de sortie garantit également que des registres IOB sont utilisés. Le seul inconvénient de cette méthode est qu’elle est spécifique à chaque FPGA.
Remarque : le comportement des registres DDR de sortie peut être inattendu et déroutant. Par exemple, notez que @data est synchronisé sur le front montant de @clk. Mais le composant ODDRE1 est actif sur les deux fronts d’horloge. Prenez le temps de lire la documentation de votre FPGA pour savoir comment et quand les deux entrées de données sont échantillonnées.
Notez également que la remise à zéro n’est pas utilisée dans cet exemple. Cela peut être risqué, en particulier sur les FPGA sophistiqués : le registre DDR de sortie peut faire partie d’un élément logique plus complexe à l’intérieur de l’IOB. Un tel élément logique risque de ne pas fonctionner correctement sans remise à zéro.
Contraintes temporelles
Alors, des contraintes temporelles (timing constraints) sont-elles nécessaires avec cette méthode ? Si l’horloge et les sorties de données sont alignées presque parfaitement grâce aux registres IOB, n’est-ce pas suffisant ?
La réponse est que cette méthode peut fonctionner parfaitement même sans contraintes temporelles. Il est néanmoins judicieux de profiter des contraintes temporelles. Les raisons sont les mêmes que celles évoquées sur la page consacrée aux registres IOB.
Autres considérations
L’utilisation de registres IOB n’est pas la seule chose à garantir, cependant : il faut aussi prêter attention à la proximité physique entre les ports de sortie. Si les ports de sortie sont éloignés les uns des autres, cette distance physique peut avoir un effet néfaste sur la distorsion d’horloge (clock skew) dans le FPGA. Les différences entre les longueurs des pistes (c’est-à-dire les conducteurs sur le PCB) peuvent également avoir un effet négatif. De plus, les paramètres électriques (tension, norme d’E/S, vitesse de balayage (slew rate), courant de sortie, etc.) doivent être les mêmes pour toutes les sorties.
Si le FPGA ne dispose pas de registres IOB, les contraintes temporelles deviennent cruciales : le principe même des sorties synchrones à la source repose sur la capacité à garantir un faible écart entre tous les ports de sortie concernés. Contrôler le délai entre la bascule et la broche d’E/S est généralement suffisant : si ce délai est proche du minimum possible pour le FPGA considéré, les différences entre les sorties seront suffisamment faibles pour la plupart des besoins.
E/S bidirectionnelles
La principale caractéristique des sorties synchrones à la source est que l’horloge associée est générée par le FPGA. Cela convient évidemment lorsque tous les signaux de données sont dirigés vers le composant externe. Mais même lorsqu’il y a des signaux de données dans les deux sens, il peut être judicieux de s’appuyer sur une horloge générée par le FPGA.
Remarque cependant : les entrées de données sont synchrones avec l’horloge sur le PCB, et non avec l’horloge interne de la puce FPGA. Ces deux horloges ont exactement la même fréquence, bien sûr. Mais il existe une différence de timing qui dépend du délai de propagation de l’horloge vers la sortie des ports de sortie. Ce délai peut atteindre plusieurs nanosecondes.
Il est donc recommandé de réaliser une boucle de retour (loopback) sur le PCB : connecter la sortie d’horloge du FPGA à un port d’entrée. Ce port d’entrée peut être traité comme s’il s’agissait d’une horloge synchrone au système (system synchronous clock) : le composant externe se comporte comme si son horloge provenait d’un oscillateur dédié, et non du FPGA. La situation est similaire à celle d’une horloge synchrone au système, car le FPGA et le composant externe s’appuient tous deux sur le même signal physique sur le PCB.
Il est également possible de traiter les entrées de données comme des entrées synchrones à la source (source-synchronous inputs). En particulier, si la technique de déphasage est utilisée, aucune boucle de retour d’horloge n’est nécessaire. C’est d’ailleurs la méthode habituelle pour interfacer des mémoires DDR SDRAM.
La conclusion importante est de planifier soigneusement le timing des signaux d’entrée avant la fabrication du PCB, et d’envisager d’ajouter une boucle de retour d’horloge si nécessaire.

