clk'event vs rising_edge()

时间:2013-03-04 15:36:18

标签: vhdl

我一直用它来检测上升沿:

if (clk'event and clk='1') then

但也可以使用:

if rising_edge(clk) then

建议阅读this postrising_edge(clk),但还有a comment表示rising_edge(clk)可能导致错误行为。

我无法决定选择哪一个,继续使用(clk'event and clk='1')或采用rising_edge(clk)

对这两个人有任何真实的经历吗?任何偏好?

谢谢!

3 个答案:

答案 0 :(得分:35)

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,那么rising_edge将产生相同的代码。否则,你可以解释差异。

就个人而言,我的时钟只从0变为1,反之亦然。我发现rising_edge(clk)(clk'event and clk = '1')变种更具描述性。

答案 1 :(得分:14)

链接的注释不正确:'L'到'1'将产生上升沿。

此外,如果您的时钟信号从“H”转换为“1”,rising_edge(clk)将(正确)不会触发(clk'event and clk = '1')(错误)。

当然,这可能看起来像一个人为的例子,但我已经看到时钟波形在真实硬件中由于其他地方的故障而这样做。

答案 2 :(得分:11)

实际例子:

想象一下,你正在建模像I2C总线(时钟称为SCL,数据称为SDA),其中总线处于三态,两个网络都具有弱上拉。您的测试平台应该为PCB上的上拉电阻建模,其值为“H”。

scl <= 'H'; -- Testbench resistor pullup

您的I2C主设备或从设备可以将总线驱动为“1”或“0”,或者通过分配“Z”来保持总线

为SCL网络分配'1'将导致事件发生,因为SCL的值发生了变化。

  • 如果您有一行依赖于(scl'event and scl = '1')的代码,那么您将获得错误的触发器。

  • 如果您有一行依赖rising_edge(scl)的代码,那么 你不会得到错误的触发器。

继续示例:为SCL指定一个'0',然后指定一个'Z'。 SCL网络变为“0”,然后变回“H”。

这里,从'1'到'0'不会触发任何一种情况,但从'0'到'H'将触发rising_edge(scl)条件(正确),但是{{1} } case会错过它(不正确)。

一般建议:

对所有代码使用(scl'event and scl = '1')rising_edge(clk)代替falling_edge(clk)