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

Другие вопросы по тегам