ALU

Introduction to Design Tools
COE 1502
Example design: ALU

Recall that the ALUOp is 4 bits
–
–

High-order two bits used to determine operation class (ALUOp(3:2))
Low-order two bits used to determine which operation is performed within each class
(ALUOp(1:0))
Next, let’s define “operation classes” and have subblocks compute intermediate
results in parallel…
–
Logical operations (ALUOp(3:2) == “00”)

–
Arithmetic operations (ALUOp(3:2) == “01”)

–
SLT, SLTU
Shift (ALUOp(3:2) == “11”)


ADD, ADDU, SUB, SUBU
Comparison (ALUOp(3:2) == “10”)

–
AND, OR, NOR, XOR
SLL, SRL, SRA
Idea: perform each operation type in parallel and select the appropriate output
using the two high-order bits of ALUOp
Example design: ALU

Add subblocks, name them, and wire them up…
–
Note that ALUOp needs a bus ripper…
Use wire
tool here
Example design: ALU

Let’s take a look at the generated VHDL for the top-level
design…
–
Things to note





Same entity statement as before
Internal signal declarations
Subblocks declared as components (with interfaces)
Embedded block code
Instance port mappings
Example design: ALU
LIBRARY ALU;
ARCHITECTURE struct OF ALU IS
-- Architecture declarations
-- Internal signal declarations
SIGNAL ArithmeticR : std_logic_vector(63
SIGNAL Asign
: std_logic;
SIGNAL Bsign
: std_logic;
SIGNAL CarryOut
: std_logic;
SIGNAL ComparisonR : std_logic_vector(63
SIGNAL LogicalR
: std_logic_vector(63
SIGNAL Rsign
: std_logic;
SIGNAL ShifterR
: std_logic_vector(63
-- Component Declarations
COMPONENT Arithmetic
PORT (
A
: IN
std_logic_vector
ALUOp
: IN
std_logic_vector
B
: IN
std_logic_vector
ArithmeticR : OUT
std_logic_vector
CarryOut
: OUT
std_logic ;
Overflow
: OUT
std_logic ;
Zero
: OUT
std_logic
);
END COMPONENT;
COMPONENT Comparison
PORT (
ALUOp
: IN
std_logic_vector
Asign
: IN
std_logic ;
Bsign
: IN
std_logic ;
CarryOut
: IN
std_logic ;
Rsign
: IN
std_logic ;
ComparisonR : OUT
std_logic_vector
);
END COMPONENT;
DOWNTO 0);
DOWNTO 0);
DOWNTO 0);
DOWNTO 0);
(63 DOWNTO 0);
(1 DOWNTO 0);
(63 DOWNTO 0);
(63 DOWNTO 0);
(1 DOWNTO 0);
(63 DOWNTO 0)
COMPONENT Logical
PORT (
A
: IN
ALUOp
: IN
B
: IN
LogicalR : OUT
);
END COMPONENT;
COMPONENT Mux4Bus32
PORT (
ALUOp
: IN
ArithmeticR : IN
ComparisonR : IN
LogicalR
: IN
ShifterR
: IN
R
: OUT
);
END COMPONENT;
COMPONENT Shifter
PORT (
A
: IN
ALUOp
: IN
SHAMT
: IN
ShifterR : OUT
);
END COMPONENT;
std_logic_vector
std_logic_vector
std_logic_vector
std_logic_vector
(63 DOWNTO 0);
(1 DOWNTO 0);
(63 DOWNTO 0);
(63 DOWNTO 0)
std_logic_vector
std_logic_vector
std_logic_vector
std_logic_vector
std_logic_vector
std_logic_vector
std_logic_vector
std_logic_vector
std_logic_vector
std_logic_vector
(3 DOWNTO 2);
(63 DOWNTO 0);
(63 DOWNTO 0);
(63 DOWNTO 0);
(63 DOWNTO 0);
(63 DOWNTO 0)
(63 DOWNTO 0);
(1 DOWNTO 0);
(5 DOWNTO 0);
(63 DOWNTO 0)
-- Optional embedded configurations
-- pragma synthesis_off
FOR ALL : Arithmetic USE ENTITY ALU.Arithmetic;
FOR ALL : Comparison USE ENTITY ALU.Comparison;
FOR ALL : Logical USE ENTITY ALU.Logical;
FOR ALL : Mux4Bus32 USE ENTITY ALU.Mux4Bus32;
FOR ALL : Shifter USE ENTITY ALU.Shifter;
-- pragma synthesis_on
Example design: ALU
BEGIN
-- Architecture concurrent statements
-- HDL Embedded Text Block 1 eb1
Asign <= A(31);
Bsign <= B(31);
Rsign <= ArithmeticR(31);
-- Instance port mappings.
I1 : Arithmetic
PORT MAP (
A
=> A,
ALUOp
=> ALUOp(1 DOWNTO 0),
B
=> B,
ArithmeticR => ArithmeticR,
CarryOut
=> CarryOut,
Overflow
=> Overflow,
Zero
=> Zero
);
I2 : Comparison
PORT MAP (
ALUOp
=> ALUOp(1 DOWNTO 0),
Asign
=> Asign,
Bsign
=> Bsign,
CarryOut
=> CarryOut,
Rsign
=> Rsign,
ComparisonR => ComparisonR
);
I0 : Logical
PORT MAP (
A
=>
ALUOp
=>
B
=>
LogicalR =>
);
I4 : Mux4Bus32
PORT MAP (
ALUOp
ArithmeticR
ComparisonR
LogicalR
ShifterR
R
);
I3 : Shifter
PORT MAP (
A
=>
ALUOp
=>
SHAMT
=>
ShifterR =>
);
END struct;
A,
ALUOp(1 DOWNTO 0),
B,
LogicalR
=>
=>
=>
=>
=>
=>
ALUOp(3 DOWNTO 2),
ArithmeticR,
ComparisonR,
LogicalR,
ShifterR,
R
A,
ALUOp(1 DOWNTO 0),
SHAMT,
ShifterR
Example design: ALU

Next, let’s create the logical sub-block…
–
Double-click the logical subblock
–
This design will perform all four logical operations in parallel and select the
desired result using the low-order two bits of ALUOp




AND => 00
OR => 01
XOR => 10
NOR => 11
Example design: ALU






Notice the new block diagram
already has the interface ports and
signals…
Add four embedded blocks (yellow
blocks) to implement the operations
Next, wire up the blocks to the
inputs (A,B), create an output mux,
wire it to the output bus and ALUOp
We can change the symbols for the
yellow blocks
We’ll need to assign names for the
internal/intermediate signals in the
design
Add the appropriate concurrent
VHDL code for each block
–
What are concurrent semantics?
Example design: ALU

Let’s take a look at the generated VHDL...
ARCHITECTURE struct OF Logical IS
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
ENTITY Logical
PORT(
A
ALUOp
B
LogicalR
);
IS
:
:
:
:
-- Declarations
END Logical ;
-- Architecture declarations
IN
IN
IN
OUT
std_logic_vector
std_logic_vector
std_logic_vector
std_logic_vector
(63 DOWNTO 0);
(1 DOWNTO 0);
(63 DOWNTO 0);
(63 DOWNTO 0)
-- Internal
SIGNAL ANDR
SIGNAL NORR
SIGNAL ORR
SIGNAL XORR
signal declarations
: std_logic_vector(63
: std_logic_vector(63
: std_logic_vector(63
: std_logic_vector(63
DOWNTO
DOWNTO
DOWNTO
DOWNTO
0);
0);
0);
0);
BEGIN
-- Architecture concurrent statements
-- HDL Embedded Text Block 1 ANDBlock
ANDR <= A AND B;
-- HDL Embedded Text Block 2 ORBlock
ORR <= A OR B;
-- HDL Embedded Text Block 3 XORBlock
XORR <= A XOR B;
-- HDL Embedded Text Block 4 NORBlock
NORR <= A NOR B;
-- HDL Embedded Text Block 5 Mux4B64
LogicalR <= ANDR when ALUOp="00" else
ORR when ALUOp="01" else
XORR when ALUOp="10" else
NORR;
-- Instance port mappings.
END struct;
Example design: ALU

Once we’re done, we’ll
generate VHDL and compile
the design in order to
simulate
–

The “M” button will perform the
entire design flow
We’re now presented with
the ModelSim window
–
–
Under the View menu option,
open the signals and wave
windows
Drag the signals from the
signals window to the wave
window
Right click to
change radix
Structure
Drag/drop signals
(or right click)
Example design: ALU

From this point, we can use force/run commands to simulate the
design
–
Examples








restart –f
view wave
add wave /ALU/A
force ALUOp “0010”
force A X”000000FF”
force A 10#32
run 10
run
–


Turn off warnings
Note that the signals can be represented in hexadecimal
–

Default runlength is 100 ns
Right-click the signals in the wave window to change its properties
We can also write a text “.do” file to aid in simulation
–
Invoked using “do” command

example:
–
do “i:/alpha/alu/test_logical.do”
Example design: ALU



Let’s go back to the top-level ALU block
diagram and create the Shifter subblock
We’ll implement the Shifter as a
flowchart (useful for testbenches)
Flowcharts implement a behavioral
VHDL architecture as a process
–
–
–

Primarily, we use:
–
–
–
–
–
–

Processes are executed sequentially, not
concurrently
Started when signal in sensitivity list changes
Allows programming constructs and variables
Start/end points
Action boxes (also hierarchical)
Decision boxes
Wait boxes (not synthesizable)
Loop boxes
Flows
Operations are assigned to ALUOp(1:0)
–
–
–
SLL => 00
SRL => 10
SRA => 11
Example design: ALU (assume 32-bit words)



Add decision box to check whether this is
a left shift or a right shift
If this is a left shift, add another decision
box to check the least significant bit of
SHAMT
Then add an action box to assign a
variable the input value, shifted 1 bit
–

We’ll have to add this variable to the
variable declaration list
–
–
–

Note the syntax for assigning variables
Under “Flow Chart Properties”, right-click
the design
We’ll need LeftOne, LeftTwo, LeftFour,
LeftEight, and LeftSixteen
Right-click, “Flow Chart Properties”
Idea: For each set bit n in the SHAMT
value, shift the input value 2n positions to
the left
–
Always shift in 0
Example design: ALU
Example design: ALU
Example design: ALU

For the right shift, there’s a
complication
–
–
–
What about arithmetic shifts?
For this, we use a LOOP block
to assign a 16-bit Fill variable
the value we will shift in
From then on, we’ll follow the
same procedure as with the left
shift, but with new variables


RightOne, RightTwo,
RightFour, RightEight, and
RightSixteen
When we’re finished, we’ll
simulate this block as we did
before
Example design: ALU

Final variable declaration list:
variable
variable
variable
variable
variable
variable
variable
variable
variable
LeftOne : std_logic_vector(31 downto 0);
LeftTwo : std_logic_vector(31 downto 0);
LeftFour : std_logic_vector(31 downto 0);
LeftEight : std_logic_vector(31 downto 0);
RightOne : std_logic_vector(31 downto 0);
RightTwo : std_logic_vector(31 downto 0);
RightFour : std_logic_vector(31 downto 0);
RightEight : std_logic_vector(31 downto 0);
Fill : std_logic_vector(31 downto 0);
Example design: ALU
Example design: ALU





Next, we’ll design the arithmetic
subblock as another block
diagram
We need to implement signed
and unsigned addition and
subtraction
We have a 32-bit adder
component in the COELib
library we can instantiate for
use in this design
Use the green component
button to add the ADD32
component from COELib
Wire up the design as follows…
Drag and drop components
from component browser
Modify Downstream Mapping for COELib
Example design: ALU

Let’s note a few things about this design
• How does the generated VHDL for the arithmetic
block differ from the shifter block?
• How is subtraction implemented using an adder?
• What is the precise difference between
signed and unsigned operations in this
context?
• How do we detect overflow in signed and
unsigned arithmetic?
• What reason would we have to detecting a
zero result?
• How well does our macro file test the unit?
Example design: ALU

Now let’s design the comparison subblock using the truth table view
–
–
Implementing signed and unsigned “set-on-less than” (A < B)
We need to utilize the subtraction results from the arithmetic subblock as
inputs to the table

Need to make sure the two low-order bits match those for subtraction in the
arithmetic unit
–
–

Outputs from arithmetic unit used as inputs
–
–

–
–
–
Sign of A
Sign of B
Output
–
–
The sign of the result
Carryout
Other inputs we need
–
–

SLT => 10
SLTU => 11
Single bit output in low-order bit
Rows and columns can be added by a right-click
Columns can be resized
Note: blank cells are considered “don’t cares”
Reminder: In VHDL, single bit literals (std_logic) are surrounded by single
quotes, bit vectors (std_logic_vector) are surrounded by double quotes
Example design: ALU
Initial truth table view
–
–
You will need to add rows
You might want to reorder the columns
Example design: ALU

Notes:
–
–
–
–
Keep in mind that we’re testing to determine if A is less than
B
Keep in mind that our inputs assume that the operation
being reflected by Rsign and CarryOut is A - B
(SLT) Why do we only consider Rsign when A and B’s signs
match?
(SLTU) How do we use CarryOut to perform comparisons?
Example design: ALU
Operation
A sign
B sign
R sign CarryOut
Output
SLT
+
-
0
SLT
-
+
1
SLT
+
+
+
0
SLT
+
+
-
SLT
-
-
+
1
0
SLT
-
-
-
1
SLTU
0
1
SLTU
1
0
Example design: ALU
Example design: ALU
--------------------------------------------------------------------------truth_process: PROCESS(ALUOp, Asign, Bsign, CarryOut, Rsign)
--------------------------------------------------------------------------BEGIN
-- Block 1
IF (ALUOp(1 DOWNTO 0) = "00") THEN
ComparisonR <= "00000000000000000000000000000000";
ELSIF (ALUOp(1 DOWNTO 0) = "01") THEN
ComparisonR <= "00000000000000000000000000000000";
ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '0') AND (Bsign = '0') AND (Rsign
ComparisonR <= "00000000000000000000000000000000";
ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '0') AND (Bsign = '0') AND (Rsign
ComparisonR <= "00000000000000000000000000000001";
ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '1') AND (Bsign = '1') AND (Rsign
ComparisonR <= "00000000000000000000000000000000";
ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '1') AND (Bsign = '1') AND (Rsign
ComparisonR <= "00000000000000000000000000000001";
ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '0') AND (Bsign = '1') THEN
ComparisonR <= "00000000000000000000000000000000";
ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '1') AND (Bsign = '0') THEN
ComparisonR <= "00000000000000000000000000000001";
ELSIF (ALUOp(1 DOWNTO 0) = "11") AND (CarryOut = '1') THEN
ComparisonR <= "00000000000000000000000000000000";
ELSIF (ALUOp(1 DOWNTO 0) = "11") AND (CarryOut = '0') THEN
ComparisonR <= "00000000000000000000000000000001";
END IF;
END PROCESS truth_process;
= '0') THEN
= '1') THEN
= '0') THEN
= '1') THEN
Example design: ALU

Finally, let’s finish the top-level ALU design by
designing the implementation for the Mux4bus32
–
For this, we’ll use a VHDL architecture/entity view

Note: the entity is not necessary in this view… it will be
generated automatically anyway
R <=
LogicalR when ALUOp(3 downto 2)="00" else
ArithmeticR when ALUOp(3 downto 2)="01" else
ComparisonR when ALUOp(3 downto 2)="10" else
ShifterR;