web-dev-qa-db-fra.com

clk'event vs rising_Edge ()

J'avais toujours utilisé cela pour détecter un front montant:

if (clk'event and clk='1') then

mais cela peut aussi être utilisé:

if rising_Edge(clk) then

La lecture this post , rising_Edge(clk) est recommandée, mais il y a aussi n commentaire indiquant que rising_Edge(clk) pourrait provoquer un comportement incorrect.

Je ne peux pas décider lequel choisir pour l'avenir, continuer avec (clk'event and clk='1') Ou adopter rising_Edge(clk).

Toute expérience réelle sur ces deux? Des préférences?

Merci!

36
Diego Herranz

rising_Edge est défini comme:

FUNCTION rising_Edge  (SIGNAL s : std_ulogic) RETURN BOOLEAN IS
BEGIN
    RETURN (s'EVENT AND (To_X01(s) = '1') AND
                        (To_X01(s'LAST_VALUE) = '0'));
END;

FUNCTION To_X01  ( s : std_ulogic ) RETURN  X01 IS
BEGIN
    RETURN (cvt_to_x01(s));
END;

CONSTANT cvt_to_x01 : logic_x01_table := (
                     'X',  -- 'U'
                     'X',  -- 'X'
                     '0',  -- '0'
                     '1',  -- '1'
                     'X',  -- 'Z'
                     'X',  -- 'W'
                     '0',  -- 'L'
                     '1',  -- 'H'
                     'X'   -- '-'
                    );

Si votre horloge ne passe que de 0 à 1 et de 1 à 0, rising_Edge produira un code identique. Sinon, vous pouvez interpréter la différence.

Personnellement, mes horloges vont seulement de 0 à 1 et vice versa. Je trouve que rising_Edge(clk) est plus descriptif que la variante (clk'event and clk = '1').

35
Bill Lynch

Le commentaire lié est incorrect: "L" à "1" produira un bord montant.

De plus, si votre signal d'horloge passe de 'H' à '1', rising_Edge(clk) ne se déclenchera pas (correctement) pendant que (clk'event and clk = '1') (incorrectement) le fera.

Certes, cela peut sembler être un exemple artificiel, mais j’ai vu des formes d’horloge le faire dans du matériel réel, en raison de défaillances constatées ailleurs.

14
Brian Drummond

Exemple pratique:

Imaginez que vous modélisez quelque chose comme un bus I2C (signaux appelés SCL pour horloge et SDA pour données), où le bus est à trois états et où les deux réseaux ont une faible remontée. Votre banc d’essai doit modéliser la résistance de rappel sur le PCB avec la valeur 'H').

scl <= 'H'; -- Testbench resistor pullup

Votre maître ou esclave I2C peut piloter le bus sur "1" ou "0" ou le laisser tranquille en affectant un "Z"

L'attribution d'un "1" au réseau SCL provoquera un événement, car la valeur de SCL a changé.

  • Si vous avez une ligne de code qui repose sur (scl'event and scl = '1'), Vous obtiendrez un faux déclencheur.

  • Si vous avez une ligne de code qui repose sur rising_Edge(scl), vous n'obtiendrez pas de faux déclencheur.

En reprenant l'exemple, vous affectez un "0" à SCL, puis un "Z". Le réseau SCL passe à "0", puis revient à "H".

Ici, passer de '1' à '0' ne déclenche aucun cas, mais aller de '0' à 'H' va déclencher une condition rising_Edge(scl) (correcte), mais le (scl'event and scl = '1') le cas va manquer (incorrect).

Recommandation générale:

Utilisez rising_Edge(clk) et falling_Edge(clk) au lieu de clk'event Pour tout le code.

11
Iain Waugh