You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免VHDL并发断言在输入变化时误触发?附全加器示例

解决VHDL并发断言频繁触发的问题

我太懂这种困扰了——并发断言会对表达式里所有信号的变化立刻做出响应,所以每次输入(X/Y/Cin)跳变时,哪怕只是过渡瞬间,它都会跑一遍检查,导致报告满天飞。针对你的全加器例子,我给你几个实用的解决思路:

方案1:把断言移到测试台,完全控制检查时机

最推荐的做法是把验证逻辑从DUT里剥离,放到测试台中,只在输入信号稳定后再执行断言检查。这样既能保持DUT的简洁(不混入验证代码),又能精准控制检查时机。

修改后的DUT(移除断言)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity Full_Adder is
port( X, Y, Cin : in std_logic;
sum, Cout : out std_logic);
end Full_Adder;
architecture bhv of Full_Adder is
signal s_sum : std_logic:='0';
signal s_Cout : std_logic:='0';
begin
s_sum <= (X xor Y) xor Cin;
s_Cout <= (X and (Y or Cin)) or (Cin and Y);
sum<=s_sum;
Cout<=s_Cout;
end bhv;

修改后的测试台(添加定时断言)

Library IEEE;
USE IEEE.Std_logic_1164.all;
entity tb_fulladder is
end tb_fulladder;
architecture behavioral of tb_fulladder is
component Full_Adder
port( X, Y, Cin : in std_logic;
sum, Cout : out std_logic
);
end component;
signal A,B,Cin: std_logic:='0';
signal S,Cout: std_logic;
begin
structural_adder: Full_Adder port map (
X => A,
Y => B,
Cin => Cin,
sum => S,
Cout => Cout
);
process
begin
-- 测试向量1
A <= '0'; B <= '0'; Cin <= '0'; wait for 100 ns;
assert (S = ((A xor B) xor Cin)) report "Erreur de somme pour (0,0,0)" severity note;
assert (Cout = ((A and (B or Cin)) or (Cin and B))) report "Erreur de retenue pour (0,0,0)" severity note;

-- 测试向量2
A <= '0'; B <= '0'; Cin <= '1'; wait for 100 ns;
assert (S = ((A xor B) xor Cin)) report "Erreur de somme pour (0,0,1)" severity note;
assert (Cout = ((A and (B or Cin)) or (Cin and B))) report "Erreur de retenue pour (0,0,1)" severity note;

-- 测试向量3
A <= '0'; B <= '1'; Cin <= '0'; wait for 100 ns;
assert (S = ((A xor B) xor Cin)) report "Erreur de somme pour (0,1,0)" severity note;
assert (Cout = ((A and (B or Cin)) or (Cin and B))) report "Erreur de retenue pour (0,1,0)" severity note;

-- 测试向量4
A <= '0'; B <= '1'; Cin <= '1'; wait for 100 ns;
assert (S = ((A xor B) xor Cin)) report "Erreur de somme pour (0,1,1)" severity note;
assert (Cout = ((A and (B or Cin)) or (Cin and B))) report "Erreur de retenue pour (0,1,1)" severity note;

-- 测试向量5
A <= '1'; B <= '0'; Cin <= '0'; wait for 100 ns;
assert (S = ((A xor B) xor Cin)) report "Erreur de somme pour (1,0,0)" severity note;
assert (Cout = ((A and (B or Cin)) or (Cin and B))) report "Erreur de retenue pour (1,0,0)" severity note;

-- 测试向量6
A <= '1'; B <= '0'; Cin <= '1'; wait for 100 ns;
assert (S = ((A xor B) xor Cin)) report "Erreur de somme pour (1,0,1)" severity note;
assert (Cout = ((A and (B or Cin)) or (Cin and B))) report "Erreur de retenue pour (1,0,1)" severity note;

-- 测试向量7
A <= '1'; B <= '1'; Cin <= '0'; wait for 100 ns;
assert (S = ((A xor B) xor Cin)) report "Erreur de somme pour (1,1,0)" severity note;
assert (Cout = ((A and (B or Cin)) or (Cin and B))) report "Erreur de retenue pour (1,1,0)" severity note;

-- 测试向量8
A <= '1'; B <= '1'; Cin <= '1'; wait for 100 ns;
assert (S = ((A xor B) xor Cin)) report "Erreur de somme pour (1,1,1)" severity note;
assert (Cout = ((A and (B or Cin)) or (Cin and B))) report "Erreur de retenue pour (1,1,1)" severity note;

wait; -- 终止测试进程
end process;
end behavioral;

方案2:在DUT中添加触发信号,按需启用断言

如果必须在DUT中保留断言,可以新增一个check_enable输入信号,只有当该信号有效时,断言才会执行。测试台可以在输入稳定后拉高这个信号,触发检查。

修改后的DUT(带触发信号)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity Full_Adder is
port( 
    X, Y, Cin : in std_logic;
    check_enable : in std_logic; -- 新增断言触发信号
    sum, Cout : out std_logic
);
end Full_Adder;
architecture bhv of Full_Adder is
signal s_sum : std_logic:='0';
signal s_Cout : std_logic:='0';
begin
s_sum <= (X xor Y) xor Cin;
s_Cout <= (X and (Y or Cin)) or (Cin and Y);
sum<=s_sum;
Cout<=s_Cout;

-- 仅当check_enable为'1'时执行断言检查
assert (check_enable = '0' or s_sum =((X xor Y) xor Cin)) 
    report "Erreur de somme" severity note;
assert (check_enable = '0' or s_Cout = ((X and (Y or Cin)) or (Cin and Y))) 
    report "Erreur de retenue" severity note;
end bhv;

修改后的测试台(控制触发信号)

Library IEEE;
USE IEEE.Std_logic_1164.all;
entity tb_fulladder is
end tb_fulladder;
architecture behavioral of tb_fulladder is
component Full_Adder
port( 
    X, Y, Cin : in std_logic;
    check_enable : in std_logic;
    sum, Cout : out std_logic
);
end component;
signal A,B,Cin, check_en: std_logic:='0';
signal S,Cout: std_logic;
begin
structural_adder: Full_Adder port map (
X => A,
Y => B,
Cin => Cin,
check_enable => check_en,
sum => S,
Cout => Cout
);
process
begin
check_en <= '0'; -- 默认关闭断言检查

-- 测试向量1
A <= '0'; B <= '0'; Cin <= '0'; wait for 90 ns;
check_en <= '1'; wait for 10 ns; -- 稳定后开启检查
check_en <= '0';

-- 测试向量2
A <= '0'; B <= '0'; Cin <= '1'; wait for 90 ns;
check_en <= '1'; wait for 10 ns;
check_en <= '0';

-- 剩余测试向量重复上述逻辑即可...

wait;
end process;
end behavioral;

方案3:在DUT中延迟检查(适合组合逻辑)

对于纯组合逻辑,可以在断言前引入一个小延迟,确保输入变化后的过渡态消失后再执行检查。不过这种方法依赖于具体时序,灵活性较差:

-- 在DUT的架构中添加带延迟的进程
process(X, Y, Cin)
begin
    wait for 1 ns; -- 等待信号稳定(时间需根据实际设计调整)
    assert (s_sum =((X xor Y) xor Cin)) report "Erreur de somme" severity note;
    assert (s_Cout = ((X and (Y or Cin)) or (Cin and Y))) report "Erreur de retenue" severity note;
end process;

总结

优先推荐方案1,这种方式既能保证DUT的纯净性,又能完全掌控断言的触发时机,是验证领域的通用做法。如果必须在DUT中保留断言,方案2的触发信号方式更可靠,适合需要复用DUT的多场景测试。

内容的提问来源于stack exchange,提问作者Basil1402

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 21:33:12