【问题标题】:clk'event vs rising_edge()clk'event vs 上升沿()
【发布时间】:2013-02-18 18:08:58
【问题描述】:

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

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)

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

谢谢!

【问题讨论】:

  • “if(rising_edge(clk))”可以在子程序体中使用吗?
  • @VineetDeoraj 当然可以。在某些情况下,它可能没有意义或不可综合(例如,如果在由不同时钟触发的进程中调用子程序)但这是另一回事。

标签: vhdl


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

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

【讨论】:

  • 在仿真启动时,如果你的时钟从'U'变为'1',rising_edge(clk) 将为假,但手写边沿检测“event and 1”将为真。在这种特定情况下,rising_edge 会更安全。
  • if (clk'last_value='0' and clk='1') then 会做同样的事情吗?
  • 这是一个有争议的评论——很好,因为它给出了rising_edge() 机制的清晰定义;对从“H”到 1 和从“1”到 L 转换的rising_edge() 的优势感到矛盾,这是完全错误的。我的选择 - 没有充分的理由使用“事件和 1”构造 - 完全同意 Iain Waugh 的回答。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    实例:

    假设您正在建模类似 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)falling_edge(clk) 而不是clk'event

    【讨论】:

    • 您的示例成功地证明了设计描述不使用器件引脚缓冲区的谬误。在现实生活中,当触发器复位未被断言时,除了“X”、“0”或“1”之外,您不会传播任何东西到触发器的时钟输入。该问题不是由使用特定的 IEEE Std 1076.6-2004 批准的边缘敏感时序逻辑表示方法引起的。问题是特定供应商是否会允许 TO_X01(scl) 作为正式的或类似的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-20
    • 2014-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多