我在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%的代码覆盖率。我发现了两个问题:
要求涵盖其他案例,因为所有选择都完全涵盖了枚举,因此不需要。但是这个分支是无法访问的...... 为什么QuestaSim期望覆盖这个分支?
QuestaSim显示了我的示例FSM的错误状态图。该图包含状态的自我边缘:RUNNING
和FINISH
。这些边缘不存在,也不能被覆盖
如果我删除默认作业fsm_ns <= fsm_cs;
并在IDLE状态下添加其他分支,我将获得全面覆盖。
if req = '1' then
fsm_ns <= RUNNING;
else
fsm_ns <= IDLE;
end if;
为什么状态图显示错误的边缘以及为什么我不能使用默认分配?
我可以忍受子弹项目1,但是项目2是个问题。如果我以这种方式编写FSM,我会复制很多不需要的代码,大多数合成器都无法识别FSM模式!所以我将失去FSM优化并检查合成。
答案 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;代码未被错误地记录在最后一个案例组null
翻译为“nop”。将覆盖范围挂钩到。很抱歉,我无法在这里阐明Modelsim的行为。
但是,存在但无法访问的代码 - &#34;死代码&#34; - 被视为代表高完整性实践中的设计错误,所以我认为Modelsim是正确的以突出它,而ghdl在不支持的情况下是不正确的。
它与安全状态机设计的问题有些相关,其中SEU(可能来自宇宙射线)破坏了状态寄存器。请注意,如果STATES
成员少于2 **,则会有一个&#34;其他&#34;状态,并且null
动作,如果它到达那个状态,它将锁定那里。 (但是,删除&#34;其他&#34;条款不会纠正它,并且综合工具可能会结束&#34;其他&#34;子句无法访问并且无论如何都要将其删除。安全的SM设计是另一个主题)
答案 1 :(得分:1)
按预期显示其他人未被覆盖的时间。您可以使用以下方法将其排除:
-- coverage off
when others => null;
-- coverage on
我在每个案例陈述中都这样做,其他案例不可能 击中。
if
状态中的IDLE
条件具有100%的分支覆盖率,即使没有其他分支(Active: 4, True Hits: 1, AllFalse: 3)
也是如此。对于100%FSM覆盖率,您应该通过复位信号排除隐式更改,或者您必须在每个FSM状态下拉出复位。编译时,可以使用-nofsmresettrans
swith排除重置状态更改。我使用Modelsim DE 10.5c和10.6以及Questa 10.6获得相同的行为。
BTW:如果FSM的某些部分位于依赖于泛型的生成块内,我无法获得FSM覆盖,所以我不得不取消生成内容,只留下一个重置进程。我认为这是一个Modelsim / Questa限制,它不能识别生成块内的FSM,但我不是。该帮助还暗示使用泛型的FSM未被识别。也许就是这种情况。