CS233 Lab 6 Handout
Learning Objectives
1. Understanding the implementation of branches, loads, and stores in a processor datapath.
2. Building a full machine capable of running MIPS programs containing a variety of instructions.
Work that needs to be handed in (via SVN)
By the first deadline
1. decoder.v: This file contains the module mips_decode, which takes an instruction’s opcode
and funct fields and produces all of the control signals needed by the data path. You
should use combinational design to do the implementation, much like you did for the steering
circuit. Your decoder needs to support all the instructions from Lab 5, plus the following
instructions:
bne, beq, j, jr, lui, slt, lw, lbu, sw, sb, addm
We won’t autograde your decoder output for addm, since different implementations of it can
set the control signals differently.
2. decoder_tb.v: A test bench for your decoder. As before, we can’t autograde this, but we
can use it to determine partial credit.
By the second deadline
1. full_machine.v: This file contains the module full_machine, which implements the data
path for all instructions from Lab 5, plus the following instructions:
bne, beq, j, jr, lui, slt, lw, lbu, sw, sb, addm
See the final page for details about addm.
Like Lab 5, we’ve provided all of the major components, so there will be little logic outside of
wiring up these provided components and your MIPS decoder. There is significant overlap
between this assignment and Lab 5, so you should reuse portions of you Lab 5 Verilog in this
Lab.
2. fm.s: Additional tests for your full machine; the next section has the details. Not autograded
(see decoder_tb.v).
The files that we provide for Lab 6 include many of those we provided from Lab 5, with the following
notable additions/extension. None of these need to be checked in.
• rom.v: has a data memory in addition to the instruction memory from Lab 5.
• all.s and lwbr.s: two example MIPS assembly programs for testing your code
• all.text.dat and lwbr.text.dat: the machine language that corresponds to the two pro-
vided assembly programs.
• all.data.dat and lwbr.data.dat: the data memory images that correspond to the two
provided assembly programs.
Compiling, Running and Testing
We’ve provided a Makefile you can use for compiling and running your code. The main rules of
interest are make decoder and make full_machine, and their names should be self-explanatory.
1
CS233 Lab 6 Handout
Before you can run the full machine, however, you need to set up a test case to use. We’ve provided
two test cases in lwbr.s and all.s, which you can use by running make lwbr_test and make
all_test, respectively. The assembly files contain comments specifying their expected behavior,
which you can use to verify your implementation’s correctness. lwbr.s is simpler, so we recommend
getting that working first and then progressing to all.s.
Our provided tests aren’t comprehensive, and in particular, they don’t test most of the instructions
carried over from last week, so it’s a good idea to write your own. To do so, add your test cases to
fm.s and then run make fm_test to assemble this file. The program needed for this compilation
is already present on EWS machines. You can download it to your own machine by following the
instructions on the wiki to download spim-vasm:
https://wiki.cites.illinois.edu/wiki/display/cs233sp17/CS+233+on+Your+Own+Machine
The full machine test bench will stop after 30 instructions by default. If you need to run more
instructions, you should edit it accordingly.
Optional details, for those interested
Our simulated memories (instruction and data) get their initial values from loading files. Specifically,
the instruction memory loads a file called memory.text.dat and the data memory gets its value
from loading memory.data.dat.
Since we’ve provided two test cases, and neither of them are named memory.text.dat and
memory.data.dat, you’ll need copy or symbolic link one of the set of files. Specifically, we’d
recommend that you use symbolic links. Symbolic links provide an alternate name for a given file.
For example:
ln -s lwbr.text.dat memory.text.dat
ln -s lwbr.data.dat memory.data.dat
By typing ls -l memory*, we can see that now the memory.* files refer to their lwbr counterparts.
machine:Lab6 zilles$ ls -l memory*
lrwxr-xr-x 1 zilles staff 14 Sep 29 13:00 memory.data.dat -> lwbr.data.dat
lrwxr-xr-x 1 zilles staff 14 Sep 29 13:00 memory.text.dat -> lwbr.text.dat
We can switch to the all.* equivalents by removing the memory.* files and making new symbolic
links.
rm memory.text.dat memory.data.dat
2
https://wiki.cites.illinois.edu/wiki/display/cs233sp17/CS+233+on+Your+Own+Machine
CS233 Lab 6 Handout
ln -s all.text.dat memory.text.dat
ln -s all.data.dat memory.data.dat
3
CS233 Lab 6 Handout
Decoder
alu_op[2:0]
write_enable
rd_src
except
opcode[5:0]
funct[5:0]
MIPS decoder
zero (from ALU)
wr_enable
rd_src
alu_op[2:0]
inst[5:0]
inst[31:26]
except
6
6
3
control_type control_type
zero
lui lui
slt slt
byte_load byte_load
word_we word_we
byte_we byte_we
mem_read mem_read
alu_src2 alu_src2
The exception signal should be 1 when the opcode/func field pair is not recognized.
inst alu_op rd_src wr_ena alu_src2 ctrl_type mem_rd word_we byte_we byte_ld lui slt
beq
bne
j
jr
lui
slt
lw
lbu
sw
sb
// mips_decode: a decoder for MIPS arithmetic instructions
//
// alu_op (output) – control signal to be sent to the ALU
// writeenable (output) – should a new value be captured by the register file
// rd_src (output) – should the destination register be rd (0) or rt (1)
// alu_src2 (output) – should the 2nd ALU source be a register (0) or an immediate (1)
// except (output) – set to 1 when the opcode/func filed pair is unrecognized
// control_type[1:0] (output) – 00 = fallthrough, 01 = branch_target (taken),
// 10 = jump_target, 11 = jump_register
// mem_read (output) – the register value written is coming from the memory
// word_we (output) – we’re writing a word’s worth of data
// byte_we (output) – we’re only writing a byte’s worth of data
// byte_load (output) – we’re doing a byte load
// lui (output) – the instruction is a lui
// slt (output) – the instruction is an slt
// opcode (input) – the opcode field from the instruction
// funct (input) – the function field from the instruction
// zero (input) – from the ALU
4
CS233 Lab 6 Handout
2
(A
dd
)
32
al
u_
op
[2
:0
]
w
rit
e_
en
ab
le
rd
_s
rc
ex
ce
pt
op
co
de
[5
:0
]
fu
nc
t[5
:0
]
M
IP
S
d
ec
od
er
A
[3
1:
0]
al
u_
op
[2
:0
]
ou
t
[3
1:
0]
B
[3
1:
0]
A
LU
rs
D
at
a
rs
N
um
re
se
t
rd
N
um
rtD
at
a
rtN
um
rd
W
rit
eE
na
bl
e
rd
D
at
a
R
eg
is
te
r
Fi
le
re
se
t
cl
k
w
r_
en
ab
le
R
de
stR
t
R
s
ze
ro
ne
ga
tiv
e
ov
er
flo
w
0 1
w
r_
en
ab
le
rd
_s
rc
al
u_
sr
c2
al
u_
op
[2
:0
]
re
se
t
en
ab
leQ
[3
1:
0]
D
[3
1:
0]
P
C
R
eg
is
te
r
S
ig
n
E
xt
en
de
r
ou
t[3
1:
0]
in
[1
5:
0]
da
ta
[3
1:
0]
ad
dr
[2
9:
0]
In
st
ru
ct
io
n
M
em
or
y
4
in
st
[3
1:
0]
P
C
[3
1:
0]
A
LU
1
ne
xt
P
C
[3
1:
0]
0 1 rd
_s
rc
in
st
[2
5:
21
]
in
st
[2
0:
16
]
in
st
[1
5:
11
]
in
st
[2
0:
16
]
in
st
[5
:0
]
in
st
[1
5:
0]
in
st
[3
1:
26
]
ex
ce
pt
PC[31:2]
R
t
R
d
im
m
16
im
m
32
32
30
32
3
5 5 5
16
32
6 6
32
32
32
32
32
3
3
ou
t[1
:0
] 0
1
2
3
co
nt
ro
l_
ty
pe
0
1
2
3
2
(A
dd
)
A
LU
3
S
hi
ft
L
ef
t 2
ou
t[3
1:
0]
in
[2
9:
0]
30
32
in
st
[2
5:
0]
00
(f
or
L
S
B
s)
P
C
[3
1:
28
] (
fo
r M
S
B
s)
br
an
ch
of
fs
et
br
an
ch
of
fs
et
32
co
nt
ro
l_
ty
pe
co
nt
ro
l_
ty
pe
0
1
sl
t
0
1
lu
i
16
16
‘b
0
da
ta
_o
ut
[3
1:
0]
ad
dr
[3
1:
0]
D
at
a
M
em
or
y
31’b0
ze
ro
0 1
m
em
_r
ea
d
data_out[31:24]
data_out[23:16]
data_out[15:8]
data_out[7:0]
24
‘b
0
0 1
by
te
_l
oa
d
8
lu
i
lu
i
sl
t
sl
t
by
te
_l
oa
d
by
te
_l
oa
d
32
26
w
or
d_
w
e
w
or
d_
w
e
by
te
_w
e
by
te
_w
e
w
or
d_
w
e
by
te
_w
e
da
ta
_i
n[
31
:0
]
w
or
d_
w
e
by
te
_w
e
re
se
t
32
32
m
em
_r
ea
d
m
em
_r
ea
d
al
u_
sr
c2
al
u_
sr
c2
5
CS233 Lab 6 Handout
Datapath modification for ISA extension
Modify the datapath and decoder to extend the current MIPS ISA with the new addm instruction
that we introduced in the discussion section. In mips_defines.v, we have defined the function
code for the addm instruction as 6’h2c. You will need to recognize this instruction in your decoder
and add the new parts of the datapath in full_machine.v.
The semantics of the new addm instruction have been defined in the Discussion Section as R[rd] =
Memory[R[rs] + 0] + R[rt]. For this extension you can use the design that your group constructed
during the discussion section, or use a new design using the datapath below.
2 (Add)
32
alu_op[2:0]
write_enable
rd_src
except
opcode[5:0]
funct[5:0]
MIPS decoder
A[31:0]
alu_op[2:0]
out
[31:0]
B[31:0]
ALU
rsDatarsNum
reset
rdNum
rtDatartNum
rdWriteEnable
rdData
Register File
reset
clk
wr_enable
Rdest
Rt
Rs
zero
negative
overflow
0
1
wr_enable
rd_src
alu_src2
alu_op[2:0]
reset
enable
Q[31:0]
D[31:0]
PC Register
Sign
Extender
out[31:0]
in[15:0]
data[31:0]
addr[29:0]
Instruction
Memory
4
inst[31:0]
PC[31:0]
ALU
1
nextPC[31:0]
0
1
rd_src
inst[25:21]
inst[20:16]
inst[15:11]
inst[20:16]
inst[5:0]
inst[15:0]
inst[31:26]
except
P
C
[3
1:
2]
Rt
Rd
imm16
imm32
32
30
32
3
5
5
5
16
32
6
6
32
32
32
32
32
3
3
out[1:0]
0123
control_type
0 1 2 3
2 (Add)
ALU
3
Shift Left 2
out[31:0]
in[29:0]
30
32
inst[25:0]
00 (for LSBs)
PC[31:28] (for MSBs)
branch
offset
branch
offset
32
control_type control_type
0 1
slt
01lui
16
16’b0
data_out[31:0]
addr[31:0]
Data
Memory
31’b0
zero
0
1
mem_read
da
ta
_o
ut
[3
1:
24
]
da
ta
_o
ut
[2
3:
16
]
da
ta
_o
ut
[1
5:
8]
da
ta
_o
ut
[7
:0
]
24’b00
1
byte_load
8
lui lui
slt slt
byte_load byte_load
32
26
word_we word_we
byte_we byte_we
word_we
byte_we
data_in[31:0]
word_we
byte_we
reset
32
32
mem_read mem_read
alu_src2 alu_src2
Fixing slt
Our slt implementation, as discussed in lecture, won’t always give correct results. Figure out why
and put a corrected implementation in your full_machine.v to get 5 points of extra credit.
6