【问题标题】:What is the correct implementation of handling asynchronous signals in an FSM?在 FSM 中处理异步信号的正确实现是什么?
【发布时间】:2013-12-10 09:45:29
【问题描述】:

我们正在用 VHDL 实现一个以太网 MAC 控制器..

首先,这是我的代码的代码 sn-p..

-- next state
PROCESS(p_state, phy_start, phy_ctr, phy_clk)
BEGIN
    CASE p_state IS
        WHEN sIDLE =>
            IF(phy_start = '1' or rising_edge(phy_start)) THEN
                n_state <= sPRE;
            ELSIF(phy_start'event AND phy_start='0') THEN
                n_state <= n_state;
            ELSE
                n_state <= sIDLE;
            END IF;
     ............

问题是我的教授告诉我我将 phy_start 关联为时钟信号,其中rising_edge() 必须只与一个时钟关联,即 phy_clk。我想要发生的是当 phy_start 断言时,它将在下一个时钟周期进入 sPRE 状态。断言在时钟的上升沿完成。我试过了

    PROCESS(p_state, phy_start, phy_ctr, phy_clk)
BEGIN
    CASE p_state IS
        WHEN sIDLE =>
            IF(phy_start = '1') THEN
                n_state <= sPRE;
            ELSIF(phy_start'event AND phy_start='0') THEN
                n_state <= n_state;
            ELSE
                n_state <= sIDLE;
     .............

但它没有进入 phy_start = '1' 因为它发生在转换中..(我们称之为设置时间,在该时间段内数据必须稳定才能正确读取)。那么正确的实现是什么?或者,如果断言发生在上升沿,我别无选择,只能将 phy_start 断言 2 个时钟周期,或者 phy_start 必须在时钟的下降沿断言。另外,下一个状态逻辑的正确敏感度列表集是什么?

【问题讨论】:

    标签: vhdl hdl


    【解决方案1】:

    如果所有的时钟都在phy_clk 之下,你不应该在其他信号上使用rising_edge() 或'event。这些与时钟相关联,而不是与信号相关联。 如果您想检测以phy_clk 为时钟信号的信号何时上升,您应该这样进行:

    process(phy_clk,nreset)
    begin
      if nreset = '0' then
        phy_start_d <= '0';
      elsif phy_clk = '1' and phy_clk'event then
        phy_start_d <= phy_start;
      end if;
    end process;
    phy_start_p <= phy_start and not phy_start_d;
    

    phy_start_p 信号仅在phy_start 上升时设置为 1,并且与phy_clk 完全同步;

    【讨论】:

    • nreset 有什么用?
    • 您通常需要在开始时重置信号,以便从众所周知的配置开始。通常复位信号为低电平有效,复位的反相也是如此。出于这个原因,我将其称为 nreset(否定重置)。在这里你可以简单地删除它,但对于其他类型的设计,如果你一开始没有重置状态,你会遇到一些严重的问题。
    • phy_start 在时钟上升沿断言时的值是多少,因为您已经设计了您提供的逻辑?
    • 正如很多人已经说过的,如果 phy_start 应该是一个同步信号,它会在 phy_clk 信号的上升沿发生变化。您必须记住,信号的变化不是瞬时的,即使在模拟中 phy_start 之后也会改变一些增量......
    【解决方案2】:

    如果phy_start是由另一个进程同步创建的,那么你没有问题。

    只需在您的其他同步过程中读取它,并与您从上一个时钟周期存储的值进行比较,以检测信号何时从 0 变为 1

    process (phy_clk)
      variable last_start : std_logic := '0';
    begin
      if rising_edge(phy_clk) then
         if phy_start = '1' and last_start = '0' then
            -- do something in here
         end if;
         last_start := phy_start;
      end if;
    end process;
    

    【讨论】:

      【解决方案3】:

      最近有一个相关问题的答案,您可以在以下位置找到: how many processes i need to monitor two signals?

      记住 VHDL 用于描述硬件(设计)很有用,所以 综合工具可以转换描述以适应可用的硬件, 这通常是触发器(顺序设计)和门(组合 设计)。综合工具通常有一些建议 编写VHDL,所以硬件的翻译会顺利进行。

      对于具有异步复位 (rst) 和上升沿时钟 (clk) 的触发器,具有 由可选门生成的下一个值,VHDL 通常是:

      -- Template for flip flops
      process (clk, rst) is
      begin
        if rising_edge(clk) then
          -- Flip flops outputs updated on rising edge of clk
        end if;
        if rst = '1' then
          -- Flip flops outputs assigned with constant value when rst is '1'
        end if;
      end process;
      

      只有rstclk 应该在敏感列表中,所以使用其他信号 过程中的表达式不应包含在内。用于任何表达 生成触发器的值将被工具转换为门。

      触发器只能使用上升沿时钟,除非有良好的 原因使用下降沿时钟,甚至两个沿,因为只使用一个单一的 edge 将更容易进行时间约束。

      如果不使用异步重置,则将rst 从 敏感度列表并删除相关的 if 语句。

      对于纯门,VHDL 通常是,假设使用 VHDL-2008:

      -- Template for gates
      process (all) is
      begin
        -- Gates outputs updated based
      end process;
      

      或者对于简单的表达,只需删除该过程并编写:

      my_signal <= my_expression;
      

      那么回到具体的代码,那么就可以把这个写成单 以phy_clk 作为时钟的进程:

      PROCESS (phy_clk)
      BEGIN
          IF RISING_EDGE(phy_clk) THEN
              CASE p_state IS
                  WHEN sIDLE =>
                      p_state <= ...  -- New value for state based on signals
      

      当需要对信号的变化做出反应时,例如phy_start 从 '0' 到 '1',然后是具有phy_start 的单周期延迟版本的信号 可以制作,例如phy_start_ff,可以写成an表达式 在代码中:

      if (phy_start_ff = '0') and (phy_start = '1') then  -- phy_start from 0 to 1
        ..
      

      【讨论】:

      • phy_start 会在 phy_start 的上升沿被检测为“1”吗?
      • 描述假设所有状态变化都同步到单个时钟,假设为phy_clk。所以状态直到phy_clk 的上升沿才会更新,但如果phy_start 为“1”并且在之前的phy_clk 上升沿为“0”,则检测到更改。我用p_state(当前状态)更新的信息更新了上面的PROCESS (phy_clk)
      • 如果 phy_start 与 phy_clk 同时断言会怎样?在那种情况下,phy_start 尚未达到设置所需的最短时间,并且信号 phy_start 已在 if 条件中读取。它不会读取不确定的值吗?
      • @Xegara:描述还假设表达式中使用的所有信号都在phy_clk时钟域中,因为这是进行同步设计的条件,否则所需的设置时间不是确保,正如你所指出的。如果其他信号不在phy_clk域中,那么我认为您应该大致了解一下设计条件,并确定是否可以将信号同步到phy_clk,因为这将使设计变得更加简单。您可能想谷歌“vhdl 异步时钟域”,或查看eetimes.com/document.asp?doc_id=1276114
      • 所以您的意思是,将所有内容与 phy_clk 同步会导致设计更加简单。这是否也意味着补偿必须由其他 vhd 模块完成,例如 vhd 模块应该在时钟的下降沿断言 phy_start 或将其延长到两个时钟周期?
      猜你喜欢
      • 1970-01-01
      • 2015-05-31
      • 2013-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      相关资源
      最近更新 更多