clk'event vsising_edge()
Я всегда использовал это для обнаружения нарастающего фронта:
if (clk'event and clk='1') then
но это также может быть использовано:
if rising_edge(clk) then
Читая этот пост, rising_edge(clk)
рекомендуется, но есть также комментарий, указывающий, что rising_edge(clk)
может привести к неправильному поведению.
Я не могу решить, какой из них выбрать для будущего, продолжая с (clk'event and clk='1')
или принимая rising_edge(clk)
,
Есть ли опыт этих двух в реальном мире? Любые предпочтения?
Спасибо!
3 ответа
ising_edge определяется как:
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' -- '-'
);
Если ваши часы идут только от 0 до 1 и от 1 до 0, то восходящий_эдр выдаст идентичный код. В противном случае вы можете интерпретировать разницу.
Лично мои часы идут только от 0 до 1 и наоборот. я нахожу rising_edge(clk)
быть более наглядным, чем (clk'event and clk = '1')
вариант.
Связанный комментарий неверен: от 'L' до '1' приведет к нарастающему фронту.
Кроме того, если ваш тактовый сигнал переходит от "H" к "1", rising_edge(clk)
(правильно) не сработает, пока (clk'event and clk = '1')
(неправильно) будет.
Конечно, это может выглядеть как надуманный пример, но я видел, как тактовые сигналы делают это на реальном оборудовании из-за сбоев в других местах.
Практический пример:
Представьте, что вы моделируете что-то вроде шины I2C (сигналы называются SCL
для часов и SDA
для данных), где шина имеет три состояния, и обе сети имеют слабую нагрузку. Ваш испытательный стенд должен смоделировать нагрузочный резистор на плате со значением "H".
scl <= 'H'; -- Testbench resistor pullup
Ваши ведущие или подчиненные устройства I2C могут подвести шину к "1" или "0" или оставить ее в покое, назначив "Z"
Назначение "1" сети SCL вызовет событие, потому что значение SCL изменилось.
Если у вас есть строка кода, которая опирается на
(scl'event and scl = '1')
тогда вы получите ложный триггер.Если у вас есть строка кода, которая опирается на
rising_edge(scl)
, тогда вы не получите ложный триггер.
Продолжая пример: вы назначаете "0" для SCL, затем назначаете "Z". Сеть SCL переходит в "0", затем обратно в "H".
Здесь переход от "1" к "0" не вызывает ни того, ни другого случая, но переход от "0" к "H" вызовет rising_edge(scl)
условие (правильное), но (scl'event and scl = '1')
дело пропустит (неверно).
Общая рекомендация:
использование rising_edge(clk)
а также falling_edge(clk)
вместо clk'event
для всего кода.