Eduardo Gutierrez
Eduardo Gutierrez

Reputation: 59

How can I add two std_logic_vectors that have been concatenated in VHDL?

I'm working on an ALU using a certain set of functions. I figured that the addition and bitshift portions would be a lot easier if I used an extra bit to store the carry out. I'm trying to concatenate an extra bit to two 8 bit long 'std_logic_vector's. The extra bit would hold the carry out in the addition.

However when I go to run the simulation after some debugging it doesn't look like the lines I used to give s_a and s_b their values are doing anything. If I were to take out the default values they come out empty.

I'm sure the error is something silly, I'm not to familiar with how concatenation works in vhdl, maybe theres a better way of storing the carry out, any help would be appreciated.

CODE:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity ALU is
    Port ( 
            A       : in std_logic_vector(7 downto 0);
            B       : in std_logic_vector(7 downto 0);
            SEL     : in std_logic_vector(3 downto 0);
            Cin     : in std_logic;
            Result  : out std_logic_vector(7 downto 0);
            C       : out std_logic;
            Z       : out std_logic);

end ALU;

architecture Behavioral of ALU is

signal s_result: unsigned(8 downto 0) := "000000000";
signal s_cin: unsigned(8 downto 0) := "000000000";
signal s_a: unsigned(8 downto 0) := "000000000";
signal s_b: unsigned(8 downto 0) := "000000000";
signal s_exempt: std_logic := '0';

begin

s1: process(A, B, SEL, CIN)
    begin

        s_a <= ('0' & unsigned(A));
        s_b <= ('0' & unsigned(B));
        s_cin(0) <= Cin;
        s_exempt <= '0';

        case SEL is
          when "0000" =>   
            s_result <= s_a + s_b;
            C <= s_result(8);
          when "0001" =>                    --ADDc Add with carry
            s_result <= s_a + s_b + s_cin;
            C <= s_result(8);
          when "0010" =>                    --SUB
            if(s_a > s_b) then
                s_result <= s_a - s_b;
                C <= '0';
            else
                s_result <= s_b - s_a;
                C <= '1';
            end if;
          when "0011" =>                    --SUBc Subtract with carry

            if(s_a > (s_b + s_cin)) then
              s_result <= s_a - s_b - s_cin;
              C <= '0';
            else
              s_result <= s_b - s_a - s_cin;
              C <= '1';
            end if;
          when "0100" =>                    --CMP  Compare both values              
            if(s_a > s_b) then
                C <= '0';
                Z <= '0';  
            elsif(s_a = s_b) then
                Z <= '1';
                C <= '0';         
            else
                C <= '1';
                Z <= '1';
            end if;
            s_exempt <= '1';     
          when "0101" =>                    --AND
            s_result <= s_a AND s_b;
            C <= '0';
          when "0110" => Z<= '1';           --OR
            s_result <= s_a OR s_b;
            C <= '0';
          when "0111" =>                    --EXOR
            s_result <= s_a XOR s_b;
            C <= '0';
          when "1000" =>                    --TEST, comparator, flag change ONLY
            if((s_a AND s_b) = "000000000") 
                then
                    C <= '0';
                    Z <= '1';
            else
                C <= '0';
                Z <= '0';
            end if;
          when "1001" =>                    --LSL Left shift
            s_result <= s_a sll 1;
            C <= s_result(8);
          when "1010" =>                    --LSR RIght shift
            C <= s_a(0);
            s_result <= s_a srl 1;
          when "1011" => Z<= '1';           --ROL Rotate Left
            s_result <= s_a sll 1;
            C <= s_result(8);
            s_result(0) <= s_result(8);
          when "1100" => Z<= '1';           --ROR Rotate Right
            C <= s_a(0);
            s_result <= s_a srl 1;
            s_result(0) <= s_a(0);
          when "1101" =>                    --ASR Arithemetic Roation
            C <= s_a(0);
            s_result <= s_a srl 1;
            s_result(8) <= s_a(7);
          when "1110" =>                    --MOV Moves data into result
            s_result <= s_b;
            s_exempt <= '1';
          when others => 
            s_result <= "000000000";
            s_exempt <= '1';
            Z <= '0';
            C <= '0';
        end case;

        if(s_exempt = '0') -- Checks Result for 0 if hasn't been found
            then 
                 if(s_result(7 downto 0) = "00000000") 
                    then 
                        Z <= '1';
                 else Z <= '0';
                 end if;
        end if;

       Result <= std_logic_vector(s_result(7 downto 0)); 

    end process; 

end Behavioral;

TESTBENCH:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity simulation is
end simulation;

architecture Behavioral of simulation is

    COMPONENT ALU
        Port ( 
               A         : in std_logic_vector(7 downto 0);
               B         : in std_logic_vector(7 downto 0);
               SEL        : in std_logic_vector(3 downto 0);
               Cin        : in std_logic;
               Result    : out std_logic_vector(7 downto 0);
               C         : out std_logic;
               Z        : out std_logic
          );
    END COMPONENT;

    signal A : std_logic_vector(7 downto 0) := "00000000";
    signal B : std_logic_vector(7 downto 0) := "00000000";
    signal SEL : std_logic_vector(3 downto 0) := "0000";
    signal Cin : std_logic;
    signal Result : std_logic_vector(7 downto 0) := "00000000";
    signal C: std_logic := '0';
    signal Z: std_logic := '0';

    begin

        uut: ALU PORT MAP (
            A => A,
            B => B,
            SEL => SEL,
            Cin => Cin,
            Result => Result,
            C => C,
            Z => Z
        );

        stim_proc: process
        begin
            A <= "00000001";
            B <= "00100001";
            SEL <= "0000";
            Cin <= '1';
            wait for 10ns;
            wait;
        end process;
end Behavioral;

Upvotes: 0

Views: 1328

Answers (1)

Matthew
Matthew

Reputation: 13967

Any signal assigned in a process in VHDL is not updated until the process suspends. So, for example, the value of s_result from this line:

s_result <= s_a + s_b + s_cin;

will not be updated by the time that this line is executed:

C <= s_result(8);

You need to find out about delta delays, then once you have, you will need to rewrite your code.

VHDL is a hardware description language. You are designing hardware, not writing software. For example, your initialisation of all your signals will not be implemented in hardware, meaning that your simulation may well behave differently to your hardware:

signal s_result: unsigned(8 downto 0) := "000000000";
signal s_cin: unsigned(8 downto 0) := "000000000";
signal s_a: unsigned(8 downto 0) := "000000000";
signal s_b: unsigned(8 downto 0) := "000000000";
signal s_exempt: std_logic := '0';

Upvotes: 1

Related Questions