2

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.

lolbardsnin
  • 305
  • 1
  • 4
  • 14

2 Answers2

3

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

JHBonarius
  • 10,824
  • 3
  • 22
  • 41
1

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.

gsm
  • 389
  • 2
  • 10
  • Heya yeah im using the unsigned library, and yeah i figured doing those 2 operations prior to the a+2b could be substituted with B&0. but whats confusing me is how shifting it is equal to multiplying it. eg: 0011 which is then shifted 00110 but isnt 0011*2 = 1001 or am i totally off the mark ? (our teacher suggested this method without telling us why so i really want to understand it properly) – lolbardsnin Apr 01 '17 at 00:01
  • _0011 which is then shifted 00110 but isnt 0011*2 = 1001 or am i totally off the mark ?_ 0011 is 3 in decimal; multiplied by 2 gives 6 in decimal, which is 0110 in binary (which is the correct answer; 1001 in decimal is 9). The reason shifting is equivalent to multiplication (or division, depending on direction) by 2, is because binary is base 2. Similar to base 10 (decimal) arithmetic; When you multiply/divide by 10 you are "moving" the decimal point (ie. 3*10 = 30; 3/10 = 0.3) – gsm Apr 01 '17 at 00:45
  • OHHHHH i had totally missed that, I feel like such a dufas. thanks heaps – lolbardsnin Apr 01 '17 at 01:05
  • although these 1 little issue still i just made a double check using your BTEMP <= B & '0'; and my old one along with setting A= 0000 and B= 0000 but for my F output im getting 1110 which honestly is weird – lolbardsnin Apr 01 '17 at 01:37
  • I [don't](https://postimg.org/image/g8cjsw817/) (though this is a minimalist design/tb) – gsm Apr 01 '17 at 01:57
  • There are a few errors in your actual code; Line 78 and 80. On both of them you are concatenating a single bit using "0" - You need to use single quotes ('0'). Also, you are missing a bracket on line 78. A basic sim using your code works for me, using `S0` = `S1` = `M` = `C0` = 1 (which would give you the correct `VariableAlu` case) – gsm Apr 01 '17 at 02:14
  • ah i had corrected those since then. anyway thankyou for your assistance!! may i ask what simulator you're using ? – lolbardsnin Apr 02 '17 at 01:48
  • @gsm you are converting to `unsigned`, but then not using `left_shift()`. Why? Furthermore, I believe that modern synthesis software will just optimize `std_logic_vector(unsigned(A) + unsigned(B)*2);` to combinatorial logic. – JHBonarius Apr 04 '17 at 09:36
  • @J.H.Bonarius I convert to unsigned to add the vectors, instead of using `std_logic_unsigned`. What value is there in using `left_shift()` in this instance? The same thing is achieved in a less verbose matter, with the equivalent being `FTEMP2 <= std_logic_vector(unsigned(A) + shift_left(unsigned('0'&B), 1));`. Exactly the same hardware is inferred by the synth tools. Almost all arithmetic *will* infer combinational logic (there are some situations in which this does not apply, such as mult by 2^n); This is not an optimisation. – gsm Apr 04 '17 at 11:37
  • It is about readability imho. writing `B&'0'` is the [digital] electrical engineering approach: designing a digital electronic circuit. Although possible with VHDL, many features have been introduced to be able to use VHDL as a high level programming language. For instance the `ieee.numeric_std` library. It contains a number of functions like `shift_left`, `resize`, etc. When coming from a software background, you would recognize `shift_left(unsigned(B),1)` as `(unsigned int)B << 1` – JHBonarius Apr 04 '17 at 12:00