ALU 32 BIT, Overflow, Zero Flag

1.9k views Asked by At

This ALU can perform addition, subtraction, AND, OR on the two data inputs according to an operation code supplied to the ALU. The two-bit control input named Operation partially specifies the operation code. I have been trying to work it but always get errors, still want to add proper zero flag and overflow but each time try something online I restart from scratch.

Simple_ALU.VHDL

   library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity simple_alu is
port( Clk : in std_logic; --clock signal
 A,B : in signed(31 downto 0); --input operands
 Op : in unsigned(2 downto 0); --Operation to be performed
 R : out signed(31 downto 0); --output of ALU
 z: out STD_LOGIC; --Zero flag
 Cry : out  STD_LOGIC
 );
end simple_alu;
architecture Behavioral of simple_alu is
--temporary signal declaration.
signal Reg1,Reg2,Reg3 : signed(31 downto 0) := (others => '0');
begin
Reg1 <= A;
Reg2 <= B;
R <= Reg3;
z<=z;
--Cout <= Cry;
process(Clk)
 variable temp : std_logic_vector (31 downto 0);
begin
 if(rising_edge(Clk)) then --Do the calculation at the positive edge
--of clock cycle.
 case Op is
 when "000" =>
 Reg3 <= Reg1 + Reg2; --addition
 when "001" =>
 Reg3 <= Reg1 - Reg2; --subtraction
  case OP is
          -when "010" =>
               temp := std_logic_vector((unsigned("0" & Reg1) + unsigned(Reg2)));
            Reg3 <= temp(31 downto 0);
              Cry <= temp(32);
 when "011" =>
 Reg3 <= Reg1 nand Reg2; --NAND gate
 when "100" =>
 Reg3 <= Reg1 nor Reg2; --NOR gate
 when "101" =>
 Reg3 <= Reg1 and Reg2; --AND gate
 when "110" =>
 Reg3 <= Reg1 or Reg2; --OR gate
 when "111" =>
 Reg3 <= Reg1 xor Reg2; --XOR gate
 when others =>
 NULL;
 end case;
 end if;
if (Reg3="0000000000000000000000000000000")then 
z='01'
else
z='00'
end process;
end Behavioral;

and TB

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
 signal Clk : std_logic := '0';
 signal A,B,R : signed(31 downto 0) := (others => '0');
 signal Op : unsigned(2 downto 0) := (others => '0');
 constant Clk_period : time := 10 ns;
BEGIN
 -- Instantiate the Unit Under Test (UUT)
 uut: entity work.simple_alu PORT MAP (
 Clk => Clk,
 A => A,
 B => B,
 Op => Op,
 R => R
 );
 -- Clock process definitions
 Clk_process :process
 begin
 Clk <= '0';
 wait for Clk_period/2;
 Clk <= '1';
 wait for Clk_period/2;
 end process;

 -- Stimulus process
 stim_proc: process
 begin
 wait for Clk_period*1;
 A <= "00010010000100100001001000010010"; --18 in decimal
 B <= "00001010000100100001001000010010"; --10 in decimal
 Op <= "000"; wait for Clk_period; --add A and B
 Op <= "001"; wait for Clk_period; --subtract B from A.
 Op <= "010"; wait for Clk_period; --Bitwise NOT of A
 Op <= "011"; wait for Clk_period; --Bitwise NAND of A and B
 Op <= "100"; wait for Clk_period; --Bitwise NOR of A and B
 Op <= "101"; wait for Clk_period; --Bitwise AND of A and B
 Op <= "110"; wait for Clk_period; --Bitwise OR of A and B
 Op <= "111"; wait for Clk_period; --Bitwise XOR of A and B
 wait;
 end process;
END;

I have added zero flag but modelsim cant read output, also tried the overflow but it says identifier issues. and when I wrte the if statement for zero flag it expects == or+or-or* etc

1

There are 1 answers

1
Laburtz On

While this isn't necessarily an answer. There seems to be quite a few things wrong with your code. I made some fixes and recopied below. Did not check your logic. Only your syntax. Run the TB now and see if this helps. Also it would help in the future if you list the actual errors you received. Also I would suggest tying all your internal signals to a reset for initialization.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity simple_alu is
port( 
    Clk : in std_logic; --clock signal
    rst_i : std_logic; -- reset signal
    A,B : in std_logic_vector(31 downto 0); --input operands
    Op : in std_logic_vector(2 downto 0); --Operation to be performed
    R : out std_logic_vector(31 downto 0); --output of ALU
    z: out STD_LOGIC; --Zero flag
    Cry : out  STD_LOGIC
 );
end simple_alu;
architecture Behavioral of simple_alu is

--temporary signal declaration
signal Reg1 : std_logic_vector(31 downto 0) := (others => '0'); --Changed these to SLV to match below. 
signal Reg2 : std_logic_vector(31 downto 0) := (others => '0');
signal Reg3 : std_logic_vector(31 downto 0) := (others => '0');


begin   
    --Do you intend for the internal signal assignments to be asynchronous? This means that a signal value could change while waiting on an operation to be performed. Could give bad results.
    Reg1 <= A;
    Reg2 <= B;
    R <= Reg3;
    --z <=z; commented out. Not sure what you are trying to say here.
    --Cout <= Cry;

process(Clk,rst_i)
    variable temp : std_logic_vector(32 downto 0); --This was marked (31 downto 0), but below you are calling bit 32. Changed the size of this vector to match logic.
begin
    --OP Code Handling
    if(rst_i = '1') then -- Example of reset
        --reset internal signals
        --Reg3 <= (others => '0'); -- an example
    elsif(rising_edge(Clk)) then --Do the calculation at the positive edge of clock cycle.
        case Op is
        when "000" =>
            Reg3 <= std_logic_vector(unsigned(Reg1) + unsigned(Reg2)); --addition. Use subtype conversions for handling adding of SLVs
        when "001" =>
            Reg3 <= std_logic_vector(unsigned(Reg1) - unsigned(Reg2)); --subtraction
        when "010" => -- called case Op twice. removed the second call
            temp := std_logic_vector(("0" & unsigned(Reg1)) + unsigned(Reg2));
            Reg3 <= temp(31 downto 0);
            Cry <= temp(32);
        when "011" =>
            Reg3 <= Reg1 nand Reg2; --NAND gate
        when "100" =>
            Reg3 <= Reg1 nor Reg2; --NOR gate
        when "101" =>
            Reg3 <= Reg1 and Reg2; --AND gate
        when "110" =>
            Reg3 <= Reg1 or Reg2; --OR gate
        when "111" =>
            Reg3 <= Reg1 xor Reg2; --XOR gate
        when others =>  NULL;
        end case;
    end if;

    if (Reg3="00000000000000000000000000000000")then --This wasn't large enough. Added another Zero
        z <='1'; -- Changed these to single bit, you had them as 2 bit values.
    else
        z <='0';
    end if; --forgot to end if
end process;
end Behavioral;