43

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

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)

有这两个方面的实际经验吗?有什么偏好吗?

谢谢!

4

3 回答 3

38

上升沿定义为:

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')变体更具描述性。

于 2013-03-04T16:11:54.010 回答
18

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

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

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

于 2013-03-04T16:31:03.803 回答
13

实际例子:

想象一下,您正在建模类似 I2C 总线(SCL需要时钟和SDA数据的信号),其中总线是三态的,并且两个网络都有弱上拉。您的测试台应该对 PCB 上的上拉电阻建模,其值为“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)andfalling_edge(clk)而不是clk'event所有代码。

于 2013-08-06T23:45:41.270 回答