Подтвердить что ты не робот

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).

Какой-нибудь реальный опыт в этих двух? Любые предпочтения?

Спасибо!

4b9b3361

Ответ 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 для всего кода.