raise_edge() 与进程敏感度列表

use*_*172 3 spartan fpga vhdl

我在大学课程中使用 VHDL 进行了一段时间的开发,我认为我了解它的工作原理,但有时我意识到我实际上并不了解它。

这是我的问题:

正如我所理解的,如果一个信号在进程的敏感列表中,那么只要该信号改变值,该进程就会“执行”。

所以我问,这2段代码有什么区别:

process(clk) is
begin
  if(clk = '1') then
      --Do Something
  end if;
end process;
Run Code Online (Sandbox Code Playgroud)

process(clk) is
begin
   if(rising_edge(clk)) then
      --Do Something
   end if;
end process;
Run Code Online (Sandbox Code Playgroud)

他们不应该表现得一样吗?

gro*_*rel 5

模拟:

让我们看看 VHDL 信号值是如何在 VHDL 中定义的。您将在ieee.std_logic_1164库中找到这些定义。

通常,信号被声明为std_logic以下std_ulogic定义的解析子类型:

  type STD_ULOGIC is ( 'U',             -- Uninitialized
                       'X',             -- Forcing  Unknown
                       '0',             -- Forcing  0
                       '1',             -- Forcing  1
                       'Z',             -- High Impedance   
                       'W',             -- Weak     Unknown
                       'L',             -- Weak     0       
                       'H',             -- Weak     1       
                       '-'              -- Don't care
                       );
Run Code Online (Sandbox Code Playgroud)

我们可以看到,这种信号除了通常的“0”和“1”之外,还可以有其他几个值。您的两个流程之间的区别就在这里。

现在让我们看看rising_edge函数是如何定义的,总是在 std_logic_1164 库中:

  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 rising_edge;

  function To_X01 (s : STD_ULOGIC) return X01 is
  begin
    return (cvt_to_x01(s));
  end function To_X01;

  ----------------------------------------------------------
  -- table name : cvt_to_x01
  --
  -- parameters :
  --        in  :  std_ulogic  -- some logic value
  -- returns    :  x01         -- state value of logic value
  -- purpose    :  to convert state-strength to state only
  --                  
  -- example    : if (cvt_to_x01 (input_signal) = '1' ) then ...
  --
  ----------------------------------------------------------
  constant cvt_to_x01 : logic_x01_table := (
    'X',                                -- 'U'
    'X',                                -- 'X'
    '0',                                -- '0'
    '1',                                -- '1'
    'X',                                -- 'Z'
    'X',                                -- 'W'
    '0',                                -- 'L'
    '1',                                -- 'H'
    'X'                                 -- '-'
    );
Run Code Online (Sandbox Code Playgroud)

该函数实际上将信号值转换为“X”或“0”或“1”。并且该函数仅在转换后的新值为“1”且转换后的最后值为“0”时才为真。

那么该rising_edge函数仅对以下几对 [last_value;value] 为真:

  • [0;1]
  • [L;1]
  • [0;H]
  • [L;H]

所有其他条件都无效。

合成:

[编辑以删除虚假信息]

正如@user1155120 在主要帖子评论中所解释的:

缺少信号分配,这两个过程都不​​会产生模拟事件。缺少分配目标,第一个在综合中不会产生电平敏感的时序逻辑(透明锁存器)。缺少分配目标,第二个在综合中不会产生边沿触发的时序逻辑(寄存器)。与 grorel 的 Quartus prime 不同,其他综合工具不能保证为他的输出生成寄存器1。请参阅 IEEE Std 1076.6-2004(已撤销)6.1.2.1 上升(正)沿时钟。,6.2.1.1 来自带有敏感列表的进程的电平敏感存储(需要敏感列表中的输入信号)。

output1 生成如下:

process(clk) is
begin
  if(clk = '1') then
      output1 <= input1;
  end if;
end process;
Run Code Online (Sandbox Code Playgroud)

您必须在您的过程中使用边缘检测来确保寄存器创建良好。

  • @JHBonarius 问题不在于它是否可合成,因为所有工具都会产生结果——问题在于可移植性——一些创建锁存器(因为它们忽略敏感列表——或者将其视为进程(所有)),而其他人创建触发器(预期的结果)。我们作为用户对这个问题无能为力,因为我的理解是这归结为专利合成算法。 (3认同)
  • @JHBonarius 您与 Xilinx 的对话称为营销驱动语言支持。他们得出这个结论是因为人们抱怨的不够多。因此,开始抱怨和提交错误报告。如果我们保持现状,工具之间就没有可移植性——对供应商来说不是那么糟糕——对用户社区来说是糟糕的。Xilinx 示例是否仍在使用 std_logic_arith 和 std_logic_unsigned?既然你建议遵循他们的指南,你是否也建议使用这些? (2认同)