lolbardsnin
lolbardsnin

Reputation: 311

Unsigned multiplication in VHDL 4bit vector?

im making an ALU with an option to do A + 2B but im having trouble getting my head around multiplying the 2B and getting the proper answer in my test bench.

EG: A = 0110 B = 0011 Equation is A + 2B and im getting 0110

a snippit of my code is

entity ALU is 
         port( A     :IN     STD_LOGIC_VECTOR(3 DOWNTO 0) ;
               B     :IN     STD_LOGIC_VECTOR(3 DOWNTO 0) ;
               S0    :IN     STD_LOGIC ;
               S1    :IN     STD_LOGIC ;
               M     :IN     STD_LOGIC ;
                    C0    :IN     STD_LOGIC ;

               Cout  :OUT    STD_LOGIC ;    
               Z     :OUT    STD_LOGIC ;
               F     :OUT    STD_LOGIC_VECTOR(3 DOWNTO 0));







  SIGNAL VariableAlu : STD_LOGIC_VECTOR(3 DOWNTO 0);
    SIGNAL FTEMP       : STD_LOGIC_VECTOR(3 DOWNTO 0);  
    SIGNAL FTEMP2      : STD_LOGIC_VECTOR(4 DOWNTO 0);
    SIGNAL ZTEMP        : STD_LOGIC;
    SIGNAL BTEMP1        : STD_LOGIC_VECTOR(4 DOWNTO 0);

        END ALU ;
        PROCESS(A,B,S0,S1,M,C0)
        BEGIN   

                VariableAlu <= (S0 & S1 & C0 & M); 
                 --M = 1 ARITHMETIC

  (part that shifts it, lab teacher told us to do this)
                    BTEMP1(4 DOWNTO 1)<= B;
                    BTEMP1(0)<= '0';

when "1111" => FTEMP2 <= ((A) + BTEMP1);

any help would be greatly appreciated.

Upvotes: 2

Views: 9603

Answers (2)

JHBonarius
JHBonarius

Reputation: 11291

In addition to what GSM said, you can also just write what you want. I.e. a multiplication by 2. Synthesis software is smart enough to recognize what you are doing. What you have to remember is that the result will be too large, so it has to be resized.

library IEEE;
use IEEE.std_logic_1164.all;

entity input_output_adder is
    port (
        input_a : in  std_logic_vector(4 downto 0);
        input_b : in  std_logic_vector(4 downto 0);
        output  : out std_logic_vector(4 downto 0)
        );
end entity;

architecture rtl of input_output_adder is
    use IEEE.numeric_std.all;
begin
    output <= std_logic_vector(unsigned(input_a) + resize((unsigned(input_b) * 2), 5));
end architecture;

This will result in only LUTs... nu multipliers.

Result from Vivado: Result from Vivado

Result from Quartus: Result from Quartus

Upvotes: 3

gsm
gsm

Reputation: 408

There are a few things to note about your code. Firstly, for any arithmetic, avoid using SLV and stick with unsigned or signed types from the numeric_std library.

Your explicit shift (multiplication by 2) for the operand B:

BTEMP1(4 DOWNTO 1)<= B;
BTEMP1(0)<= '0';

Is, a) not required, and b) verbose. You can achieve this by simply doing BTEMP <= B & '0';, or better yet, don't even use an intermediary signal and assign directly to FTEMP2 in the switch statement. eg.

when "1111" => FTEMP2 <= std_logic_vector(unsigned(A) + unsigned(B&'0'));

Note the conversions in the above line. They are required, as by default, SLV's do not support the + operator (unless you use the std_logic_unsigned or std_logic_signed libraries). You will need to include the numeric_std library for this.

EDIT:

I also forgot to mention that FTEMP will potentially overflow for the given function; F <= A + 2B, where A and B are both 4 bits and F is 5 bits.

Upvotes: 1

Related Questions