Reputation: 121
I tried to write a compact code for a 1-bit ALU that implements logic operations, a full adder, and a full subtractor. The compilation looks fine, but it does not assert the message "Test done."
at the end of the testbench. Moreover, the change of logic values in variables, such as A, B and F that should lead to error in the testbench are unvariedness to the program as it does not report any error. Something is certainly wrong in the main design, but I couldn't find the problem.
In the testbench, I just tested some cases of each function.
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 ;
Testbench
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;
Edit
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;
In the current program, I have got the following execution errors:
# 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.
It seems to be somethin related to the main program, but I am not sure why it shows these errors because the logic in the testbench seems correct.
I also changed the following part
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);
and then get the carryIn in the testbench.
Upvotes: 0
Views: 158
Reputation: 777
This reflects the changes recommended in comments prior to the bounty and your EDIT.
White space and optional keywords have been used to show code organization.
The rationale for the changes follows.
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;
And this produces the output:
/usr/local/bin/ghdl -r testbench --wave=testbench.ghw
testbench.vhdl:232:9:@320ns:(assertion note): Test done.
without all the assertion test error reporting.
(Format of report statements are particular to VHDL implementations.)
Process Sensitivity List
The process sensitivity only contained S
. This makes correct simulation dependent on stimuli order. It also infers latches in synthesis, here S
is used as an enable for latching the value of other evaluated inputs. Latches are undesirable for two reasons. In synthesized hardware they take resources that can be utilized for intentional design specification and worse can cause a mismatch between simulation and implementation behavior (here through dependency on stimuli order as shown between OR1 and OR2, etc.).
The rules for process sensitivity lists are found in IEEE Std 1076, here using revision -2008. (No implementations of the VHDL language fully conforming to -2008 are found, and none claiming adherence to the later -2019 revision.)
11.3 Process statement:
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.
Processes suspend and resume in wait statements, here due to events on signals listed in the sensitivity list.
And back to 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.
Sensitivity lists for synthesis follow below.
Default assignment to carryOut
Fixing the sensitivity list reveals another stimuli order dependency inducing latch on carryOut
.
The clearest description of how latches are inferred is found in IEEE Std 1076.6-2004 RTL Synthesis (withdrawn due to age and lack of maintenance).
6.2.1.1 Level-sensitive storage from process with sensitivity list:
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.
...The process sensitivity list shall contain all signals read within the process statement.
The purpose is for simulation behavior to match synthesized design specification behavior.
Tarick Welling should have recommended all signals read in the process be added to the process sensitivity list.
Removing if statements from ALU add and subtract choices
carryIn
is evaluated in the expressions producing values for assignment to F
and carryOut
. The restriction imposed by conditional execution through the use of the if statement is incompatible.
Moving the wait statements in the testbench process
Signal updates don't occur while any process is running or yet to resume. Signal updates are applied earlier in a simulation cycle than resuming and subsequently suspending processes:
14.7.5 Model execution
14.7.5.1 General
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.
The reason why the wait statements required a timeout clause is found in 10.2 Wait statement:
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.
Where TIME'HIGH is maximum simulation time and signifies simulation will end. Essentially without the time out clause you ran out the simulation time clock.
How to Troubleshoot
Your experienced readers read your code and noticed these model shortcomings. Otherwise you could have used thorough testbench stimuli, possibly re-arranged to determine what's going on. You'd have found, potentially using a waveform display that your code was ignoring inputs while S
doesn't change (NOR1 to NOR 2, etc.). These inputs weren't found in the process sensitivity list.
Getting rid of latches is dependent on understanding their causes. The effects can be seen by providing thorough test stimuli.
Sensitivity list issues can require more than thorough test stimuli because of sensitivity to stimuli order. (Here a previous 'test vector' providing an innocuous value for carryOut
, you'd be correct to test it's value.)
Upvotes: 1
Reputation: 29250
First, you have issues with your process in architecture behavior of ALU
:
The process shall be sensitive to all inputs, not just S
:
process(S, A, B, carryIn)
This way, if S
does not change but the input data change, the outputs are re-computed instead of keeping their previous value.
The carryOut
output shall always be assigned a value, not just when it is an arithmetic operation. Else, when you will try to synthesize this you will have latches inferred to store its value.
For the additions and subtractions you model only the case where carryIn = '1'
. What about the other case?
Example of solution to all problems:
```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;
```
(note the use of when others
to guarantee that we do not forget a single case).
Then you also have issues with your simulation environment. You wrote:
process
begin
-- AND
S <= "010";
A <= '0';
B <= '0';
carryIn <= '0';
assert(F ='0' and carryOut = '0') report "Fail AND1" severity error;
wait;
...
This will not work for two reasons: you check the effect of your test vector before it had any effect. As no time elapses between the signal assignments and the assertion, the F
and carryOut
values did not change yet. You check the values they had before the changes of the inputs.
The second issue is that wait;
means wait forever. It definitely suspends your process. The other statements will never be executed and the simulation will stop because in your case there is nothing else to be done.
To solve these two issues write:
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;
...
Note that you could simplify a bit by not re-assigning the signals that don't change:
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;
...
One last note: VHDL is a high level programming language. You could use some of its features to simplify your testbench. For example you could use the ieee.numeric_bit_unsigned
package that allows arithmetic operations on vectors and conversions between vectors and integers. Something like (not tested):
...
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;
Upvotes: 1