欲しい未来
欲しい未来

Reputation: 121

Issues in compact 1-bit ALU behavior

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

Answers (2)

user16145658
user16145658

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

Renaud Pacalet
Renaud Pacalet

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

Related Questions