Recherche…


Remarques

D-Flip-Flops (DFF) et les loquets sont des éléments de mémoire. Un DFF échantillonne son entrée sur l'un ou l'autre bord de son horloge (pas les deux), tandis qu'un verrou est transparent à un niveau de son activation et mémorisé sur l'autre. La figure suivante illustre la différence:

DFF vs comportement de loquets

Modéliser des DFF ou des verrous dans VHDL est facile mais il y a quelques aspects importants à prendre en compte:

  • Les différences entre les modèles VHDL de DFF et les verrous.

  • Comment décrire les bords d'un signal.

  • Comment décrire un ensemble ou des réinitialisations synchrones ou asynchrones.

D-Flip-Flops (DFF)

Dans tous les exemples:

  • clk est l'horloge,
  • d est l'entrée,
  • q est la sortie,
  • srst est une réinitialisation active haute synchrone,
  • srstn est une réinitialisation active synchrone basse,
  • arst est une réinitialisation asynchrone active,
  • arstn est une réinitialisation asynchrone active,
  • sset est un ensemble haute synchrone actif,
  • ssetn est un ensemble synchrone actif,
  • aset est un ensemble haut asynchrone actif,
  • asetn est un ensemble bas asynchrone actif

Tous les signaux sont de type ieee.std_logic_1164.std_ulogic . La syntaxe utilisée est celle qui permet de corriger les résultats de synthèse avec tous les synthétiseurs logiques. Veuillez vous reporter à l'exemple de détection du bord de l' horloge pour une discussion sur la syntaxe alternative.

Horloge de bord montante

process(clk)
begin
  if rising_edge(clk) then
    q <= d;
  end if;
end process;

Horloge de bord tombant

process(clk)
begin
  if falling_edge(clk) then
    q <= d;
  end if;
end process;

Horloge à front montant, réinitialisation active synchrone

process(clk)
begin
  if rising_edge(clk) then
    if srst = '1' then
      q <= '0';
    else
      q <= d;
    end if;
  end if;
end process;

Horloge de bord montante, réinitialisation active asynchrone

process(clk, arst)
begin
  if arst = '1' then
    q <= '0';
  elsif rising_edge(clk) then
    q <= d;
  end if;
end process;

Horloge à front descendant, asynchrone active à faible réinitialisation, synchrone active synchrone

process(clk, arstn)
begin
  if arstn = '0' then
    q <= '0';
  elsif falling_edge(clk) then
    if sset = '1' then
      q <= '1';
    else
      q <= d;
    end if;
  end if;
end process;

Horloge de bord montante, asynchrone active haute réinitialisation, bas active asynchrone

Remarque: set a une priorité plus élevée que reset

process(clk, arst, asetn)
begin
  if asetn = '0' then
    q <= '1';
  elsif arst = '1' then
    q <= '0';
  elsif rising_edge(clk) then
    q <= d;
  end if;
end process;

Loquets

Dans tous les exemples:

  • en est le signal d'activation,
  • d est l'entrée,
  • q est la sortie,
  • srst est une réinitialisation active haute synchrone,
  • srstn est une réinitialisation active synchrone basse,
  • arst est une réinitialisation asynchrone active,
  • arstn est une réinitialisation asynchrone active,
  • sset est un ensemble haute synchrone actif,
  • ssetn est un ensemble synchrone actif,
  • aset est un ensemble haut asynchrone actif,
  • asetn est un ensemble bas asynchrone actif

Tous les signaux sont de type ieee.std_logic_1164.std_ulogic . La syntaxe utilisée est celle qui permet de corriger les résultats de synthèse avec tous les synthétiseurs logiques. Veuillez vous reporter à l'exemple de détection du bord de l' horloge pour une discussion sur la syntaxe alternative.

Active haute active

process(en, d)
begin
  if en = '1' then
    q <= d;
  end if;
end process;

Actif bas actif

process(en, d)
begin
  if en = '0' then
    q <= d;
  end if;
end process;

Activation haute active, réinitialisation active synchrone

process(en, d)
begin
  if en = '1' then
    if srst = '1' then
      q <= '0';
    else
      q <= d;
    end if;
  end if;
end process;

Activation haute active, réinitialisation active asynchrone

process(en, d, arst)
begin
  if arst = '1' then
    q <= '0';
  elsif en = '1' then
    q <= d;
  end if;
end process;

Actif bas actif, asynchrone actif à faible réinitialisation, ensemble haut actif synchrone

process(en, d, arstn)
begin
  if arstn = '0' then
    q <= '0';
  elsif en = '0' then
    if sset = '1' then
      q <= '1';
    else
      q <= d;
    end if;
  end if;
end process;

Activation haute active, asynchrone active réinitialisation élevée, bas active asynchrone

Remarque: set a une priorité plus élevée que reset

process(en, d, arst, asetn)
begin
  if asetn = '0' then
    q <= '1';
  elsif arst = '1' then
    q <= '0';
  elsif en = '1' then
    q <= d;
  end if;
end process;

Détection de bord d'horloge

La petite histoire

Avec VHDL 2008 et si le type de l’horloge est bit , boolean , ieee.std_logic_1164.std_ulogic ou ieee.std_logic_1164.std_logic , une détection de bord d’horloge peut être codée pour le front montant

  • if rising_edge(clock) then
  • if clock'event and clock = '1' then -- type bit, std_ulogic or std_logic
  • if clock'event and clock then -- type boolean

et pour front descendant

  • if falling_edge(clock) then
  • if clock'event and clock = '0' then -- type bit, std_ulogic or std_logic
  • if clock'event and not clock then -- type boolean

Cela se comportera comme prévu, à la fois pour la simulation et la synthèse.

Note: la définition d'un front montant sur un signal de type std_ulogic est un peu plus complexe que le simple if clock'event and clock = '1' then . rising_edge exemple, la fonction standard d' rising_edge contient une définition différente. Même si cela ne fera probablement pas de différence pour la synthèse, cela pourrait en faire une pour la simulation.

L'utilisation des fonctions standard rising_edge et falling_edge est fortement encouragée. Avec les versions précédentes de VHDL, l'utilisation de ces fonctions peut nécessiter de déclarer explicitement l'utilisation de packages standard (par exemple ieee.numeric_bit pour le type bit ) ou même de les définir dans un package personnalisé.

Remarque: n'utilisez pas les fonctions standard rising_edge et falling_edge pour détecter les contours des signaux hors horloge. Certains synthétiseurs pourraient conclure que le signal est une horloge. Astuce: la détection d'un front sur un signal hors horloge peut souvent être effectuée en échantillonnant le signal dans un registre à décalage et en comparant les valeurs échantillonnées à différents stades du registre à décalage.

La longue histoire

Décrire correctement la détection des bords d'un signal d'horloge est essentiel lors de la modélisation de D-Flip-Flops (DFF). Une arête est, par définition, une transition d'une valeur particulière à une autre. Par exemple, on peut définir le front montant d'un signal de type bit (le type énuméré VHDL standard qui prend deux valeurs: '0' et '1' ) comme transition de '0' à '1' . Pour le type boolean nous pouvons le définir comme une transition de false à true .

Souvent, des types plus complexes sont utilisés. Le type ieee.std_logic_1164.std_ulogic , par exemple, est également un type énuméré, tout comme bit ou boolean , mais il a 9 valeurs au lieu de 2:

Valeur Sens
'U' Non initialisé
'X' Forçage inconnu
'0' Forcer le bas niveau
'1' Forcer haut niveau
'Z' Haute impédance
'W' Faible inconnu
'L' Faible niveau bas
'H' Faible niveau élevé
'-' Ne t'en fais pas

Définir un front montant sur un tel type est un peu plus complexe que pour bit ou boolean . Nous pouvons, par exemple, décider que c'est une transition de '0' à '1' . Mais on peut aussi décider que c'est une transition de '0' ou 'L' à '1' ou 'H' .

Note: c'est cette seconde définition que le standard utilise pour la fonction rising_edge(signal s: std_ulogic) définie dans ieee.std_logic_1164 .

Lorsque vous discutez des différentes manières de détecter les contours, il est donc important de prendre en compte le type de signal. Il est également important de prendre en compte l'objectif de modélisation: simulation uniquement ou synthèse logique? Illustrons ceci sur quelques exemples:

Bord montant DFF avec bit de type

signal clock, d, q: bit;
...
P1: process(clock)
begin
  if clock = '1' then
    q <= d;
  end if;
end process P1;

Techniquement, du point de vue de la sémantique de simulation, le processus P1 modélise un DFF déclenché par un front montant. En effet, l'attribution q <= d est exécutée si et seulement si:

  • clock changé (c'est ce que la liste de sensibilité exprime) et
  • la valeur actuelle de l' clock est '1' .

Comme l' clock est de type bit et que le type bit n'a que des valeurs '0' et '1' , c'est exactement ce que nous avons défini comme un front montant d'un signal de type bit. Tout simulateur traitera ce modèle comme prévu.

Note: Pour les synthétiseurs logiques, les choses sont un peu plus complexes, comme nous le verrons plus tard.

Front montant DFF avec réinitialisation active asynchrone et bit de type

Pour ajouter une réinitialisation active asynchrone à notre DFF, on pourrait essayer quelque chose comme:

signal clock, reset, d, q: bit;
...
P2_BOGUS: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif clock = '1' then
    q <= d;
  end if;
end process P2_BOGUS;

Mais cela ne fonctionne pas . La condition pour que l'attribution q <= d à exécuter soit: un front montant de l' clock tandis que reset = '0' . Mais ce que nous avons modélisé est:

  • clock ou reset ou à la fois changé et
  • reset = '0' et
  • clock = '1'

Ce qui n'est pas la même chose: si la reset passe de '1' à '0' alors que clock = '1' l'assignation sera exécutée alors qu'il ne s'agit pas d' un front montant de l' clock .

En fait, il n'y a aucun moyen de modéliser cela dans VHDL sans l'aide d'un attribut de signal:

P2_OK: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif clock = '1' and clock'event then
    q <= d;
  end if;
end process P2_OK;

Le clock'event est l'attribut de signal event appliqué pour signaler l' clock . Il est évalué comme un boolean et il est true si et seulement si l' clock signal a changé pendant la phase de mise à jour du signal qui a juste précédé la phase d'exécution en cours. Grâce à cela, le processus P2_OK modélise parfaitement ce que nous voulons en simulation (et en synthèse).

Sémantique de synthèse

De nombreux synthétiseurs logiques identifient les détections de fronts de signal basées sur des schémas syntaxiques et non sur la sémantique du modèle VHDL. En d'autres termes, ils considèrent ce à quoi ressemble le code VHDL, et non son comportement. L'un des modèles qu'ils reconnaissent tous est:

if clock = '1' and clock'event then

Donc, même dans l'exemple du processus P1 nous devrions l'utiliser si nous voulons que notre modèle soit synthétisable par tous les synthétiseurs logiques:

signal clock, d, q: bit;
...
P1_OK: process(clock)
begin
  if clock = '1' and clock'event then
    q <= d;
  end if;
end process P1_OK;

La partie and clock'event partie and clock'event de la condition sont complètement redondantes avec la liste de sensibilité mais comme certains synthétiseurs en ont besoin ...

DFF de front montant avec réinitialisation active asynchrone et type std_ulogic

Dans ce cas, l'expression du front montant de l'horloge et la condition de réinitialisation peuvent devenir compliquées. Si nous retenons la définition d'un front que nous avons proposée ci-dessus et si nous considérons que la réinitialisation est active si elle est '1' ou 'H' , le modèle devient:

library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4: process(clock, reset)
begin
  if reset = '1' or reset = 'H' then
    q <= '0';
  elsif clock'event and
        (clock'last_value = '0' or clock'last_value = 'L') and
        (clock = '1' or clock = 'H') then
    q <= d;
  end if;
end process P4;

Remarque: 'last_value est un autre attribut de signal qui renvoie la valeur que le signal avait avant la dernière modification de valeur.

Fonctions d'aide

La norme VHDL 2008 offre plusieurs fonctions d'assistance pour simplifier la détection des std_ulogic de signal, en particulier avec les types énumérés à plusieurs valeurs tels que std_ulogic . Le package std.standard définit les fonctions rising_edge et falling_edge sur les types bit et boolean et le package ieee.std_logic_1164 les définit sur les types std_ulogic et std_logic .

Remarque: avec les versions précédentes de VHDL, l'utilisation de ces fonctions peut nécessiter de déclarer explicitement l'utilisation de packages standard (par exemple, ieee.numeric_bit pour le type bit) ou même de les définir dans un package utilisateur.

Revenons aux exemples précédents et utilisons les fonctions d'aide:

signal clock, d, q: bit;
...
P1_OK_NEW: process(clock)
begin
  if rising_edge(clock) then
    q <= d;
  end if;
end process P1_OK_NEW;
signal clock, d, q: bit;
...
P2_OK_NEW: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif rising_edge(clock) then
    q <= d;
  end if;
end process P2_OK_NEW;
library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4_NEW: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif rising_edge(clock) then
    q <= d;
  end if;
end process P4_NEW;

Remarque: dans ce dernier exemple, nous avons également simplifié le test lors de la réinitialisation. Flottant, haute impédance, les réinitialisations sont assez rares et, dans la plupart des cas, cette version simplifiée fonctionne pour la simulation et la synthèse.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow