0% found this document useful (0 votes)
37 views

Elements of Computing Systems CH 2 Boolean Arithmetic

This document discusses binary arithmetic and signed binary numbers. It explains how binary numbers are represented and arithmetic operations like addition and subtraction are performed at the bit level in computers. It also describes half adders, full adders and how they are used to build multi-bit adders to perform operations on binary numbers.

Uploaded by

Saad Imran δδ
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
37 views

Elements of Computing Systems CH 2 Boolean Arithmetic

This document discusses binary arithmetic and signed binary numbers. It explains how binary numbers are represented and arithmetic operations like addition and subtraction are performed at the bit level in computers. It also describes half adders, full adders and how they are used to build multi-bit adders to perform operations on binary numbers.

Uploaded by

Saad Imran δδ
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

Chapter 2: Boolean Arithmetic 1

2. Boolean Arithmetic1
Counting is the religion of this generation, its hope and salvation.
(Gertrude Stein, American writer, 1874-1946)

In this chapter we build the Boolean circuits that represent numbers and perform arithmetic
operations on them. Our starting point is the set of logic gates we built in the last chapter, and
our ending point is a fully functional Arithmetic Logical Unit. The ALU is the centerpiece chip
that executes all the arithmetic and logical operations performed by the computer.

1. Background
Binary Numbers: Unlike the decimal system, which is founded on base 10, the binary system is
founded on base 2. When we are given a certain binary pattern, say 10011, and we are told that
this pattern is supposed to represent an integer number, the decimal value of this number is
computed by convention as follows:

(10011) two = 1 2 4 + 0 2 3 + 0 2 2 + 1 21 + 1 2 0 = 19 (1)

In general, let x = x n x n 1 ...x 0 be a string of digits. The value of x in base b, denoted ( x) b , is defined
as follows:
n
( xn xn1 ...x0 ) b = xi b i (2)
i =0

The reader can verify that in the case of (10011) two , rule (2) reduces to calculation (1).

The result of calculation (1) happens to be 19. Thus, when we press the keyboard keys labeled
1, 9 and ENTER while running, say, a spreadsheet program, what ends up in some register in
the computer is the binary code 10011. More precisely, if the computer happens to be a 32-bit
machine, say, what gets stored in the register is the bit pattern
00000000000000000000000000010011.

Binary addition: A pair of binary numbers can be added digit-by-digit from right to left,
according to the same elementary school method used in decimal addition. First, we add the two
right-most digits, also called the least significant bits of the two binary numbers. Next, we add
the resulting carry bit (which is either 0 or 1) to the sum of the next pair of bits up the
significance ladder. We continue the process until the two most significant bits are added. If the
last bit-wise addition generates a carry of 1, we can report overflow; otherwise, the addition
completes successfully.

1
From The Elements of Computing Systems, Nisan & Schocken, MIT Press, forthcoming in 2003, www.idc.ac.il/csd
Chapter 2: Boolean Arithmetic 2

0 0 0 1 (carry) 1 1 1 1
1 0 0 1 x 1 0 1 1
+ 0 1 0 1 y + 0 1 1 1
0 1 1 1 0 x+ y 1 0 0 1 0
no overflow overflow

FIGURE 1: Two examples of binary addition (assuming 4-bit registers). In the


case of overflow, the computation can be rendered invalid.

We see that computer hardware for binary addition must be able to calculate the sum of three bits
(pair of bits plus carry bit) and pass the carry bit from the addition of one pair of bits to the
addition of the next significant pair of bits.

Signed binary numbers: A binary system with n digits can code 2 n different bit patterns. Let us
call this set of patterns the system's "code space". To represent signed numbers in binary code, a
natural solution is to split this space into two equal subsets. One subset of codes is assigned to
represent positive numbers, and the other negative numbers. The exact coding scheme should be
chosen in such a way that, ideally, the introduction of signed numbers would complicate the
hardware implementation as little as possible.

This challenge has led to the development of several coding schemes for representing signed
numbers in binary code. The method used today by almost all modern computers is called the 2s
complement method, also known as radix complement. In a binary system with n digits, the 2s
complement of the number x is defined as follows:

2 n x if x 0
x= (3)
0 otherwise

For example, in a 5-bit binary system, the 2s complement representation of -2 or


minus (00010 ) two is 2 5 (00010 ) two = (32) ten (2) ten = (30) ten = (11110 ) two . To check the calculation,
the reader can verify that (00010 ) two + (11110 ) two = (00000 ) two . Note that in the latter computation,
the sum is actually (100000 ) two , but since we are dealing with a 5-bit binary system, the left-most
6th bit is lost. As a rule, when the 2's complement method is applied to n-bit numbers, x + ( x )
always sums up to 2 n (i.e. 1 followed by n 0's). This property gives the method its name. Table
2 illustrates a 4-bit binary system with the 2's complement method.
Chapter 2: Boolean Arithmetic 3

Positive Negative
Numbers Numbers
0 0000
1 0001 1111 -1
2 0010 1110 -2
3 0011 1101 -3
4 0100 1100 -4
5 0101 1011 -5
6 0110 1010 -6
7 0111 1001 -7
1000 -8

TABLE 2: the 2s complement representation of integer


numbers, assuming a 4-bit binary system.

An inspection of Table 2 suggests that an n-bit binary system with 2s complement representation
has the following properties:
The system can code a total of 2 n signed numbers, of which the maximal and
minimal numbers are 2 n 1 1 and 2 n 1 , respectively;
The codes of all positive numbers begin with a "0";
The codes of all negative numbers begin with a "1";
To obtain the code of x from the code of x, leave all the trailing (least significant)
0s and the first least significant 1 intact, then flip all the remaining bits (convert 0s
to 1s and vice versa). An equivalent shortcut, which is easier to implement in
hardware, is to flip all the bits of x and add 1 to the result.
A particularly attractive feature of this representation is that addition of any two numbers in 2s
complement is exactly identical to addition of positive numbers. Consider, for example, the
addition operation (-2) + (-3): using 2s complement (in a 4-bit representation) we have to add, in
binary, (1110)two + (1101)two. Without paying any attention to which numbers (positive or
negative) these codes represent, bit-wise addition will yield 1011 (after throwing away the 5th
overflow bit). Indeed, this is the 2s complement representation of (-5).
In short, we see that we are able to perform addition of any two signed numbers without requiring
any special hardware beyond that needed for simple bit-wise addition. What about subtraction?
Recall that in the 2s complement method, the arithmetic negation of a signed number x, i.e.
computing x, is achieved by negating all the bits of x and adding 1 to the result. Thus
subtraction can be handled by x y = x + ( y ) . Once again, hardware complexity is kept to a
minimum.
The material implications of these theoretical results are significant. Basically, they imply that a
single chip, called Arithmetic Logical Unit, can be used to encapsulate all the basic arithmetic and
logical operators performed in hardware. We now turn to specify one such ALU, beginning with
the specification of an adder chip.
Chapter 2: Boolean Arithmetic 4

2. Specification
Adders

We present a hierarchy of three adders, leading to a multi-bit adder chip:

Half-adder: designed to add 2 bits;


Full-adder: designed to add 3 bits;
Adder: designed to add two n-bit numbers.

We also present a special-purpose adder, called incrementer, designed to add 1 to a given


number.

Half Adder: The first step on our way to adding binary numbers is to be able to add two bits.
This task requires the handling of four possible cases:

0+0 = 00
0+1 = 01
1+0 = 01
1+1 = 10

We will now present a chip, called half-adder, that implements this addition operation. The least
significant bit of the addition is called sum, and the most significant bit is called carry.

Inputs Outputs
a b carry sum
0 0 0 0 a s um
h alf
0 1 0 1
ad d er
1 0 0 1 b c arry
1 1 1 0

Chip name: HalfAdder


Inputs: a, b
Outputs: sum, carry
Function: sum = LSB of a+b
carry = MSB of a+b

DIAGRAM 3: Half Adder, designed to add 2 bits.


Chapter 2: Boolean Arithmetic 5

Full Adder: Now that we know how to add 2 bits, we present a full-adder chip, designed to add
3 bits. Like the half-adder case, the full-adder chip produces two outputs: the least significant bit
of the addition, and the carry bit.

a b c carry sum
0 0 0 0 0
0 0 1 0 1 a
0 1 0 0 1 s um
0 1 1 1 0 b fu ll
1 0 0 0 1 ad d er c arry
c
1 0 1 1 0
1 1 0 1 0
1 1 1 1 1

Chip name: FullAdder


Inputs: a, b, c
Outputs: sum, carry
Function: sum = LSB of a+b+c
carry = MSB of a+b+c

DIAGRAM 4: Full Adder, designed to add 3 bits.

Adder: Memory and register chips represent integer numbers by n-bit patterns, n being 16, 32,
64, etc. depending on the computer platform. The chip whose job is to add such numbers is
called a multi-bit adder, or simply adder. We present a 16-bit adder, noting that our diagrams
and specifications scale up as-is to any n-bit system.

16
a 16
1 0 1 1 a 1 6 -b it
o ut
b + ad d e r
16
0 0 1 0 b
1 1 0 1 out

Chip name: Add16


Inputs: a[16],b[16]
Outputs: out[16]
Function: out=a+b
Comment: integer 2's complement addition.
overflow is neither detected nor handled.

DIAGRAM 5: 16-bit adder. The example (top left) illustrates the addition
of two 4-bit numbers. n-bit addition for any n is more of the same.
Chapter 2: Boolean Arithmetic 6

Incrementer: It is convenient to have a special purpose chip dedicated to adding the constant 1
to a given number. Here is the API of a 16-bit incrementer:

Chip name: Inc16


Inputs: in[16]
Outputs: out[16]
Function: out=in+1
Comment: integer 2's complement addition.
overflow is neither detected nor handled.

The Arithmetic Logic Unit (ALU)


The specifications of the adder chips presented so far were generic, meaning that they hold for
every computer. We now turn to discuss the specific 16-bit ALU of the Hack platform. This
chip is designed to compute a fixed set of functions out= f i (x,y) where x and y are the chip's two
16-bit inputs, out is the chip's 16-bit output, and f i is an arithmetic or logical function selected
from a fixed repertoire of possible functions. We instruct the Hack ALU which function to
compute by setting a set of six input bits, called control bits, to certain binary values. The exact
specification of which function the ALU computes given each setting of the control bits is given
in Diagram 6, using pseudo-code.
Chapter 2: Boolean Arithmetic 7

zx nx zy ny f no

x
16 bits
ALU 16 bits
out
y
16 bits

zr ng

Chip name: ALU


Inputs: x[16],y[16], // data inputs
zx, // zero the x input
nx, // negate the x input
zy, // zero the y input
ny, // negate the y input
f, // function code: 1 for Add, 0 for And
no // negate the out output
Outputs: out[16], // data output
zr, // status flag, true when the ALU output=0
ng // status flag, true when the ALU output<0
Function: if zx then x=0 // 16-bit zero constant
if nx then x=~x // bit-wise negation
if zy then y=0 // 16-bit zero constant
if ny then y=~y // bit-wise negation
if f then out=x+y // integer 2's complement addition
else out=x&y // bit-wise And
if no then out=~out // bit-wise negation
if out=0 then zr=1 else zr=0 // 16-bit equality comparison
if out<0 then ng=1 else ng=0 // 2's-complement comparison
Comment: overflow is neither detected nor handled.

DIAGRAM 6: The ALU of the Hack platform: interface and API. The ALU operation (the
function computed on x and y) is determined by the six control bits. The ALU sets the output
bits zr and ng to 1 when the output out is zero or negative, respectively.

Note that each one of the six control bits instructs the ALU to carry out a certain operation.
Taken together, the combined effects of these operations cause the ALU to compute a variety of
useful functions. Since the ALU is controlled by six control bits, it can potentially compute
2 6 = 64 different functions. 18 of these functions are documented in Table 7.
Chapter 2: Boolean Arithmetic 8

these bits instruct how to these bits instruct how to this bit selects this bit inst. how resulting
pre-set the x input pre-set the y input betw. + / And to post-set out ALU output

zx nx zy ny f no out=
If f then
If zx then If nx then If zy then If ny then If no then
x=0 x=~x y=0 y=~y
out=x+y else
out=~out f(x,y)=
out=x And y
1 0 1 0 1 0 0
1 1 1 1 1 1 1
1 1 1 0 1 0 -1
0 0 1 1 0 0 x
1 1 0 0 0 0 y
0 0 1 1 0 1 ~x
1 1 0 0 0 1 ~y
0 0 1 1 1 1 -x
1 1 0 0 1 1 -y
0 1 1 1 1 1 x+1
1 1 0 1 1 1 y+1
0 0 1 1 1 0 x-1
1 1 0 0 1 0 y-1
0 0 0 0 1 0 x+y
0 1 0 0 1 1 x-y
0 0 0 1 1 1 y-x
0 0 0 0 0 0 x&y
0 1 0 1 0 1 x|y

TABLE 7: The ALU truth table. Taken together, the binary operations coded by the
first six columns (input control bits) in each row affect the overall function listed in
the right column of that row. (We use the symbols ~, &, and | to represent the
operators Not, And, and Or, respectively, performed bit-wise.). The complete ALU
truth table consists of 64 rows, of which only the 18 presented here are of interest.

We see that programming the ALU to compute a certain function f(x,y) is done by setting the six
control bits to the code of the desired function. From this point on, the internal ALU logic
specified in Diagram 6 should cause the ALU to output the value f(x,y) specified in Table 7. This
does not happen miraculously -- its the result of careful design.

For example, let us consider the 12th row of table 7, where the ALU is instructed to compute the
function x-1. The zx and nx bits are 0, so the x input is neither zeroed nor negated. The zy and
ny bits are 1, so the y input is first zeroed, and then negated bit-wise. Bit-wise negation of zero,
(000...00)two, gives (11111)two, which is the 2s complement code of -1. Thus the ALU inputs
end up being x and -1. Since the f-bit is 1, the selected operation is arithmetic addition, causing
Chapter 2: Boolean Arithmetic 9

the ALU to calculate x+(-1). Finally, since the no bit is 0, the output is not negated but rather left
as is. To conclude, the ALU ends up computing x-1, which was our goal.

Does the ALU logic described in Table 6 compute every one of the other 17 functions listed in
the right column of Table 7? To verify that this is indeed the case, the reader is advised to pick up
some other rows in the table and prove their respective ALU operation. We note in passing that
some of these computations, beginning with the function f(x,y)=1, are not trivial. We also note
that there are some other useful functions computed by the ALU but not listed in the table.

It may be instructive to describe the thought process that led to the design of this particular ALU.
First, we made a list of all the primitive operations that we wanted our computer to be able to
execute (right column in Table 7). Next, we used backward reasoning to figure out how x, y, and
out can be manipulated in binary fashion in order to carry out the desired operations. These
processing requirements, along with our objective to keep the ALU logic as simple as possible,
have led to the design decision to use six control bits, each associated with a certain binary
operation. The resulting ALU is simple and elegant.

3. Implementation
Our implementation guidelines are intentionally partial, since we want you to discover the actual
chip architectures yourself. As usual, each gate can be implemented in more than one way; the
simpler the implementation, the better.

Half Adder: An inspection of Diagram 3 reveals that the functions sum(a,b) and carry(a,b)
happen to be identical to the standard Xor(a,b) and And(a,b) functions. Thus, the implementation
of this adder is rather trivial, using previously built gates.

Full Adder: A Full-Adder chip can be implemented from two half-adder chips and one
additional simple gate. Other direct implementation options are also possible, without using half-
adder chips.

Adder: The addition of two signed numbers represented by the 2's complement method as two
n-bit busses can be done bit-wise, from right to left, in n steps. In step 0, the least significant pair
of bits is added, and the carry bit is fed into the addition of the next significant pair of bits. The
process continues until in step n-1 the most significant pair of bits is added. Note that each step
involves the addition of 3 bits. Hence, an n-bit adder can be implemented by creating an array of
n full-adder chips, and chaining them in such a way that the carry bit of each adder is fed into one
of the inputs of the next adder up the significance ladder.

Incrementer: An n-bit incrementer can be implemented trivially from an n-bit adder.

ALU: Note that the ALU was carefully planned to effect all the desired ALU operations
logically, using simple Boolean operations. Therefore, the physical implementation of the ALU
is reduced to implementing these simple Boolean operations, following their pseudo-code
specifications. Your first step will likely be to create a logic circuit that manipulates a 16-bit
input according to nx and zx control bits (i.e. the circuit should conditionally zero and negate the
16-bit input). This logic can be used to manipulate the x and y inputs, as well as the out output.
Chapter 2: Boolean Arithmetic 10

Chips for addition and for bit-wise And-ing have already been built. Thus, what remains is to
build logic that chooses between them according to the f control bit. Finally, you will need some
logic that integrates all the other chips into the overall ALU.

4. Perspective
The construction of the multi-bit adder presented in this chapter was standard, although no
attention was paid to efficiency. In fact, our suggested adder implementation is rather inefficient,
due to the long delays incurred while the carry propagates from the least significant bit to the
most significant bit. This problem can be alleviated using logic circuits that effect so-called
"carry look-ahead" techniques. Since addition is one of the most prevalent operations in any
given computer architecture, such low-level improvements can result in dramatic and global
performance gains throughout the computer.

In any given computer, the overall functionality of the hardware/software platform is delivered
jointly by the ALU and the operating system that runs on top of it. Thus, when designing a new
computer system, the question of how much functionality the ALU should deliver is essentially a
cost/performance issue. The general rule is that hardware implementations of arithmetic and
logical operations are usually more costly, but achieve better performance. The design tradeoff
that we have chosen in this book is to specify an ALU hardware with a limited functionality and
then implement as many operations as possible in software. For example, our ALU features
neither multiplication and division operations, nor floating point arithmetic. Some of these
operations (as well as more mathematical functions) will be implemented at the operating system
level, as described in Chapter 11.

Detailed treatments of Boolean arithmetic and ALU design can be found in standard
undergraduate textbooks such as [Hennessy & Patterson, chapter 4].

5. Build It
Objective: Implement all the chips presented in this chapter, using previously built chips.

Tip: When your HDL programs invoke chips that you may have built in the previous project, it is
recommended to use instead the built-in versions of these chips. This will ensure correctness and
speed up the operation of the hardware simulator. There is a simple way to accomplish this
convention: make sure that your project directory includes only the files that belong to the present
project.

The remaining instructions for this project are identical to those from Chapter 1, except that every
occurrence of the text "project1" should be replaced with "project2".

You might also like