Clk'event vs rising_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)
.
Какой-нибудь реальный опыт в этих двух? Любые предпочтения?
Спасибо!
Ответы
Ответ 1
rising_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, то raise_edge будет производить идентичный код. В противном случае вы можете интерпретировать разницу.
Лично мои часы идут только от 0 до 1 и наоборот. Я нахожу rising_edge(clk)
более описательным, чем вариант (clk'event and clk = '1')
.
Ответ 2
Связанный комментарий неверен: "L" - "1" будет выдавать нарастающий фронт.
Кроме того, если ваш синхронизирующий сигнал переходит от "H" в "1", rising_edge(clk)
будет (правильно) не запускаться, а (clk'event and clk = '1')
(неправильно) будет.
Конечно, это может показаться надуманным примером, но я видел, что тактовые сигналы часов делают это на реальном оборудовании из-за сбоев в другом месте.
Ответ 3
Практический пример:
Представьте, что вы моделируете что-то вроде шины I2C (сигналы, называемые SCL
для часов и SDA
для данных), где шина имеет три состояния и обе сети имеют слабое подтягивание. Ваш testbench должен моделировать нагрузочный резистор на печатной плате со значением "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
для всего кода.