紧凑型 1 位 ALU 行为中的问题
Issues in compact 1-bit ALU behavior
我尝试为实现逻辑运算、全加器和全减器的 1 位 ALU 编写紧凑的代码。编译看起来不错,但它不会在测试台结束时断言 "Test done."
消息。此外,变量中逻辑值的变化,如A、B和F,本应导致测试台出错的,对程序来说是不变的,因为它不会报告任何错误。主设计肯定有问题,但我找不到问题。
在testbench中,我只是测试了每个功能的一些案例。
library IEEE;
use IEEE.std_logic_1164.all;
entity ALU is
port(A,B : in bit; -- operands
S : in bit_vector(2 downto 0);
F: out bit; -- output
carryIn: in bit;
carryOut: out bit);
end ALU;
architecture behavior of ALU is
begin
process(S)
begin
case (S) is
when "000" => if carryIn = '1' then F <= A XOR B XOR carryIn; -- Full Adder
carryOut <= (A AND B) OR (carryIn AND A) OR (carryIn AND B);
end if;
when "001" => if carryIn = '1' then F <= (A XOR B) XOR carryIn; -- Full Subtractor
carryOut <= ((NOT A) AND (B OR carryIn)) OR (B AND carryIn);
end if;
when "010" => F <= A AND B;
when "011" => F <= A OR B;
when "100" => F <= A NAND B;
when "101" => F <= A NOR B;
when "110" => F <= A XOR B;
when "111" => F <= A XNOR B;
end case;
end process;
end behavior ;
测试平台
library IEEE;
use IEEE.std_logic_1164.all;
entity testbench is
end testbench;
architecture tb of testbench is
component ALU is
port(A,B : in bit;
S : in bit_vector(2 downto 0);
F: out bit;
carryIn: in bit;
carryOut: out bit);
end component;
signal A, B, F, carryIn, carryOut: bit;
signal S : bit_vector(2 downto 0);
begin
DUT: ALU port map (A => A, B => B, F => F, carryIn => carryIn, carryOut => carryOut, S => S);
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail AND1" severity error;
wait;
S <= "010";
A <= '0';
B <= '1';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail AND2" severity error;
wait;
-- OR
S <= "011";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail OR1" severity error;
wait;
S <= "011";
A <= '0';
B <= '1';
carryIn <= '0';
assert(F ='1' and carryOut = '0') report "Fail OR2" severity error;
wait;
-- NAND
S <= "100";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='1' and carryOut = '0') report "Fail NAND1" severity error;
wait;
S <= "100";
A <= '1';
B <= '1';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail NAND2" severity error;
wait;
-- NOR
S <= "101";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='1' and carryOut = '0') report "Fail NOR1" severity error;
wait;
S <= "101";
A <= '1';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail NOR2" severity error;
wait;
-- XOR
S <= "110";
A <= '0';
B <= '1';
carryIn <= '0';
assert(F ='1' and carryOut = '0') report "Fail XOR1" severity error;
wait;
S <= "110";
A <= '1';
B <= '0';
carryIn <= '0';
assert(F ='1' and carryOut = '0') report "Fail XOR2" severity error;
wait;
-- XNOR
S <= "111";
A <= '0';
B <= '1';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail XNOR1" severity error;
wait;
S <= "111";
A <= '1';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail XNOR2" severity error;
wait;
-- Full Adder
S <= "000";
A <= '0';
B <= '0';
carryIn <= '1';
assert(F ='1' and carryOut = '0') report "Fail FullAdder1" severity error;
wait;
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
assert(F ='1' and carryOut = '1') report "Fail FullAdder2" severity error;
wait;
-- Full Subtractor
S <= "000";
A <= '0';
B <= '1';
carryIn <= '1';
assert(F ='0' and carryOut = '1') report "Fail Subtractor1" severity error;
wait;
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
assert(F ='1' and carryOut = '1') report "Fail Subtractor2" severity error;
wait;
assert false report "Test done." severity note;
wait;
end process;
end tb;
编辑
library IEEE;
use IEEE.std_logic_1164.all;
entity testbench is
end testbench;
architecture tb of testbench is
component ALU is
port(A,B : in bit;
S : in bit_vector(2 downto 0);
F: out bit;
carryIn: in bit;
carryOut: out bit);
end component;
signal A, B, F, carryIn, carryOut: bit;
signal S : bit_vector(2 downto 0);
begin
DUT: ALU port map (A => A, B => B, F => F, carryIn => carryIn, carryOut => carryOut, S => S);
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
wait for 20 ns;
assert(F ='0') report "Fail AND1" severity error;
wait for 20 ns;
S <= "010";
A <= '0';
B <= '1';
assert(F ='0') report "Fail AND2" severity error;
wait for 20 ns;
-- OR
S <= "011";
A <= '0';
B <= '0';
wait for 20 ns;
assert(F ='0') report "Fail OR1" severity error;
wait for 20 ns;
S <= "011";
A <= '0';
B <= '1';
wait for 20 ns;
assert(F ='1') report "Fail OR2" severity error;
wait for 20 ns;
-- NAND
S <= "100";
A <= '0';
B <= '0';
wait for 20 ns;
assert(F ='1') report "Fail NAND1" severity error;
wait for 20 ns;
S <= "100";
A <= '1';
B <= '1';
wait for 20 ns;
assert(F ='0') report "Fail NAND2" severity error;
wait for 20 ns;
-- NOR
S <= "101";
A <= '0';
B <= '0';
wait for 20 ns;
assert(F ='1') report "Fail NOR1" severity error;
wait for 20 ns;
S <= "101";
A <= '1';
B <= '0';
wait for 20 ns;
assert(F ='0') report "Fail NOR2" severity error;
wait for 20 ns;
-- XOR
S <= "110";
A <= '0';
B <= '1';
wait for 20 ns;
assert(F ='1') report "Fail XOR1" severity error;
wait for 20 ns;
S <= "110";
A <= '1';
B <= '0';
wait for 20 ns;
assert(F ='1') report "Fail XOR2" severity error;
wait for 20 ns;
-- XNOR
S <= "111";
A <= '0';
B <= '1';
wait for 20 ns;
assert(F ='0') report "Fail XNOR1" severity error;
wait for 20 ns;
S <= "111";
A <= '1';
B <= '0';
wait for 20 ns;
assert(F ='0') report "Fail XNOR2" severity error;
wait for 20 ns;
-- Full Adder
S <= "000";
A <= '0';
B <= '0';
carryIn <= '1';
wait for 20 ns;
assert(F ='1') report "Fail FullAdder1" severity error;
wait for 20 ns;
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
wait for 20 ns;
assert(F ='1') report "Fail FullAdder2" severity error;
wait for 20 ns;
-- Full Subtractor
S <= "000";
A <= '0';
B <= '1';
carryIn <= '1';
wait for 20 ns;
assert(F ='0') report "Full Subtractor 1" severity error;
wait for 20 ns;
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
wait for 20 ns;
assert(F ='1') report "Full Subtractor 2" severity error;
wait for 20 ns;
assert false report "Test done." severity note;
wait;
end process;
end tb;
在当前程序中,我遇到了以下执行错误:
# EXECUTION:: ERROR : Fail OR2
# EXECUTION:: Time: 120 ns, Iteration: 0, Instance: /testbench,
Process: line__21.
# EXECUTION:: ERROR : Fail NAND2
# EXECUTION:: Time: 200 ns, Iteration: 0, Instance: /testbench,
Process: line__21.
# EXECUTION:: ERROR : Fail NOR2
# EXECUTION:: Time: 280 ns, Iteration: 0, Instance: /testbench,
Process: line__21.
# EXECUTION:: ERROR : Fail Subtrator1
# EXECUTION:: Time: 560 ns, Iteration: 0, Instance: /testbench,
Process: line__21.
# EXECUTION:: NOTE : Test done.
# EXECUTION:: Time: 620 ns, Iteration: 0, Instance: /testbench,
Process: line__21.
# KERNEL: Simulation has finished. There are no more test vectors to
simulate.
# VSIM: Simulation has finished.
这似乎与主程序有关,但我不确定为什么会显示这些错误,因为测试台中的逻辑似乎是正确的。
下面的部分我也改了
when "000" => F <= A XOR B XOR carryIn; -- Full Adder
carryOut <= (A AND B) OR (carryIn
AND A) OR (carryIn AND B);
when "001" => F <= (A XOR B) XOR carryIn; -- Full Subtractor
carryOut <= ((NOT A) AND (B OR
carryIn)) OR (B AND carryIn);
然后在testbench中获取carryIn。
首先,您在 architecture behavior of ALU
中的流程存在问题:
该过程应对所有输入敏感,而不仅仅是 S
:
process(S, A, B, carryIn)
这样,如果 S
没有改变但输入数据改变了,输出将被重新计算而不是保持它们以前的值。
carryOut
输出总是要赋值的,而不仅仅是算术运算。否则,当您尝试合成它时,您将推断出锁存器来存储它的值。
对于加法和减法,您仅对 carryIn = '1'
的情况建模。另一种情况呢?
所有问题的解决方案示例:
```vhdl
process(S, A, B, carryIn)
begin
carryOut <= '0';
case (S) is
when "000" => -- Full Adder
F <= A XOR B XOR carryIn;
carryOut <= (A AND B) OR (carryIn AND A) OR (carryIn AND B);
when "001" => -- Full Subtractor
F <= A XOR B XOR carryIn;
carryOut <= ((NOT A) AND (B OR carryIn)) OR (B AND carryIn);
when "010" => F <= A AND B;
when "011" => F <= A OR B;
when "100" => F <= A NAND B;
when "101" => F <= A NOR B;
when "110" => F <= A XOR B;
when others => F <= A XNOR B;
end case;
end process;
```
(注意使用 when others
来保证我们不会忘记一个案例)。
那你的模拟环境也有问题。您写道:
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail AND1" severity error;
wait;
...
这将不起作用有两个原因:您在测试向量产生任何影响之前检查它的影响。由于信号分配和断言之间没有时间流逝,因此 F
和 carryOut
值尚未更改。您检查它们在输入更改之前的值。
第二个问题是wait;
表示永远等待。它肯定会暂停你的过程。其他语句将永远不会执行并且模拟将停止,因为在您的情况下没有其他事情要做。
要解决这两个问题写:
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 1 ns;
assert (F = '0') and (carryOut = '0') report "Fail AND1" severity error;
S <= "010";
A <= '0';
B <= '1';
carryIn <= '0';
wait for 1 ns;
assert (F = '0') and (carryOut = '0') report "Fail AND2" severity error;
...
请注意,您可以通过不重新分配不变的信号来简化一点:
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 1 ns;
assert (F = '0') and (carryOut = '0') report "Fail AND1" severity error;
B <= '1';
wait for 1 ns;
assert (F = '0') and (carryOut = '0') report "Fail AND2" severity error;
...
最后一点:VHDL 是一种高级编程语言。您可以使用它的一些功能来简化您的测试平台。例如,您可以使用 ieee.numeric_bit_unsigned
包,它允许对向量进行算术运算以及在向量和整数之间进行转换。类似(未测试):
...
use ieee.numeric_bit_unsigned.all;
...
process
begin
for i in 0 to 7 loop -- loop over the 8 possible values of (A,B,carryIn)
(A, B, carryIn) <= to_bitvector(i, 3);
-- AND
S <= "010";
wait for 1 ns;
assert F = ((A and B)) and (carryOut = '0') report "Fail AND" severity error;
-- OR
S <= "011";
wait for 1 ns;
assert (F = (A or B)) and (carryOut = '0') report "Fail OR" severity error;
...
...
-- Full Adder
S <= "000";
wait for 1 ns;
assert carryOut & f = ('0' & A) + ('0' & B) + carryIn
report "Fail FullAdder" severity error;
-- full subtractor
S <= "001";
wait for 1 ns;
assert carryOut & F = ('0' & A) - (('0' & B) + carryIn)
report "Fail FullSubtractor" severity error;
end loop;
assert false report "Test done." severity note;
wait;
end process;
这反映了赏金和您的编辑之前评论中建议的更改。
白色 space 和可选关键字已用于显示代码组织。
更改的理由如下。
library IEEE;
use IEEE.std_logic_1164.all;
entity ALU is
port (
A, B: in bit; -- operands
S: in bit_vector(2 downto 0);
F: out bit; -- output
carryIn: in bit;
carryOut: out bit
);
end entity ALU;
architecture behavior of ALU is
begin
-- process (S)
process (S, A, B, carryIn) -- CHANGED - ADDED A, B, carryIn Tarick Welling
begin
carryOut <= '0'; -- CHANGED - ADDED DEFAULT ASSIGNMENT user16145658
case (S) is
when "000" =>
-- if carryIn = '1' then -- CHANGED not needed user16145658
F <= A XOR B XOR carryIn; -- Full Adder
carryOut <= (A AND B) OR (carryIn AND A) OR (carryIn AND B);
-- end if; -- CHANGED not needed user16145658
when "001" =>
-- if carryIn = '1' then -- CHANGED not needed user16145658
F <= (A XOR B) XOR carryIn; -- Full Subtractor
carryOut <= ((NOT A) AND (B OR carryIn)) OR (B AND carryIn);
-- end if; -- CHANGED not needed user16145658
when "010" =>
F <= A AND B;
when "011" =>
F <= A OR B;
when "100" =>
F <= A NAND B;
when "101" =>
F <= A NOR B;
when "110" =>
F <= A XOR B;
when "111" =>
F <= A XNOR B;
end case;
end process;
end architecture behavior;
library IEEE;
use IEEE.std_logic_1164.all;
entity testbench is
end testbench;
architecture tb of testbench is
component ALU is
port (
A, B: in bit;
S: in bit_vector(2 downto 0);
F: out bit;
carryIn: in bit;
carryOut: out bit
);
end component ALU;
signal A, B, F, carryIn, carryOut: bit;
signal S: bit_vector(2 downto 0);
begin
DUT:
ALU
port map (
A => A,
B => B,
F => F,
carryIn => carryIn,
carryOut => carryOut,
S => S
);
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail AND1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "010";
A <= '0';
B <= '1';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail AND2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- OR
S <= "011";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail OR1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "011";
A <= '0';
B <= '1';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail OR2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- NAND
S <= "100";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail NAND1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "100";
A <= '1';
B <= '1';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail NAND2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- NOR
S <= "101";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail NOR1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "101";
A <= '1';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail NOR2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- XOR
S <= "110";
A <= '0';
B <= '1';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail XOR1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "110";
A <= '1';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail XOR2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- XNOR
S <= "111";
A <= '0';
B <= '1';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail XNOR1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "111";
A <= '1';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail XNOR2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- Full Adder
S <= "000";
A <= '0';
B <= '0';
carryIn <= '1';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail FullAdder1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '1'
report "Fail FullAdder2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- Full Subtractor
S <= "000";
A <= '0';
B <= '1';
carryIn <= '1';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '1'
report "Fail Subtractor1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '1'
report "Fail Subtractor2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
assert false
report "Test done."
severity note;
wait; -- KEEP AS IS user16145658
end process;
end architecture tb;
这会产生输出:
/usr/local/bin/ghdl -r testbench --wave=testbench.ghw
testbench.vhdl:232:9:@320ns:(assertion note): Test done.
没有所有断言测试错误报告。
(报告语句的格式特定于 VHDL 实现。)
处理敏感度列表
进程敏感度只包含S
。这使得正确的模拟依赖于刺激顺序。它还推断综合中的锁存器,这里 S
用作锁存其他评估输入值的启用。由于两个原因,闩锁是不受欢迎的。在综合硬件中,它们占用可用于有意设计规范的资源,更糟糕的是可能导致模拟和实现行为之间的不匹配(此处通过对刺激顺序的依赖,如 OR1 和 OR2 等所示)。
过程敏感性列表的规则可在 IEEE 标准 1076 中找到,此处使用修订版 -2008。 (未发现符合-2008 的 VHDL 语言 fully 的实现,并且 none 声称遵守后来的 -2019 修订版。 )
11.3 流程说明:
If a process sensitivity list appears following the reserved word process, then the process statement is assumed to contain an implicit wait statement as the last statement of the process statement part; this implicit wait statement is of the form
wait on sensitivity_list ;
...
If a process sensitivity list appears following the reserved word process in a process statement, then the process statement shall not contain an explicit wait statement. Similarly, if such a process statement is a parent of a procedure, then it is an error if that procedure contains a wait statement.
...
A segue to 10.2 Wait statement:
The sensitivity clause defines the sensitivity set of the wait statement, which is the set of signals to which the wait statement is sensitive. Each signal name in the sensitivity list identifies a given signal as a member of the sensitivity set. Each signal name in the sensitivity list shall be a static signal name, and each name shall denote a signal for which reading is permitted. ...
The suspended process also resumes as a result of an event occurring on any signal in the sensitivity set of the wait statement. If such an event occurs, the condition in the condition clause is evaluated. ...
The suspended process also resumes as a result of an event occurring on any signal in the sensitivity set of the wait statement.
进程在等待语句中挂起和恢复,这里是由于敏感列表中列出的信号事件。
然后回到 11.3:
The execution of a process statement consists of the repetitive execution of its sequence of statements. After the last statement in the sequence of statements of a process statement is executed, execution will immediately continue with the first statement in the sequence of statements.
合成的敏感度列表如下。
默认分配给 carryOut
修复敏感度列表揭示了另一个刺激顺序依赖性诱导闭锁 carryOut
。
在 IEEE Std 1076.6-2004 RTL Synthesis 中找到了关于如何推断锁存器的最清晰的描述(由于年代久远和缺乏维护而被撤回)。
6.2.1.1 来自具有敏感列表的进程的电平敏感存储:
A level-sensitive storage element shall be modeled for a signal (or variable) when all the following apply:
a) The signal (or variable) has an explicit assignment.
b) The signal (or variable) does not have an execution path with <clock_edge> as a condition.
c) There are executions of the process that do not execute an explicit assignment (via an assignment
statement) to the signal (or variable).
By default, the effect of an identity assignment of the signal (or variable) shall be as though the assignment
was not present.
...
进程敏感度列表应包含在进程语句中读取的所有信号。
目的是让模拟行为与综合设计规范行为相匹配。
Tarick Welling 应该建议将进程中读取的 所有 信号添加到进程敏感列表中。
从 ALU 加减选项中删除 if 语句
carryIn
在表达式中计算,生成赋值给 F
和 carryOut
的值。条件执行通过使用 if 语句施加的限制是不兼容的。
在测试台进程中移动等待语句
当任何进程 运行 或尚未恢复时,不会发生信号更新。信号更新在模拟周期中比恢复和随后暂停进程更早应用:
14.7.5 模型执行
14.7.5.1 一般
The execution of a model consists of an initialization phase followed by the repetitive execution of process statements in the description of that model. Each such repetition is said to be a simulation cycle. In each cycle, the values of all signals in the description are computed. If as a result of this computation an event occurs on a given signal, process statements that are sensitive to that signal will resume and will be executed as part of the simulation cycle.
等待语句需要超时子句的原因在10.2等待语句中找到:
The timeout clause specifies the maximum amount of time the process will remain suspended at this wait statement. If no timeout clause appears, the timeout clause for (STD.STANDARD.TIME'HIGH – STD.STANDARD.NOW) is assumed. It is an error if the time expression in the timeout clause evaluates to a negative value.
其中TIME'HIGH是最大模拟时间,表示模拟将结束。基本上没有超时条款你 运行 模拟时钟。
如何排除故障
您的有经验的读者阅读了您的代码并注意到了这些模型的缺点。否则,您可能会使用彻底的测试平台刺激,可能会重新 运行ged 来确定发生了什么。您会发现,可能使用波形显示,您的代码忽略了输入,而 S
没有改变(NOR1 到 NOR 2,等等)。在过程敏感度列表中找不到这些输入。
摆脱闩锁取决于了解它们的原因。通过提供彻底的测试刺激可以看到效果。
由于对刺激顺序的敏感性,敏感性列表问题可能需要的不仅仅是彻底的测试刺激。 (这里之前的 'test vector' 为 carryOut
提供了一个无关紧要的值,你测试它的值是正确的。)
我尝试为实现逻辑运算、全加器和全减器的 1 位 ALU 编写紧凑的代码。编译看起来不错,但它不会在测试台结束时断言 "Test done."
消息。此外,变量中逻辑值的变化,如A、B和F,本应导致测试台出错的,对程序来说是不变的,因为它不会报告任何错误。主设计肯定有问题,但我找不到问题。
在testbench中,我只是测试了每个功能的一些案例。
library IEEE;
use IEEE.std_logic_1164.all;
entity ALU is
port(A,B : in bit; -- operands
S : in bit_vector(2 downto 0);
F: out bit; -- output
carryIn: in bit;
carryOut: out bit);
end ALU;
architecture behavior of ALU is
begin
process(S)
begin
case (S) is
when "000" => if carryIn = '1' then F <= A XOR B XOR carryIn; -- Full Adder
carryOut <= (A AND B) OR (carryIn AND A) OR (carryIn AND B);
end if;
when "001" => if carryIn = '1' then F <= (A XOR B) XOR carryIn; -- Full Subtractor
carryOut <= ((NOT A) AND (B OR carryIn)) OR (B AND carryIn);
end if;
when "010" => F <= A AND B;
when "011" => F <= A OR B;
when "100" => F <= A NAND B;
when "101" => F <= A NOR B;
when "110" => F <= A XOR B;
when "111" => F <= A XNOR B;
end case;
end process;
end behavior ;
测试平台
library IEEE;
use IEEE.std_logic_1164.all;
entity testbench is
end testbench;
architecture tb of testbench is
component ALU is
port(A,B : in bit;
S : in bit_vector(2 downto 0);
F: out bit;
carryIn: in bit;
carryOut: out bit);
end component;
signal A, B, F, carryIn, carryOut: bit;
signal S : bit_vector(2 downto 0);
begin
DUT: ALU port map (A => A, B => B, F => F, carryIn => carryIn, carryOut => carryOut, S => S);
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail AND1" severity error;
wait;
S <= "010";
A <= '0';
B <= '1';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail AND2" severity error;
wait;
-- OR
S <= "011";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail OR1" severity error;
wait;
S <= "011";
A <= '0';
B <= '1';
carryIn <= '0';
assert(F ='1' and carryOut = '0') report "Fail OR2" severity error;
wait;
-- NAND
S <= "100";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='1' and carryOut = '0') report "Fail NAND1" severity error;
wait;
S <= "100";
A <= '1';
B <= '1';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail NAND2" severity error;
wait;
-- NOR
S <= "101";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='1' and carryOut = '0') report "Fail NOR1" severity error;
wait;
S <= "101";
A <= '1';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail NOR2" severity error;
wait;
-- XOR
S <= "110";
A <= '0';
B <= '1';
carryIn <= '0';
assert(F ='1' and carryOut = '0') report "Fail XOR1" severity error;
wait;
S <= "110";
A <= '1';
B <= '0';
carryIn <= '0';
assert(F ='1' and carryOut = '0') report "Fail XOR2" severity error;
wait;
-- XNOR
S <= "111";
A <= '0';
B <= '1';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail XNOR1" severity error;
wait;
S <= "111";
A <= '1';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail XNOR2" severity error;
wait;
-- Full Adder
S <= "000";
A <= '0';
B <= '0';
carryIn <= '1';
assert(F ='1' and carryOut = '0') report "Fail FullAdder1" severity error;
wait;
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
assert(F ='1' and carryOut = '1') report "Fail FullAdder2" severity error;
wait;
-- Full Subtractor
S <= "000";
A <= '0';
B <= '1';
carryIn <= '1';
assert(F ='0' and carryOut = '1') report "Fail Subtractor1" severity error;
wait;
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
assert(F ='1' and carryOut = '1') report "Fail Subtractor2" severity error;
wait;
assert false report "Test done." severity note;
wait;
end process;
end tb;
编辑
library IEEE;
use IEEE.std_logic_1164.all;
entity testbench is
end testbench;
architecture tb of testbench is
component ALU is
port(A,B : in bit;
S : in bit_vector(2 downto 0);
F: out bit;
carryIn: in bit;
carryOut: out bit);
end component;
signal A, B, F, carryIn, carryOut: bit;
signal S : bit_vector(2 downto 0);
begin
DUT: ALU port map (A => A, B => B, F => F, carryIn => carryIn, carryOut => carryOut, S => S);
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
wait for 20 ns;
assert(F ='0') report "Fail AND1" severity error;
wait for 20 ns;
S <= "010";
A <= '0';
B <= '1';
assert(F ='0') report "Fail AND2" severity error;
wait for 20 ns;
-- OR
S <= "011";
A <= '0';
B <= '0';
wait for 20 ns;
assert(F ='0') report "Fail OR1" severity error;
wait for 20 ns;
S <= "011";
A <= '0';
B <= '1';
wait for 20 ns;
assert(F ='1') report "Fail OR2" severity error;
wait for 20 ns;
-- NAND
S <= "100";
A <= '0';
B <= '0';
wait for 20 ns;
assert(F ='1') report "Fail NAND1" severity error;
wait for 20 ns;
S <= "100";
A <= '1';
B <= '1';
wait for 20 ns;
assert(F ='0') report "Fail NAND2" severity error;
wait for 20 ns;
-- NOR
S <= "101";
A <= '0';
B <= '0';
wait for 20 ns;
assert(F ='1') report "Fail NOR1" severity error;
wait for 20 ns;
S <= "101";
A <= '1';
B <= '0';
wait for 20 ns;
assert(F ='0') report "Fail NOR2" severity error;
wait for 20 ns;
-- XOR
S <= "110";
A <= '0';
B <= '1';
wait for 20 ns;
assert(F ='1') report "Fail XOR1" severity error;
wait for 20 ns;
S <= "110";
A <= '1';
B <= '0';
wait for 20 ns;
assert(F ='1') report "Fail XOR2" severity error;
wait for 20 ns;
-- XNOR
S <= "111";
A <= '0';
B <= '1';
wait for 20 ns;
assert(F ='0') report "Fail XNOR1" severity error;
wait for 20 ns;
S <= "111";
A <= '1';
B <= '0';
wait for 20 ns;
assert(F ='0') report "Fail XNOR2" severity error;
wait for 20 ns;
-- Full Adder
S <= "000";
A <= '0';
B <= '0';
carryIn <= '1';
wait for 20 ns;
assert(F ='1') report "Fail FullAdder1" severity error;
wait for 20 ns;
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
wait for 20 ns;
assert(F ='1') report "Fail FullAdder2" severity error;
wait for 20 ns;
-- Full Subtractor
S <= "000";
A <= '0';
B <= '1';
carryIn <= '1';
wait for 20 ns;
assert(F ='0') report "Full Subtractor 1" severity error;
wait for 20 ns;
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
wait for 20 ns;
assert(F ='1') report "Full Subtractor 2" severity error;
wait for 20 ns;
assert false report "Test done." severity note;
wait;
end process;
end tb;
在当前程序中,我遇到了以下执行错误:
# EXECUTION:: ERROR : Fail OR2
# EXECUTION:: Time: 120 ns, Iteration: 0, Instance: /testbench,
Process: line__21.
# EXECUTION:: ERROR : Fail NAND2
# EXECUTION:: Time: 200 ns, Iteration: 0, Instance: /testbench,
Process: line__21.
# EXECUTION:: ERROR : Fail NOR2
# EXECUTION:: Time: 280 ns, Iteration: 0, Instance: /testbench,
Process: line__21.
# EXECUTION:: ERROR : Fail Subtrator1
# EXECUTION:: Time: 560 ns, Iteration: 0, Instance: /testbench,
Process: line__21.
# EXECUTION:: NOTE : Test done.
# EXECUTION:: Time: 620 ns, Iteration: 0, Instance: /testbench,
Process: line__21.
# KERNEL: Simulation has finished. There are no more test vectors to
simulate.
# VSIM: Simulation has finished.
这似乎与主程序有关,但我不确定为什么会显示这些错误,因为测试台中的逻辑似乎是正确的。
下面的部分我也改了
when "000" => F <= A XOR B XOR carryIn; -- Full Adder
carryOut <= (A AND B) OR (carryIn
AND A) OR (carryIn AND B);
when "001" => F <= (A XOR B) XOR carryIn; -- Full Subtractor
carryOut <= ((NOT A) AND (B OR
carryIn)) OR (B AND carryIn);
然后在testbench中获取carryIn。
首先,您在 architecture behavior of ALU
中的流程存在问题:
该过程应对所有输入敏感,而不仅仅是
S
:process(S, A, B, carryIn)
这样,如果
S
没有改变但输入数据改变了,输出将被重新计算而不是保持它们以前的值。carryOut
输出总是要赋值的,而不仅仅是算术运算。否则,当您尝试合成它时,您将推断出锁存器来存储它的值。对于加法和减法,您仅对
carryIn = '1'
的情况建模。另一种情况呢?
所有问题的解决方案示例:
```vhdl
process(S, A, B, carryIn)
begin
carryOut <= '0';
case (S) is
when "000" => -- Full Adder
F <= A XOR B XOR carryIn;
carryOut <= (A AND B) OR (carryIn AND A) OR (carryIn AND B);
when "001" => -- Full Subtractor
F <= A XOR B XOR carryIn;
carryOut <= ((NOT A) AND (B OR carryIn)) OR (B AND carryIn);
when "010" => F <= A AND B;
when "011" => F <= A OR B;
when "100" => F <= A NAND B;
when "101" => F <= A NOR B;
when "110" => F <= A XOR B;
when others => F <= A XNOR B;
end case;
end process;
```
(注意使用 when others
来保证我们不会忘记一个案例)。
那你的模拟环境也有问题。您写道:
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail AND1" severity error;
wait;
...
这将不起作用有两个原因:您在测试向量产生任何影响之前检查它的影响。由于信号分配和断言之间没有时间流逝,因此 F
和 carryOut
值尚未更改。您检查它们在输入更改之前的值。
第二个问题是wait;
表示永远等待。它肯定会暂停你的过程。其他语句将永远不会执行并且模拟将停止,因为在您的情况下没有其他事情要做。
要解决这两个问题写:
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 1 ns;
assert (F = '0') and (carryOut = '0') report "Fail AND1" severity error;
S <= "010";
A <= '0';
B <= '1';
carryIn <= '0';
wait for 1 ns;
assert (F = '0') and (carryOut = '0') report "Fail AND2" severity error;
...
请注意,您可以通过不重新分配不变的信号来简化一点:
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 1 ns;
assert (F = '0') and (carryOut = '0') report "Fail AND1" severity error;
B <= '1';
wait for 1 ns;
assert (F = '0') and (carryOut = '0') report "Fail AND2" severity error;
...
最后一点:VHDL 是一种高级编程语言。您可以使用它的一些功能来简化您的测试平台。例如,您可以使用 ieee.numeric_bit_unsigned
包,它允许对向量进行算术运算以及在向量和整数之间进行转换。类似(未测试):
...
use ieee.numeric_bit_unsigned.all;
...
process
begin
for i in 0 to 7 loop -- loop over the 8 possible values of (A,B,carryIn)
(A, B, carryIn) <= to_bitvector(i, 3);
-- AND
S <= "010";
wait for 1 ns;
assert F = ((A and B)) and (carryOut = '0') report "Fail AND" severity error;
-- OR
S <= "011";
wait for 1 ns;
assert (F = (A or B)) and (carryOut = '0') report "Fail OR" severity error;
...
...
-- Full Adder
S <= "000";
wait for 1 ns;
assert carryOut & f = ('0' & A) + ('0' & B) + carryIn
report "Fail FullAdder" severity error;
-- full subtractor
S <= "001";
wait for 1 ns;
assert carryOut & F = ('0' & A) - (('0' & B) + carryIn)
report "Fail FullSubtractor" severity error;
end loop;
assert false report "Test done." severity note;
wait;
end process;
这反映了赏金和您的编辑之前评论中建议的更改。
白色 space 和可选关键字已用于显示代码组织。
更改的理由如下。
library IEEE;
use IEEE.std_logic_1164.all;
entity ALU is
port (
A, B: in bit; -- operands
S: in bit_vector(2 downto 0);
F: out bit; -- output
carryIn: in bit;
carryOut: out bit
);
end entity ALU;
architecture behavior of ALU is
begin
-- process (S)
process (S, A, B, carryIn) -- CHANGED - ADDED A, B, carryIn Tarick Welling
begin
carryOut <= '0'; -- CHANGED - ADDED DEFAULT ASSIGNMENT user16145658
case (S) is
when "000" =>
-- if carryIn = '1' then -- CHANGED not needed user16145658
F <= A XOR B XOR carryIn; -- Full Adder
carryOut <= (A AND B) OR (carryIn AND A) OR (carryIn AND B);
-- end if; -- CHANGED not needed user16145658
when "001" =>
-- if carryIn = '1' then -- CHANGED not needed user16145658
F <= (A XOR B) XOR carryIn; -- Full Subtractor
carryOut <= ((NOT A) AND (B OR carryIn)) OR (B AND carryIn);
-- end if; -- CHANGED not needed user16145658
when "010" =>
F <= A AND B;
when "011" =>
F <= A OR B;
when "100" =>
F <= A NAND B;
when "101" =>
F <= A NOR B;
when "110" =>
F <= A XOR B;
when "111" =>
F <= A XNOR B;
end case;
end process;
end architecture behavior;
library IEEE;
use IEEE.std_logic_1164.all;
entity testbench is
end testbench;
architecture tb of testbench is
component ALU is
port (
A, B: in bit;
S: in bit_vector(2 downto 0);
F: out bit;
carryIn: in bit;
carryOut: out bit
);
end component ALU;
signal A, B, F, carryIn, carryOut: bit;
signal S: bit_vector(2 downto 0);
begin
DUT:
ALU
port map (
A => A,
B => B,
F => F,
carryIn => carryIn,
carryOut => carryOut,
S => S
);
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail AND1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "010";
A <= '0';
B <= '1';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail AND2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- OR
S <= "011";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail OR1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "011";
A <= '0';
B <= '1';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail OR2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- NAND
S <= "100";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail NAND1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "100";
A <= '1';
B <= '1';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail NAND2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- NOR
S <= "101";
A <= '0';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail NOR1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "101";
A <= '1';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail NOR2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- XOR
S <= "110";
A <= '0';
B <= '1';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail XOR1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "110";
A <= '1';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail XOR2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- XNOR
S <= "111";
A <= '0';
B <= '1';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail XNOR1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "111";
A <= '1';
B <= '0';
carryIn <= '0';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '0'
report "Fail XNOR2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- Full Adder
S <= "000";
A <= '0';
B <= '0';
carryIn <= '1';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '0'
report "Fail FullAdder1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '1'
report "Fail FullAdder2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
-- Full Subtractor
S <= "000";
A <= '0';
B <= '1';
carryIn <= '1';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='0' and carryOut = '1'
report "Fail Subtractor1"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
S <= "000";
A <= '1';
B <= '1';
carryIn <= '1';
wait for 20 ns; -- CHANGED MOVED user16145658
assert F ='1' and carryOut = '1'
report "Fail Subtractor2"
severity error;
-- wait for 20 ns; -- CHANGED MOVED added timeout clause mkrieger1
assert false
report "Test done."
severity note;
wait; -- KEEP AS IS user16145658
end process;
end architecture tb;
这会产生输出:
/usr/local/bin/ghdl -r testbench --wave=testbench.ghw
testbench.vhdl:232:9:@320ns:(assertion note): Test done.
没有所有断言测试错误报告。
(报告语句的格式特定于 VHDL 实现。)
处理敏感度列表
进程敏感度只包含S
。这使得正确的模拟依赖于刺激顺序。它还推断综合中的锁存器,这里 S
用作锁存其他评估输入值的启用。由于两个原因,闩锁是不受欢迎的。在综合硬件中,它们占用可用于有意设计规范的资源,更糟糕的是可能导致模拟和实现行为之间的不匹配(此处通过对刺激顺序的依赖,如 OR1 和 OR2 等所示)。
过程敏感性列表的规则可在 IEEE 标准 1076 中找到,此处使用修订版 -2008。 (未发现符合-2008 的 VHDL 语言 fully 的实现,并且 none 声称遵守后来的 -2019 修订版。 )
11.3 流程说明:
If a process sensitivity list appears following the reserved word process, then the process statement is assumed to contain an implicit wait statement as the last statement of the process statement part; this implicit wait statement is of the form
wait on sensitivity_list ;
...
If a process sensitivity list appears following the reserved word process in a process statement, then the process statement shall not contain an explicit wait statement. Similarly, if such a process statement is a parent of a procedure, then it is an error if that procedure contains a wait statement.
...
A segue to 10.2 Wait statement:
The sensitivity clause defines the sensitivity set of the wait statement, which is the set of signals to which the wait statement is sensitive. Each signal name in the sensitivity list identifies a given signal as a member of the sensitivity set. Each signal name in the sensitivity list shall be a static signal name, and each name shall denote a signal for which reading is permitted. ...
The suspended process also resumes as a result of an event occurring on any signal in the sensitivity set of the wait statement. If such an event occurs, the condition in the condition clause is evaluated. ...
The suspended process also resumes as a result of an event occurring on any signal in the sensitivity set of the wait statement.
进程在等待语句中挂起和恢复,这里是由于敏感列表中列出的信号事件。
然后回到 11.3:
The execution of a process statement consists of the repetitive execution of its sequence of statements. After the last statement in the sequence of statements of a process statement is executed, execution will immediately continue with the first statement in the sequence of statements.
合成的敏感度列表如下。
默认分配给 carryOut
修复敏感度列表揭示了另一个刺激顺序依赖性诱导闭锁 carryOut
。
在 IEEE Std 1076.6-2004 RTL Synthesis 中找到了关于如何推断锁存器的最清晰的描述(由于年代久远和缺乏维护而被撤回)。
6.2.1.1 来自具有敏感列表的进程的电平敏感存储:
A level-sensitive storage element shall be modeled for a signal (or variable) when all the following apply:
a) The signal (or variable) has an explicit assignment.
b) The signal (or variable) does not have an execution path with <clock_edge> as a condition.
c) There are executions of the process that do not execute an explicit assignment (via an assignment statement) to the signal (or variable).
By default, the effect of an identity assignment of the signal (or variable) shall be as though the assignment was not present.
...进程敏感度列表应包含在进程语句中读取的所有信号。
目的是让模拟行为与综合设计规范行为相匹配。
Tarick Welling 应该建议将进程中读取的 所有 信号添加到进程敏感列表中。
从 ALU 加减选项中删除 if 语句
carryIn
在表达式中计算,生成赋值给 F
和 carryOut
的值。条件执行通过使用 if 语句施加的限制是不兼容的。
在测试台进程中移动等待语句
当任何进程 运行 或尚未恢复时,不会发生信号更新。信号更新在模拟周期中比恢复和随后暂停进程更早应用:
14.7.5 模型执行
14.7.5.1 一般
The execution of a model consists of an initialization phase followed by the repetitive execution of process statements in the description of that model. Each such repetition is said to be a simulation cycle. In each cycle, the values of all signals in the description are computed. If as a result of this computation an event occurs on a given signal, process statements that are sensitive to that signal will resume and will be executed as part of the simulation cycle.
等待语句需要超时子句的原因在10.2等待语句中找到:
The timeout clause specifies the maximum amount of time the process will remain suspended at this wait statement. If no timeout clause appears, the timeout clause for (STD.STANDARD.TIME'HIGH – STD.STANDARD.NOW) is assumed. It is an error if the time expression in the timeout clause evaluates to a negative value.
其中TIME'HIGH是最大模拟时间,表示模拟将结束。基本上没有超时条款你 运行 模拟时钟。
如何排除故障
您的有经验的读者阅读了您的代码并注意到了这些模型的缺点。否则,您可能会使用彻底的测试平台刺激,可能会重新 运行ged 来确定发生了什么。您会发现,可能使用波形显示,您的代码忽略了输入,而 S
没有改变(NOR1 到 NOR 2,等等)。在过程敏感度列表中找不到这些输入。
摆脱闩锁取决于了解它们的原因。通过提供彻底的测试刺激可以看到效果。
由于对刺激顺序的敏感性,敏感性列表问题可能需要的不仅仅是彻底的测试刺激。 (这里之前的 'test vector' 为 carryOut
提供了一个无关紧要的值,你测试它的值是正确的。)