You are on page 1of 10

Andrew Stevens

TORO CPU PROJECT


Introduction:
In this project an 8 bit CPU was implemented on a DE2 FPGA development board.
We were given a pre made memory board and given the code that dealt with the
timing differences between the two boards. We were also given the 8 bit instruction
definitions. We were responsible for the implementation code for these instruction.
We were also responsible for the implementation of the control unit. The code used
to test our instruction set and control unit was placed on the ROM of the memory
unit by the professor. This allowed for quick testing and allowed for error correction
within implementation.
Data Flow:
Data flow within this system is controlled by the control unit and is centered on the
system bus. The other place data is transferred is within the accumulator register
and the ALU register allowing for adding of the system bus and the accumulator.
The first thing that is done on startup is MAR is loaded with PC + 1. Then the
instruction register is loaded with a location in memory that is determined by MAR
that was just loaded. The MAR is then set again to the next step in the PC register.
From this state all 5 other states are possible depending on what the Instruction
register was loaded as. There is Inherent addressing witch acts on the accumulator
then goes back a step and loads another Instruction from memory into the
Instruction Register. There is Direct Read that loads Mar from memory once.
Immediate mapping that acts on the data in the ALU register at the time and
memory. There is also indirect mapping which reads twice into MAR from memory.
Control Units:
The control unit is based on a state machine with 6 separate states. It uses an 8 bit
instruction to determine the actions to be done in each state and also which state it
goes to. The first two most significant bits determine if it is an ALU, BR, or STO
operation. There is an unused operation selection. The next two are bits determine
the type of addressing mode INH, IMM, DIR, and IND. These are the ones that
control what states the CPU will go through on that turn. The last three bits are the
operators and the Branch condition depending on the first two bits. The ALU
operations are as follows; B, A plus B, A and B, A or B, A xor B, and Shift R
arithmetic. The branch conditions were set by the Carry bit Negative bit and the
zero bit.
Debugging:
Solving technical difficulties was almost painless. The factors that contributed to the
ease of debugging are as follows; given pin assignments for, starting code has a
clock speed down control built in, and a given test program to run on the CPU. You
will need to know how to read binary and quickly transfer it to hex but with a known
program and known output and speed setting that allow for time to read the values
quick debugging can be done to figure out improper implementation of any of the
internal systems of the CPU.
1

Andrew Stevens

Conclusion:
The implementation of this CPU using AHDL works and accomplishes the
demonstration of binary arithmetic and the state machine used for the control data
flow. This allows for implementation of many programs and with enough memory
can almost do any algorithmic operation. To improve the operation of this CPU there
are several things that could be implemented to improve performance and
functionality. For the ALU a look ahead adder could be implemented to cut down on
time spent within two of the steps. More pipe lining could be implemented in order
to have a larger through put. The design could be ported over to VHDL which is an
electrical engineering standard. More functionalities could be added such as
multiplication and divide operation. The application of minimal instruction set does
have it benefits. It allows for optimization of the computations within the ALU. It also
makes it easy to upscale to more digits and potentially adding additional CPUs to
work in tandem with little ease.

Andrew Stevens

Andrew Stevens

Andrew Stevens
Visabool Design for the Control Unit
Reset IR[7..0] C N Z;

alu = ~IR7 ~IR6;


br = ~IR7 IR6;
sta = IR7 ~IR6;
inh = ~IR5 ~IR4;
imm = ~IR5 IR4;
dir = IR5 ~IR4;
ind = IR5 IR4;

st0 = ~s2 ~s1 ~s0;


st1 = ~s2 ~s1 s0;
st2 = ~s2 s1 ~s0;
st3 = ~s2 s1 s0;
st4 = s2 ~s1 ~s0;
st5 = s2 ~s1 s0;

s2.d = ~Reset st2 dir + ~Reset st2 imm + ~Reset st3 + ~Reset st4;
s1.d = ~Reset st1 + ~Reset st2 ind;
s0.d = ~Reset st0 + ~Reset st2 inh + ~Reset st2 imm + ~Reset st2 ind + ~Reset st4;

BCT = ~IR2 ~IR1 ~IR0 + ~IR2 ~IR1 IR0 C + ~IR2 IR1 ~IR0 N + ~IR2 IR1 IR0 Z + IR2 ~IR1 IR0 ~C +
IR2 IR1 ~IR0 ~N + IR2 IR1 IR0 ~Z;

ld_PC = st5 br BCT;


ld_IR = st1;
ld_A = inh st2 + st5 alu;
ld_MAR = st0 + st2 + st3 + st4;
write = st5 sta;
oe_PC = st0 + st2;
oe_A = st5 sta;
read = st1 + st3 + st4 + st5 br BCT + st5 alu;
inc_PC = st0 + st2;

Andrew Stevens
AHDL Code to Implement the TORO CPU
Subdesign Toro680
(
ClkM27, Reset_b, ClkSel[2..0]

:Input;

LdMAR, Rd_b, Wr_b, ClkDisp ,MemClkO :Output;


StOut[5..0] ,BusOut[7..0]
Bus[7..0]

:Output;
:BIDIR;

)
Variable
Ctr[27..0], MemClk, CpuClk

:Dff;

OeAClk, OeAdelayed

:Dff;

PC[7..0], IR[7..0], Ac[7..0], C

:Dff;

PCt[7..0], Act[7..0]

:Tri;

IncPC, LdPC, OePC, LdIR, LdA, OeA


Rd, Wr, Sum[8..0], N, Z, AndIt

:Node;

:Node;

Alu, Br, Sta, Inh, Imm, Dir, Ind

:Node;

Reset, BCT, Cda, Add, OrIt, XorIt, ShR :Node;


B[7..0]

:Tri_State_Node;

State

:Machine

With States(I0,I1,A0,A1,A2,Ex);
Begin
Ctr[].clk = ClkM27;
Ctr[].d = Ctr[].q+1;
MemClk.clk = ClkM27;
MemClk.d = (ClkSel[]==0)&Ctr[27] # (ClkSel[]==1)&Ctr[26]
# (ClkSel[]==2)&Ctr[24] # (ClkSel[]==3)&Ctr[22]
# (ClkSel[]==4)&Ctr[20] # (ClkSel[]==5)&Ctr[18]
# (ClkSel[]==6)&Ctr[16] # (ClkSel[]==7)&Ctr[6];
MemClkO = MemClk.q; % Clock being sent to Memory board %
OeAClk.clk = ClkM27;
OeAClk.d = (ClkSel[]==0)&Ctr[25] # (ClkSel[]==1)&Ctr[24]
# (ClkSel[]==2)&Ctr[22] # (ClkSel[]==3)&Ctr[20]
# (ClkSel[]==4)&Ctr[18] # (ClkSel[]==5)&Ctr[16]
# (ClkSel[]==6)&Ctr[14] # (ClkSel[]==7)&Ctr[4];

Andrew Stevens
OeAdelayed.clk = OeAClk.q; % OeAClk is 4 times faster than MemClk %
OeAdelayed.d = OeA;

% OeAdelayed.q is 1/4 MemClk cycle behind OeA %

Act[].oe = OeAdelayed.q; % The RAM chip requires significant hold time %

CpuClk.clk = ClkM27;
CpuClk.d = MemClk.q; % CpuClk is 1/27M sec (37 ns) behind MemClk %
PC[].clk = CpuClk;
IR[].clk = CpuClk;
AC[].clk = CpuClk;
C.clk = CpuClk;
State.clk = CpuClk;
ClkDisp = CpuClk;

% Clock being displayed on DE2 used by CPU Dffs %

--Sum[] = (0,Ac[]) + (0,B[]); % extend add to 9 bits for access to Carry %

Alu = !IR7 & !IR6;


Br = !IR7 & IR6;
Sta = IR7 & !IR6;

Inh = !IR5 & !IR4;


Imm = !IR5 & IR4;
Dir = IR5 & !IR4;
Ind = IR5 & IR4;

BCT = !IR2 & !IR1 & !IR0 #


!IR2 & !IR1 & IR0 & C #
!IR2 & IR1 & !IR0 & N #
!IR2 & IR1 & IR0 & Z #
IR2 & !IR1 & IR0 & !C #
IR2 & IR1 & !IR0 & !N #
IR2 & IR1 & IR0 & !Z;

LdPC = Ex & Br & BCT;

Andrew Stevens
LdIR = I1;
LdA = Inh & A0 # Ex & Alu;
LdMAR = I0 # A0 # A1 # A2;
Wr = Ex & Sta;
OePC = I0 # A0;
OeA = Ex & Sta;
Rd = I1 # A1 # A2 # Ex & Br & BCT # Ex & Alu;
IncPC = I0 # A0;

Reset = !Reset_b;
Rd_b = !Rd;
Wr_b = !Wr;

StOut[]= (I0 , I1 , A0 , A1 , A2 , Ex);

State.clk = CpuClk;
Case State Is
When I0 =>
If Reset Then State = I0;
ELSE State = I1; END IF;
When I1 =>
If Reset Then State = I0;
ELSE State = A0; END If;
When A0 =>
If Reset Then State = I0; End If;
If !Reset & Inh Then State = I1; End If;
If !Reset & Ind Then State = A1; End If;
If !Reset & Dir Then State = A2; End If;
If !Reset & Imm Then State = Ex; End If;
When A1 =>
If Reset Then State = I0;
ElSE State = A2; End If;
When A2 =>
If Reset Then State = I0;

Andrew Stevens
ElSE State = Ex; End If;
When Ex =>
State = I0;
End Case;

Cda = !IR0 & !IR1 & !IR2;


Add = !IR2 & !IR1 & IR0;
AndIt = !IR2 & IR1 & !IR0;
OrIt = !IR2 & IR1 & IR0;
ShR = IR2 & !IR1 & IR0;
XorIT = IR2 & !IR1 & !IR0;

% ALU Operation %
Sum[] = Cda & (0,B[]) #
Add & ((0,B[]) + (0,Ac[])) #
AndIt & ((0,B[]) & (0,Ac[])) #
OrIt & ((0,B[]) # (0,Ac[])) #
XorIt & ((0,B[]) $ (0,Ac[])) #
ShR & (0,Ac7, Ac[7..1]);

% Acumulator Operations %
Act[].in = Ac[];
Ac[] = LdA & Sum[7..0] # !LdA & Ac[];

C.d = Ex & Add & Sum8 # !Ex & C;


N = Ac7;
Z = Ac[] == 0;

% Bus Operaions %
BusOut[] = B[];
B[] = Act[].out;
B[] = Pct[].out;
B[] = Bus[];
Bus[] = B[];

Andrew Stevens

% IR operations %
IR[] = LdIR & B[] # !LdIR & IR[];

% PC operations %
Pct[].in = PC[];
Pct[].oe = OePC;
PC[] = !Reset & LdPC & B[] # !Reset & IncPC & (PC[] + 1) # !Reset & !LdPC & !IncPC & PC[];
End;

10

You might also like