\documentclass[11pt]{article}
\usepackage{handout2e}
\input{macros}
\input{epsf}
\usepackage{graphicx}
%\usepackage[dvips]{graphicx}
\usepackage{epsfig}
\begin{document}

\input{courseMacros}
\thispagestyle{empty}
\setlength{\parindent}{0pt}
\setlength{\parskip}{1.8ex}

\newcommand{\load}{\mbox{{\it lod }}}
\newcommand{\add}{\mbox{{\it add }}}
\newcommand{\ngt}{\mbox{{\it neg }}}
\newcommand{\jump}{\mbox{{\it jiz }}}

\lecturehead{CS1800}{Discrete Structures}{Fall 2010}{23 September 2010}{}

\begin{center}
\Large{\bf Design of a simple processor}
\end{center}


\section{Architecture}

The processor we will design will have the following components:

\begin{itemize}
\item
8 32-bit registers $R_0$, $R_1$, \ldots, $R_7$ for holding data.

\item
256 16-bit registers $P_0$, $P_1$, \ldots, $P_{255}$ for holding a
program.

\item
A 32-bit adder.

\item
An 8-bit register $PC$ that will serve as a program counter.
\end{itemize}

It is useful to have the constant values $0$ and $1$ available for
use.  So we set registers $R_0$ and $R_1$ to hold the values $0$ and
$1$, respectively, permanently.

The processor will have five types of instructions: {\em add}, {\em
negate}, {\em load}, and {\em jump if zero}.  A program consists of a
sequence of instructions stored in the 256 program registers.  Each of
these registers holds 16 bits.  The 16 bits of an instruction specify
the type of instruction and its operands.  We need two bits to specify
the instruction; the first two of the 16 bits (positions 0 and 1) will
specify the instruction type.  The formats of the 4 instructions are
as follows.

The add instruction adds the contents of two registers $R_a$ and $R_b$
and stores the result in register $R_c$.  The indices $a$, $b$, and
$c$ are specified in bit positions 2-4, 5-7, and 8-10, respectively.
Bit positions 11-15 will be ignored.  The add instruction also
increments the program counter by 1.  The add instruction 
\[
\add R_a, R_b \rightarrow R_c
\]

is encoded as follows.

\begin{center}
\begin{tabular}{cccccccccccccccc}
0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 &
15\\ \hline
0 & 0 & a & a & a &  b & b & b & c & c & c & 0 & 0 & 0 & 0 & 0\\ \hline
\end{tabular}
\end{center}

\junk{
\begin{figure}[htb]
\begin{center}
\epsfig{file=add}
%\includegraphics[width=4in]{add.eps}
\end{center}
\end{figure}
}
The negate instruction replaces $R_a$ with $-R_a$, using the two's
complement representation.  The index $a$ is specified by bit
positions 2-4.  The negate instruction also increments the program
counter by 1.  The negate instruction
\[
\ngt R_a
\]
is encoded as follows.

\begin{center}
\begin{tabular}{cccccccccccccccc}
0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 &
15\\ \hline
0 & 1 & a & a & a & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ \hline
\end{tabular}
\end{center}

\junk{\begin{figure}[htb]
\begin{center}
\includegraphics[width=4in]{negate}
\end{center}
\end{figure}
}

The load instruction loads an 8-bit number $d$ into the 8 low-order
bit positions of register $R_a$.  The index $a$ is specified by bit
positions 2-4.  The value $d$ is specified in binary by the 8
low-order positions of the instruction; that is, positions 8-15.  The
effect of the instruction is to set the value in register $R_a$ to
$d$; note that the 24 high-order bits of $R_a$ are set to 0.  Also,
the program counter is incremented by 1.  The load instruction
\[
\load d \rightarrow R_a
\]
is encoded as follows.

\begin{center}
\begin{tabular}{cccccccccccccccc}
0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 &
15\\ \hline
1 & 0 & a & a & a & 0 & 0 & 0 & d & d & d & d & d & d & d & d\\ \hline
\end{tabular}
\end{center}

\junk{\begin{figure}[htb]
\begin{center}
\includegraphics[width=4in]{load}
\end{center}
\end{figure}
}

The jump if zero instruction changes the program counter register to
the value specified by an 8-bit number $d$, if register $R_a$ is 0;
otherwise the program counter $PC$ is incremented by 1, as usual.  The
jump if zero instruction
\[
\jump R_a \rightarrow d
\]
is encoded as follows.

\begin{center}
\begin{tabular}{cccccccccccccccc}
1 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 &
15\\ \hline
1 & 0 & a & a & a & 0 & 0 & 0 & d & d & d & d & d & d & d & d\\ \hline
\end{tabular}
\end{center}

\junk{\begin{figure}[htb]
\begin{center}
\includegraphics[width=4in]{jump}
\end{center}
\end{figure}
}

\section{Multiplexers and demultiplexers}

Digital circuits are designed in a modular fashion, building more and
more complex components out of basic building blocks.  A key component
of almost every digital circuit is a device that selects any one of
many inputs and sends that value to a single output, called a {\em
  selector}.

\smallskip

Consider a $2$-way $1$-bit multiplexer that has three inputs $X_0$,
$X_1$, and $Y$, and a single output $Z$.  If $Y$ (called the {\em
  control}) is $0$, then the output $Z$ is the same as $X_0$; if $Y$
is $1$, then the output $Z$ is the same as $X_1$.  For example, if
$X_0$ is $0$, $X_1$ is $1$, and $Y$ is $1$, then $Z$ equals $1$.  The
truth table for the above multiplexer is as follows.

\[
\begin{array}{c@{\ }c@{\ }c|c}
X_0 & X_1 & Y & Z \\
\hline
  0 &   0 & 0 & 0 \\
  0 &   0 & 1 & 0 \\
  0 &   1 & 0 & 0 \\
  0 &   1 & 1 & 1 \\
  1 &   0 & 0 & 1 \\
  1 &   0 & 1 & 0 \\
  1 &   1 & 0 & 1 \\
  1 &   1 & 1 & 1
\end{array}
\]

We can now express the output $Z$ as a Boolean formula in terms of the
inputs $X_0$, $X_1$, and $Y$.  Simplifying the Boolean formula as much
as you can, by applying the laws of logical equivalence, we obtain the
following.

\begin{flushleft} % Locally scoped abbreviations
\renewcommand\a\land
\renewcommand\o\lor
\renewcommand\O{\ \lor\ }
\newcommand\n\neg
\newcommand\xz{X_0}
\newcommand\xx{X_1}
\newcommand\y{Y}
Begin by reading off the disjunctive normal form (DNF) of $Z$ from the truth
table:
\[
\begin{array}{r@{{}={}}r@{{}\O{}}l}
Z & (\n\xz\a\xx\a\y) \O (\xz\a\n\xx\a\n\y) & (\xz\a\xx\a\n\y) \O (\xz\a\xx\a\y)
\end{array}
\]
Then simplify using commutativity, distributivity, and the fact that $A\o\n A =
T$:
\[
\begin{array}{r@{{}={}}r@{{}\O{}}l}
Z
& (\n\xz\a\xx\a\y) \O (\xz\a\n\xx\a\n\y) & (\xz\a\xx\a\n\y) \O (\xz\a\xx\a\y) \\
& (\n\xz\a\xx\a\y) \O (\xz\a\xx\a\y) & (\xz\a\xx\a\n\y) \O (\xz\a\n\xx\a\n\y) \\
& ((\n\xz\o\xz)\a\xx\a\y) & (\xz\a(\xx\o\n\xx)\a\n\y) \\
& (\xx\a\y) & (\xz\a\n\y)
\end{array}
\]
\end{flushleft}

We are now ready to design a circuit for the multiplexer.  

\[
\includegraphics[width=2in]{prob4-iii-circuit}
\]

As one can imagine, an equally important device is the {\em
  demultiplexer}, that essentially does the opposite of what the
multiplexer does: it sends a single input to one of many outputs,
depending on a control value.  Consider a demultiplexer that has two
inputs $X$ and $Y$ and two outputs $Z_0$ and $Z_1$.  If $Y$ is $0$,
then $Z_0$ takes the value of $X$, and $Z_1$ is $0$.  On the other
hand, if $Y$ is $1$, then $Z_1$ takes the value of $X$, and $Z_0$ is
$0$.

We now design a circuit for the demultiplexer, proceeding as
above. The DNF is particularly simple for this truth table, so we
don't need to simplify the Boolean formulas.
\[
%
\begin{array}{c@{\ }c|c@{\ }c}
X & Y & Z_0 & Z_1 \\
\hline
0 & 0 & 0   & 0   \\
0 & 1 & 0   & 0   \\
1 & 0 & 1   & 0   \\
1 & 1 & 0   & 1   \\
\end{array}
%
\qquad\qquad
%
\begin{array}{r@{{}={}}l}
Z_0 & X \land \neg Y \\
Z_1 & X \land Y
\end{array}
%
\qquad\qquad
%
\begin{array}{c}
\includegraphics[width=1in]{prob4-iv-circuit}
\end{array}
%
\]

\junk{
\section{Clocked gates and registers}

Using a combination of clocked and unclocked NOT gates, we can design
registers.  Here is a depiction of a 4-bit register that accepts a
4-bit value on its 4 inputs before a clock pulse, and puts that value
on its 4 outputs.

\begin{center}
\begin{figure}[ht]
\includegraphics[width=4in]{register}
\caption{\label{fig:register} A 4-bit register}
\end{figure}
\end{center}

The above register only holds values for one clock cycle.  It is much
more helpful if we could design the register so as to hold the values
for an extended period of time.  We can extend the register circuit
from above so that it accepts an extra input $S$ (for Set).  If $S$ is
$1$, then the new circuit behaves exactly as above when the clock
pulses.  However, if $S$ is $0$ when the clock pulses, then the
register ignores its inputs, keeping the same outputs as before the
clock pulse.
}

\section{Design of the processor}

We will design the entire processor using the basic gates that we have
studied, along with clocks.  We have already seen how to build adders
from gates.  We will next use gates (unclocked and clocked) to build
multiplexers, demultiplexers, and registers, and then move on to more
complex components.  We will present the design in a modular fashion
-- building more complex components from simpler components that we
have already designed.  Finally we assume that the registers $P_0,
\ldots, P_{255}$ already contain the instructions to run, and their
contents do not need to be changed.

\junk{ You may use as many adders, multiplexers, demultiplexers, and
  registers of any size as you need.  You may also design and use your
  own circuits as you wish.  You may also use the constant values 0
  and 1 as inputs to any of your circuits.

Show your design using a diagram.  You need not show the design of the
basic components we have already built.  For instance, if you are
using a 4-way 1-bit multiplexer, you may simply draw a picture
depicting the multiplexer.  Make your design as simple as possible,
without worrying about optimizing the size of the circuit.

({\em Hint:} The program counter should serve as the control input to
a multiplexer, that selects the instruction to execute.  The registers
should serve as data inputs to one or more multiplexers.)
}

\junk{
\item
Write a program for the above processor to multiply two numbers, which
are stored in registers $R_2$ and $R_3$.  The final result is to be
placed in register $R_4$.  Don't worry about overflows.  Since our
processor does not have a halt instruction, you can end your program
by going into an infinite loop.

The following example program takes two numbers, say $x$ and $y$,
which are stored in registers $R_2$ and $R_3$, respectively, computes
$x + 15 - y$, stores the result in $R_4$, and enters into an infinite
loop.

\begin{eqnarray*}
0 & \load & 15 \rightarrow R_5\\
1 & \add & R_2, R_5 \rightarrow R_6\\
2 & \add & R_3, R_0 \rightarrow R_5\\
3 & \ngt & R_5\\
4 & \add & R_6, R_5 \rightarrow R_4\\
5 & \jump & R_0 \rightarrow 5
\end{eqnarray*}


\item
Write a program for the above processor to compute $F_n$, the $n$th
Fibonacci number.  Assume that $n$ is stored in register $R_2$, and
that the final answer is stored in $R_3$.  Again, don't worry about
overflows; and you can end your program by going into an infinite loop.
\end{enumerate}
}

Our design will proceed in steps. 

\begin{enumerate}
\item 
We lay out the registers (giving names to the input bits, output bits,
and registers for convenience).
\item
We design the circuits for extracting the next instruction and
incrementing the PC.
\item
We design the circuits for implementing the add, negate, load, and
jump-if-zero operations.
\item
We design the circuit that determines the input and the set bits for
the data registers and the PC based on the above circuits.
\item
In each of the above circuits, we clearly label the inputs and
outputs.  These circuits can be put together by matching the
appropriate labeled inputs and outputs.
\end{enumerate}

\newpage

\subsection{Registers} 
Here is a layout of the registers.  Note that the set bit for PC is
always 1 and the set bit of program registers is always 0.  So the PC
changes at every clock cycle and the program registers never change.
The set bits for the data registers will be determined by the
instruction.

\begin{figure}[htb]
\begin{center}
\includegraphics[width=0.8\textwidth]{registers}
\end{center}
\end{figure}

\newpage

\subsection{Extracting the instruction and incrementing the PC} The
following are the circuits for extracting the next instruction using
the PC, and calculating the increment of PC.  Note that whether the PC
will be actually incremented (or set to something else) will be
determined by the instruction, as we will see shortly.

\begin{figure}[htb]
\begin{center}
\includegraphics[width=0.8\textwidth]{instruction}
\end{center}
\end{figure}

\newpage

\subsection{The add instruction}
Here is the circuit for implementing the add instruction.  

\begin{figure}[htb]
\begin{center}
\includegraphics[width=0.8\textwidth]{execute_add}
\end{center}
\end{figure}

\newpage

\subsection{The negate instruction}
Here is the circuit for implementing the negate instruction.  

\begin{figure}[htb]
\begin{center}
\includegraphics[width=0.8\textwidth]{execute_negate}
\end{center}
\end{figure}


\newpage

\subsection{The load instruction}
Here is the circuit for implementing the load instruction.  

\begin{figure}[htb]
\begin{center}
\includegraphics[width=0.8\textwidth]{execute_load}
\end{center}
\end{figure}

\newpage

\subsection{The jump-if-zero instruction}
Here is the circuit for implementing the jump-if-zero instruction.  

\begin{figure}[htb]
\begin{center}
\includegraphics[width=0.8\textwidth]{execute_jump}
\end{center}
\end{figure}

\newpage

\subsection{Storing the new values into the data registers and PC}
The values computed by the add, negate, load, and jump-if-zero
circuits give us potential values that need to be stored in the data
registers.  Whether the registers need to be updated and what their
new values will be is determined by the particular instruction type.
The following circuit pushes in the correct value into the registers.
It also determines the correct value of the PC.  The inputs to the
program registers are the same as their outputs (since they are not
allowed to change).

\begin{figure}[htb]
\begin{center}
\includegraphics[width=0.8\textwidth]{input_registers}
\end{center}
\end{figure}

\section*{Acknowledgments}
This unit is based on material from the course ``Great Theoretical
Ideas in Computer Science'' taught at Carnegie Mellon University.
\end{document}


