event - falling edge vhdl
clk''event vs rising_edge() (3)
Siempre lo había usado para detectar un flanco ascendente:
if (clk''event and clk=''1'') then
pero esto también se puede usar:
if rising_edge(clk) then
Al leer esta publicación , se recomienda rising_edge(clk)
, pero también hay un comentario que indica que rising_edge(clk)
podría generar un comportamiento incorrecto.
No puedo decidir cuál elegir para el futuro, continuar con (clk''event and clk=''1'')
o adoptar rising_edge(clk)
.
¿Alguna experiencia en el mundo real sobre estos dos? ¿Alguna preferencia?
¡Gracias!
El comentario vinculado es incorrecto: ''L'' a ''1'' producirá un flanco ascendente.
Además, si la señal del reloj pasa de ''H'' a ''1'', rising_edge(clk)
activará (correctamente) mientras (clk''event and clk = ''1'')
(incorrectamente) lo hará.
Por supuesto, eso puede parecer un ejemplo artificial, pero he visto formas de onda de reloj hacer eso en hardware real, debido a fallas en otros lugares.
rising_edge se define como:
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 su reloj solo va de 0 a 1, y de 1 a 0, rising_edge producirá un código idéntico. De lo contrario, puedes interpretar la diferencia.
Personalmente, mis relojes solo van de 0 a 1 y viceversa. Encuentro rising_edge(clk)
para ser más descriptivo que la (clk''event and clk = ''1'')
.
Ejemplo práctico:
Imagine que está modelando algo así como un bus I2C (señales llamadas SCL
para reloj y SDA
para datos), donde el bus es tri-estado y ambas redes tienen un pull-up débil. Su banco de pruebas debe modelar la resistencia pull-up en la PCB con un valor de ''H''.
scl <= ''H''; -- Testbench resistor pullup
Su maestro I2C o dispositivos esclavos pueden conducir el autobús a ''1'' o ''0'' o dejarlo en paz asignando una ''Z''
Asignar un ''1'' a la red SCL hará que ocurra un evento, porque el valor de SCL cambió.
Si tiene una línea de código que depende de
(scl''event and scl = ''1'')
, obtendrá un desencadenador falso.Si tiene una línea de código que depende de
rising_edge(scl)
, no obtendrá un desencadenador falso.
Continuando con el ejemplo: asigne un ''0'' a SCL, luego asigne una ''Z''. La red SCL va a ''0'', luego vuelve a ''H''.
Aquí, pasar de ''1'' a ''0'' no desencadena ningún caso, pero pasar de ''0'' a ''H'' desencadenará una rising_edge(scl)
(correcta), pero el (scl''event and scl = ''1'')
caso se perderá (incorrecto).
Recomendación general:
Utilice rising_edge(clk)
y falling_edge(clk)
lugar de clk''event
para todo el código.