<- previous    index    next ->

Lecture 8, ALU

The Arithmetic Logic Unit is the section of the CPU that actually
performs add, subtract, multiply, divide, and, or, floating point and
other operations. The choice of which operations are implemented is
determined by the Instruction Set Architecture, ISA. Most modern
computers separate the integer unit from the floating point unit.
Many modern architectures have simple integer, complex integer, and
an assortment of floating point units.




The ALU gets inputs from registers reg_use.jpg

Where did numbers such as 100010 for subop and  000010 for sllop
come from ? cs411_opcodes.txt


-- alu_start.vhdl

library IEEE;
use IEEE.std_logic_1164.all;

entity alu_32 is
  port(inA    : in  std_logic_vector (31 downto 0);
       inB    : in  std_logic_vector (31 downto 0);
       inst   : in  std_logic_vector (31 downto 0);
       result : out std_logic_vector (31 downto 0));
end entity alu_32;


architecture schematic of alu_32 is 
  signal cin     : std_logic := '0';
  signal cout    : std_logic;
begin  -- schematic
  --
  --   REPLACE THIS SECTION FOR PROJECT PART 1
  --   (add the signals you need above the "begin"
  --    add logic below the "begin")
  
  adder: entity WORK.add32 port map(a    => inA,
                                    b    => inB,     -- change
                                    cin  => cin,     -- change
                                    sum  => result,  -- change
                                    cout => cout);

-- examples of entity instantiations:
  
-- bsh: entity WORK.bshift port map (left    => sllop,
--                                   logical => '1',
--                                   shift   => inst(10 downto 6),
--                                   input   => inB,
--                                   output  => bresult);

-- r1: entity WORK.equal6  port map (inst  => inst(31 downto 26),
--                                   test  => "000000",
--                                   equal => rrop);

-- s1: entity WORK.equal6  port map (inst  => inst(5 downto 0),
--                                   test  => "100010",         -- 34
--                                   equal => subop1);
-- s1a: subop <= subop1 and rrop;


--      S_sel <= sllop_or_srlop; -- for mux32_6

-- much more
   
end architecture schematic;  -- of alu_32

Many variations of  subop, subop1, subop_and, subopa
Your starter part1ce_start.vhdl  uses  subopa short for subop_and.  		 
part1ce_start.vhdl





-- mux32_3.vhdl

library IEEE;
use IEEE.std_logic_1164.all;
entity mux32_3 is
  port(in0    : in  std_logic_vector (31 downto 0);
       in1    : in  std_logic_vector (31 downto 0);
       in2    : in  std_logic_vector (31 downto 0);
       ct1    : in  std_logic;          -- pass in1(has priority)
       ct2    : in  std_logic;          -- pass in2
       result : out std_logic_vector (31 downto 0));
end entity mux32_3;

architecture behavior of mux32_3 is 
begin  -- behavior -- no process needed with concurrent statements
  result <= in1 when ct1='1' else in2 when ct2='1' else in0 after 50 ps;
end architecture behavior;  -- of mux32_3

-- mux_32_6.vhdl  have only zero or one  ctl  ='1'

library IEEE;
use IEEE.std_logic_1164.all;

entity mux_32_6 is
  port(in0    : in  std_logic_vector (31 downto 0);
       in1    : in  std_logic_vector (31 downto 0);
       in2    : in  std_logic_vector (31 downto 0);
       in3    : in  std_logic_vector (31 downto 0);
       in4    : in  std_logic_vector (31 downto 0);
       in5    : in  std_logic_vector (31 downto 0);
       ctl1   : in  std_logic;
       ctl2   : in  std_logic;
       ctl3   : in  std_logic;
       ctl4   : in  std_logic;
       ctl5   : in  std_logic;
       result : out std_logic_vector (31 downto 0));
end entity mux_32_6;

architecture behavior of mux_32_6 is 
begin  -- behavior -- no process needed with concurrent statements
  result <= in1 when ctl1='1' else in2 when ctl2='1' else
            in3 when ctl3='1' else in4 when ctl4='1' else
            in5 when ctl5='1' else in0 after 10 ps;
end architecture behavior;  -- of mux_32_6






Note that bshift.vhdl contains two different architectures
for the same entity. A behavioral architecture using sequential
programming and a circuits architecture using digital logic
components.

bshift.vhdl


An 8-bit version of shift right logical, using single bit signals,
three bit shift count, is:






There are many ways to build an ALU. Often the choice is based
on mask making and requires a repeated pattern. The "bit slice"
method uses the same structure for every bit. One example is:



Note that 'Operation' is two bits, 0 for logical and, 1 for logical or,
2 for add or subtract, and 3 for an operation called set used for
comparison.
'Binvert' and 'CarryIn' would be set to '1' for subtract.
'Binvert' and 'a' set to '0' would be complement.
The overflow detection is in every stage yet only used in the
last stage.

The bit slices are wired together to form a simple ALU:



The 'set' operation would give non zero if 'a' < 'b' and
zero otherwise. A possible condition status or register
value for a "beq" instruction.


If overflow was to be detected, the circuit below uses the
sign bit of the A and B inputs and the sign bit of the
result to detect overflow on twos complement addition.


 



The ALU fits into the machine architecture as shown below:





32-bit and 64-bit  ALU  architectures are available.

A 64-bit architecture, by definition, has 64-bit integer registers.
Many computers have had 64-bit IEEE floating point for many years.
The 64-bit machines have been around for a while as the Alpha and
PowerPC yet have become popular for the desktop with the Intel and
AMD 64-bit machines.



Software has been dragging well behind computer architecture.
The chaos started in 1979 with the following "choices."



The full whitepaper www.unix.org/whitepapers/64bit.html

My desire is to have the compiler, linker and operating system be ILP64.
All my code would work fine. I make no assumptions about word length.
I use sizeof(int)  sizeof(size_t) etc. when absolutely needed.
On my 8GB computer I use a single array of over 4GB thus the subscripts
must be 64-bit. The only option, I know of, for gcc is  -m64 and that
just gives LP64. Yuk! I have to change my source code and use "long"
everywhere in place of "int". If you get the idea that I am angry with
the compiler vendors, you are correct!

Here are sample programs and output to test for 64-bit capability in gcc:

Get sizeof on types and variables big.c

output from  gcc -m64 big.c  big.out

malloc more than 4GB  big_malloc.c

output from  big_malloc_mac.out

Newer Operating Systems and compilers (note 'sizeof' changed to long)
Get sizeof on types and variables big12.c

output from  gcc big12.c  big12.out




The early 64-bit computers were:

DEC Alpha

DEC Alpha

IBM PowerPC


Some history of 64-bit computers:





Java for 64-bit, source compatible

Then to VHDL resource, FPGA.
get free GHDL

    <- previous    index    next ->

Other links

Go to top