1

So far everything works as intended except for the Cout (carryout) and V (overflow) when I simulate in the testbench. I get constant Us when performing addition and subtraction. I performed some of the calculations I'm testing by hand so I know which should have a carry value and overflow value.

entity ALU is
  Port ( Cin        :  in STD_LOGIC_VECTOR ( 0 downto 0);
     ALUCntrl   :  in STD_LOGIC_VECTOR ( 3 downto 0);
     A, B       :  in STD_LOGIC_VECTOR (31 downto 0);
     ALUout     : out STD_LOGIC_VECTOR (31 downto 0); 
     Cout, Z, V : out STD_LOGIC );
end ALU;

architecture Behavioral of ALU is
    SIGNAL result        : STD_LOGIC_VECTOR (32 downto 0);
    SIGNAL bCout, bZ, bV : STD_LOGIC;
begin

WITH ALUCntrl SELECT
    result(31 downto 0) <= A  and B when "0000",
                           A   or B when "0001",
                           A  xor B when "0011", 
                           std_logic_vector(unsigned(A) + unsigned(B) + unsigned(Cin)) WHEN "0010",
                           std_logic_vector(unsigned(A) - unsigned(B)) WHEN "0110",
                           A xnor B WHEN "1100",
                           A xnor B WHEN "1111",
                           "00000000000000000000000000000000" WHEN OTHERS;

 WITH result(31 downto 0) SELECT
    bZ <= '1' WHEN "00000000000000000000000000000000",
          '0' WHEN OTHERS;

 WITH ALUCntrl SELECT
    bCout <= result(32) WHEN "0010",
             result(32) WHEN "0110",
             '0' WHEN OTHERS;

 PROCESS(ALUCntrl)
 BEGIN
 CASE ALUCntrl IS
    WHEN "0010" =>-- Addition Overflow
        IF    ((A(31) = '1') and (B(31) = '1') and (result(31) = '0')) THEN 
            bV <= '1';
        ELSIF ((A(31) = '0') and (B(31) = '0') and (result(31) = '1')) THEN 
            bV <= '1';
        ELSE
            bV <= '0';
        END IF;
    WHEN "0110" => -- Subtraction overflow
        IF   ((A(31) = '0') and (B(31) ='1') and (result(31) = '1')) THEN 
            bV <= '1';
        ELSIF ((A(31) = '1') and (B(31) = '0') and (result(31) = '0')) THEN 
            bV <= '1';
        ELSE
            bV <= '0';
        END IF;
    WHEN OTHERS =>
        bV <= '0';
    END CASE;
 END PROCESS;

ALUout <= result(31 downto 0);
Cout   <= bCout;
Z      <= bZ;
V      <= bV;
end Behavioral;

TEST-BENCH

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity ALU_tb is
--  Port ( );
end ALU_tb;

architecture Behavioral of ALU_tb is
-- INPUTS
signal Cin        : STD_LOGIC_VECTOR ( 0 downto 0);
signal A, B       : STD_LOGIC_VECTOR (31 downto 0);
signal ALUCntrl   : STD_LOGIC_VECTOR ( 3 downto 0);
-- OUTPUTS
signal ALUout     : STD_LOGIC_VECTOR (31 downto 0); 
signal Cout, Z, V : STD_LOGIC; 

component ALU is 
port(
     Cin        :  in STD_LOGIC_VECTOR ( 0 downto 0);
     A, B       :  in STD_LOGIC_VECTOR (31 downto 0);
     ALUCntrl   :  in STD_LOGIC_VECTOR ( 3 downto 0);
     ALUout     : out STD_LOGIC_VECTOR (31 downto 0); 
     Cout, Z, V : out STD_LOGIC );
end component ALU;

begin
design_ALU: ALU
port map(
    Cin      => Cin,
    A        => A,
    B        => B,
    ALUCntrl => ALUCntrl,
    ALUout   => ALUout,
    Cout     => Cout,
    Z        => Z,
    V        => V
);
tb : PROCESS
BEGIN
ALUCntrl <= "0000"; -- AND
Cin      <= "00";
A        <= "11111111111111111111111111111111";
B        <= "00000000000000000000000000000000";

wait for 250ns;
ALUCntrl <= "0001"; -- OR
A        <= "10011000100110001001100010011000";
B        <= "10001001100010011000100110001001";

wait for 250ns;
ALUCntrl <= "0011"; -- XOR
A        <= "00000001000000010000000100000001";
B        <= "00010000000100000001000000010000";

wait for 250ns;
ALUCntrl <= "0010"; -- ADD
A        <= "00000000000000000000000000000001";
B        <= "11111111111111111111111111111111";

wait for 250ns;
ALUCntrl <= "0010"; -- ADD
A        <= "01100011100010010111010101001111";
B        <= "10101101010101100010010011100110";

wait for 250ns;
ALUCntrl <= "0010"; -- ADD
Cin      <= "01";
A        <= "00000000000000000000000000000001";
B        <= "11111111111111111111111111111111";

wait for 250ns;
ALUCntrl <= "0010"; -- ADD
A        <= "01100011100010010111010101001111";
B        <= "10101101010101100010010011100110";

wait for 250ns;
ALUCntrl <= "0010"; -- ADD
A        <= "11111111111111111111111111111111";
B        <= "11111111111111111111111111111111";

wait for 250ns;
ALUCntrl <= "0110"; -- SUB
A        <= "00000000000000000000000000000000";
B        <= "00000000000000000000000000000001";

wait for 250ns;
ALUCntrl <= "0110"; -- SUB
A        <= "11111001011010000100011110000011";
B        <= "11111001100110001101010101100010";

wait for 250ns;
ALUCntrl <= "0110"; -- SUB
A        <= "10000000000000000000000000000000";
B        <= "00000001000000000000000000000000";

wait for 250ns;
ALUCntrl <= "1100"; -- NOR
A        <= "10011010101111001101111011011111";
B        <= "10011010101111001101111011111101";

wait for 250ns;
ALUCntrl <= "1111"; -- XNOR
A        <= "10001001101111001101111000110100";
B        <= "11000101001110111101011010000111";

wait;
END PROCESS tb;

end Behavioral;
  • 1
    You are trying to add std_logic_vector + std_logic_vector. Instead either use the type signed or unsigned. – Jim Lewis Mar 11 '20 at 00:18
  • You have included the package numeric_std. This is correct. Do not also include the package std_logic_arith. It also defines types signed and unsigned and they conflict with the ones from numeric_std. The result, neither is directly visible. – Jim Lewis Mar 11 '20 at 00:20
  • For numeric_std, either make sure to use VHDL-2008 mode or the "+ Cin" will not work because prior to 2008 addition with std_logic is not defined. You can fix that by replacing the Cin with (0 => Cin). – Jim Lewis Mar 11 '20 at 00:22
  • For c_out and c_in, you probably need to use a variable (that updates immediately) rather than a signal (that updates a delta cycle later). – Jim Lewis Mar 11 '20 at 00:24
  • I've updated the code, but I wasn't sure how to implement the Cin as part of the arithmetic op without making it equal length to A and B. With the changes I've made, I'm getting results that are off in my simulation when simulating for ADD and SUB. –  Mar 11 '20 at 07:17
  • Did you try "unsigned(A) + unsigned(B) + (0 => Cin)" - assuming that you are intending unsigned math. – Jim Lewis Mar 11 '20 at 14:29
  • Signals only update when a process suspends (here at the sensitivity list). Variables update immediately. View any signal to which you do an assignment in the process as an output. Do not read the outputs of the process inside the process - they will not have updated yet. You need to refactor your code to account for this - either signals and multiple processes - or variables and one process. For your code, I suggest variables. This will also let you simplify it significantly. – Jim Lewis Mar 11 '20 at 14:38
  • 1
    Once you get the code working, I suggest that you replace: WHEN "0000" => with constants: WHEN ALU_AND_OP => This will help with code review. – Jim Lewis Mar 11 '20 at 14:43
  • So what would you suggest in place of "IF (bsum(31 downto 0) = "00...") THEN". If I use a variable, my thought process is to use "IF (ALUout = "00...") THEN", but that gives my an error. Alternatively I also tried "IF (std_logic_vector(unsigned(A(31 downto 0)) - unsigned(B(31 downto 0))) = "00...") THEN" but that gave me another error. So wouldn't it be preferred to create buffers for every variable and then assign those values to the inputs and outputs after the process? Also doesn't (0=>Cin) assign Cin to be zero? If I assign Cin to be 1 in the testbench, will it change? –  Mar 11 '20 at 20:11
  • Replace all assignments to ALUOut with an assignment to a variable named result. Then assign result to ALUOUT. Then use result internally to the process as a temporary. Always assign to result before reading from it (on Left Hand Side of an assignment or including it in an fi statment). If you make the type of result to be unsigned, then rather than checking for "0000000..." you can simply use result = 0 – Jim Lewis Mar 12 '20 at 21:49
  • I had added the variable, but my prof suggested reverting back to signal (as well as some other edits). After editing, my Carry out (Cout) and overflow (V) do not update as intended in the testbench simulation. The only flag working properly is the zero flag. –  Mar 14 '20 at 05:56
  • 1
    You need to learn the importance of the sensitivity list in a process. –  Mar 15 '20 at 02:07
  • I think I got it. Adding the 1-bit Cin to the two 32-bit values was throwing things off. –  Mar 15 '20 at 18:58
  • I see something different. I see an assignment to result(31 downto 0) , however, not result(32). BCout depends on result(32) being correct. – Jim Lewis Mar 16 '20 at 15:10
  • Generally I agree with your professor WRT using signals. When learning VHDL, you must understand how signals work. Variables OTOH, are a nice thing to have but not essential - in addition, they add an additional layer of potential problems during synthesis. However, I suggested variables as it was the fastest way to get your code to something that works. Once you get this version working, as a learning exercise, I would go back and get the other version working - this is important so that you integrate the right coding lessons - rather just remembering using variables had issues. – Jim Lewis Mar 16 '20 at 15:16

0 Answers0