Search code examples
functionvhdl

Std_logic_vector adding function


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

entity unu is
port(a,b:std_logic_vector(1 downto 0);
    q:out std_logic_vector(2 downto 0)
   );
end unu;

architecture Behavioral of unu is

function max (op1, op2 : INTEGER) return INTEGER is
    begin
        if op1 > op2 then
           return op1;
        else
           return op2;
        end if;
    end max;

function "+"( A,B:std_logic_vector) return std_logic_vector is
constant size1: INTEGER := a'LENGTH;
constant size2: INTEGER := b'LENGTH;
constant size:integer :=max(size1,size2)+1;
variable result:std_logic_vector(size downto 0);
begin
result:=std_logic_vector(unsigned(A)+unsigned(B));
return result;
end "+";

begin
q<=a+b;  --line 28

end Behavioral;

I receive this error

ERROR:HDLCompiler:410 -Line 28: Expression has 2 elements ; expected 4

I'm trying to make a function that adds two std_logic_vector


Solution

  • There is a requirement in assignment that there is an element on the right hand side for every element on the left hand side. Your left hand side signal q has 3 elements. The expression on the right hand side has 4 (max length of A and B,plus 1, plus identity (size downto 0).

    The failure is actually in assigning the std_logic_vector conversion of the unsigned "+" operator result to result in the function, which you have made length 4:

    constant size:integer :=max(size1,size2)+1;
    variable result:std_logic_vector(size downto 0);
    

    If you want a "+" operator that adds std_logic_vector values as unsigned and increases the length by one try:

    architecture Behavioral of unu is
    
        -- function max (op1, op2 : INTEGER) return INTEGER is
        --     begin
        --         if op1 > op2 then
        --            return op1;
        --         else
        --            return op2;
        --         end if;
        --     end max;
    
        function "+"( A,B:std_logic_vector) return std_logic_vector is
        -- constant size1: INTEGER := a'LENGTH;
        -- constant size2: INTEGER := b'LENGTH;
        -- constant size:integer :=max(size1,size2)+1;
        -- variable result:std_logic_vector(size downto 0);
        begin
        -- result:=std_logic_vector(unsigned(A)+unsigned(B));
        -- return result;
        return std_logic_vector('0' & unsigned(A)+unsigned(B));
        end "+";
    
    begin
        q<=a+b;  --line 28
    
    end Behavioral;
    

    You could achieve the same result by:

        return std_logic_vector(unsigned(A)+unsigned(B));
    

    And resizing one of the operands or the result assigned to q:

        q <= ('0' & a) + b; 
    

    OR

        q <= a + ('0' & b);
    

    OR

        q <= '0' & (a + b);
    

    Sign extending only makes sense for signed addition. Operand padding gives the normal arithmetic meaning for the result.

    The function declaration for unsigned "+" in package numeric_std:

    function "+" (L, R: UNSIGNED) return UNSIGNED;
    -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0).
    -- Result: Adds two UNSIGNED vectors that may be of different lengths.
    

    Shows the length of the result is adjusted for the maximum of the length of the Left or Right argument already.