为什么此FSM未达到100%的代码覆盖率?

时间:2017-02-06 23:34:44

标签: vhdl code-coverage modelsim questasim

我在VHDL中有以下简单的FSM描述:

library ieee;
use ieee.std_logic_1164.all;

entity coverage1 is
  port (
    clk : in  std_logic;
    rst : in  std_logic;
    req : in  std_logic;
    ack : out std_logic
  );
end entity coverage1;

architecture rtl of coverage1 is
  type STATES is (IDLE, RUNNING, FINISH);
  signal fsm_cs : STATES := IDLE;
  signal fsm_ns : STATES;
begin

  process (fsm_cs, req) is
  begin
    fsm_ns <= fsm_cs;
    ack    <= '0';

    case fsm_cs is
      when IDLE =>
        if req = '1' then
          fsm_ns <= RUNNING;
        end if;

      when RUNNING =>
        fsm_ns <= FINISH;

      when FINISH =>
        ack <= '1';
        fsm_ns <= IDLE;

      when others =>
              null;
    end case;
  end process;

  process (clk) is
  begin
    if rising_edge(clk) then
      if rst = '1' then
        fsm_cs <= IDLE;
      else
        fsm_cs <= fsm_ns;
      end if;
    end if;
  end process;
end architecture;

这个测试台:

library ieee;
use ieee.std_logic_1164.all;

entity coverage1_tb is
end entity coverage1_tb;

architecture tb of coverage1_tb is
  signal clk : std_logic := '1';
  signal rst : std_logic;
  signal req : std_logic;
  signal ack : std_logic;

  signal finished : boolean := false;
begin
  coverage1_1: entity work.coverage1
    port map (
      clk => clk,
      rst => rst,
      req => req,
      rdy => rdy,
      ack => ack);

  clk <= not clk after 5 ns when not finished else unaffected;

  process
  begin
    rst <= '1';
    wait until rising_edge(clk);
    rst <= '0';
    req <= '0';
    wait until rising_edge(clk);
    req <= '1';
    wait until rising_edge(clk);
    req <= '0';
    wait until rising_edge(clk) and ack = '1';
    wait until rising_edge(clk);
    finished <= true;
    wait;
  end process;
end architecture tb;

FSM未在ModelSim / QuestaSim中达到100%的代码覆盖率。我发现了两个问题:

  1. 要求涵盖其他案例,因为所有选择都完全涵盖了枚举,因此不需要。但是这个分支是无法访问的...... 为什么QuestaSim期望覆盖这个分支?

  2. QuestaSim显示了我的示例FSM的错误状态图。该图包含状态的自我边缘:RUNNINGFINISH。这些边缘不存在,也不能被覆盖 如果我删除默认作业fsm_ns <= fsm_cs;并在IDLE状态下添加其他分支,我将获得全面覆盖。

    if req = '1' then
      fsm_ns <= RUNNING;
    else
      fsm_ns <= IDLE;
    end if;
    

    为什么状态图显示错误的边缘以及为什么我不能使用默认分配?

  3. 我可以忍受子弹项目1,但是项目2是个问题。如果我以这种方式编写FSM,我会复制很多不需要的代码,大多数合成器都无法识别FSM模式!所以我将失去FSM优化并检查合成。

2 个答案:

答案 0 :(得分:2)

一些观察结果,再次使用ghdl。

评论rdy端口,ghdl再次报告100%的覆盖率。

具有讽刺意味的是null in&#34;其他&#34;条款获得20次点击......这是可疑的。由于它是该过程中的最后一个活动线,我相信任何唤醒过程但不做任何事情的事件都会记录在这里。

null;收集这20个点击后添加了end case,确认了这一点 - 但others案例仍未被记录为覆盖漏洞(尽管没有点击)。我的假设是,因为null没有生成代码,所以不会被跟踪。向fsm_ns <= IDLE;分支添加无害但可跟踪的操作when others现在会产生一个覆盖漏洞(当null移除后end case时,会出现虚假命中。

摘要:

  • 值得测试一个主动语句作为跟踪when others中的覆盖范围以及null之后的end case的效果,以便&#34;结束处理&#34;代码未被错误地记录在最后一个案例组
  • ghdl需要在这两个方面进行一些整理,或许将null翻译为“nop”。将覆盖范围挂钩到。

enter image description here

很抱歉,我无法在这里阐明Modelsim的行为。

但是,存在但无法访问的代码 - &#34;死代码&#34; - 被视为代表高完整性实践中的设计错误,所以我认为Modelsim是正确的以突出它,而ghdl在不支持的情况下是不正确的。

它与安全状态机设计的问题有些相关,其中SEU(可能来自宇宙射线)破坏了状态寄存器。请注意,如果STATES成员少于2 **,则会有一个&#34;其他&#34;状态,并且null动作,如果它到达那个状态,它将锁定那里。 (但是,删除&#34;其他&#34;条款不会纠正它,并且综合工具可能会结束&#34;其他&#34;子句无法访问并且无论如何都要将其删除。安全的SM设计是另一个主题)

答案 1 :(得分:1)

  1. 按预期显示其他人未被覆盖的时间。您可以使用以下方法将其排除:

    -- coverage off
    when others => null;
    -- coverage on
    

    我在每个案例陈述中都这样做,其他案例不可能 击中。

  2. 即使没有其他分支,我也能获得100%的州覆盖率。 if状态中的IDLE条件具有100%的分支覆盖率,即使没有其他分支(Active: 4, True Hits: 1, AllFalse: 3)也是如此。对于100%FSM覆盖率,您应该通过复位信号排除隐式更改,或者您必须在每个FSM状态下拉出复位。编译时,可以使用-nofsmresettrans swith排除重置状态更改。
  3. 我使用Modelsim DE 10.5c和10.6以及Questa 10.6获得相同的行为。

    BTW:如果FSM的某些部分位于依赖于泛型的生成块内,我无法获得FSM覆盖,所以我不得不取消生成内容,只留下一个重置进程。我认为这是一个Modelsim / Questa限制,它不能识别生成块内的FSM,但我不是。该帮助还暗示使用泛型的FSM未被识别。也许就是这种情况。