Please get started on the lab as soon as possible. In general, in this class you will have about 3 weeks from the lab release date until the due date.
You will submit your work by pushing it to your repository on LoboGit. Details about how to access your repository are found on the course webpage.
First, install some tools: Xilinx ISE WebPack and ModelSim SE. The total space required will be about 30 GB (total download size is about 8 GB). You have two options here.
Option 1 - Install on Your Personal Windows Machine
I do not recommend this option, and I cannot provide you with much help if you try this option and it doesn't work.
Here's where to get the tools for Windows:
- ModelSim Starter Edition (SE): product page, install file.
- Xilinx ISE WebPack: product page, install file, instructions for installation on Windows.
Option 2 - Install on Your Personal Linux Machine (or Linux VM)
You cannot install this software on the lab machines, since you don't have sudo
permissions there.
NOTE: these install instructions were tested on Ubuntu 16.04 and 18.04.
The following outlines how to install ModelSim on Linux.
wget http://download.altera.com/akdlm/software/acdsinst/13.1/162/ib_installers/ModelSimSetup-13.1.0.162.run
chmod +x ModelSimSetup-13.1.0.162.run
sudo apt-get install build-essential gcc-multilib g++-multilib lib32z1 lib32stdc++6 lib32gcc1 expat:i386 fontconfig:i386 libfreetype6:i386 libexpat1:i386 libc6:i386 libgtk-3-0:i386 libcanberra0:i386 libice6:i386 libsm6:i386 libncurses5:i386 zlib1g:i386 libx11-6:i386 libxau6:i386 libxdmcp6:i386 libxext6:i386 libxft2:i386 libxrender1:i386 libxt6:i386 libxtst6:i386
# sudo apt-get install libpng12-0:i386
# sudo apt-get install libpng16-16:i386
sudo ./ModelSimSetup-13.1.0.162.run
After you have installed ModelSim in /opt/altera/13.1
, you then need
to do the following:
wget http://download.savannah.gnu.org/releases/freetype/freetype-2.4.12.tar.bz2
tar -xvf freetype-2.4.12.tar.bz2
cd freetype-2.4.12
./configure --build=i686-pc-linux-gnu "CFLAGS=-m32" "CXXFLAGS=-m32" "LDFLAGS=-m32"
make -j8
sudo mkdir /opt/altera/13.1/modelsim_ase/lib32
sudo cp objs/.libs/libfreetype.so* /opt/altera/13.1/modelsim_ase/lib32
cd /opt/altera/13.1/modelsim_ase/
sudo pico bin/vsim
This should open the ModelSim startup script. You need to go to the line that looks like
dir=`dirname $arg0`
and insert the following on the next line:
export LD_LIBRARY_PATH=${dir}/lib32
Additionally, search for the word linux_rh60
in the file, and change it to
linuxaloem
.
Now, if you exit the editor, and type bin/vsim
, you should see ModelSim start up.
Next, add the following at the end of your ~/.bashrc
file:
export PATH=$PATH:/opt/altera/13.1/modelsim_ase/bin
alias xilinx="source /opt/Xilinx/14.7/ISE_DS/settings64.sh"
export MODELSIM="/opt/altera/13.1/modelsim_ase/modelsim.ini"
export WD_MGC="/opt/altera/13.1/modelsim_ase/"
export MODEL_TECH="/opt/altera/13.1/modelsim_ase/linuxaloem"
and type source ~/.bashrc
to apply your changes.
Finally, install Xilinx ISE Webpack.
- Download the Full Installer for Linux.
- You will be asked to first create a Xilinx account. You'll need to use your UNM email address.
- The download is about 7 GB, so will take quite a while to download (it took about 45 minutes for me).
- Once the download is finished, do the following:
tar -xvf Xilinx_ISE_DS_Lin_14.7_1015_1.tar
cd Xilinx_ISE_DS_Lin_14.7_1015_1
sudo ./xsetup
- The graphical installer should let you install Xilinx ISE Webpack in
/opt/Xilinx
. - After the install is complete, you should go to the Xilinx license site and download a Xilinx ISE Webpack license.
- You should be able to start Xilinx by typing
xilinx
ise
Xilinx will ask for a license, and you should click "manage licenses", and then "load license"
and select your downloaded license file (Xilinx.lic
).
In the first lab, we learned about how the MIPS instruction set works by implementing a basic MIPS CPU in software. In the second lab, we learned how to implement a single-cycle MIPS CPU in hardware. In this lab, we will think a bit more about the hardware CPU implementation.
In the second lab, we added support for the following 12 MIPS instructions:
add
, addi
, sub
, and
, or
, nor
, lw
, sw
, slt
, beq
, j
, nop
.
Reminder: the course textbook provides a very useful MIPS Cheat Sheet. You can also check out the other MIPS Assembly Reference which shows the syntax of the MIPS assembly language instructions (the order of the arguments can sometimes be a bit confusing). We will again utilize these references throughout this lab.
Recall the following basic MIPS assembly code:
# this program computes $t1 * $t2 and places the result in $t0
.globl c_entry
c_entry: nop
# initialize registers
addi $t1, $zero, 5
addi $t2, $zero, 4
addi $t0, $zero, 0
loop: beq $t2, $zero, done
add $t0, $t0, $t1
addi $t2, $t2, -1
j loop
.globl done
done: nop
We saw that this code can be assembled into the following machine code:
address | block offset | machine instruction | assembly code | explanation |
---|---|---|---|---|
0x00000000 | c_entry+0 | 00 00 00 00 |
nop |
no-operation (left-shift by zero places) |
0x00000004 | c_entry+4 | 20 09 00 05 |
addi $t1, $zero, 5 |
add immediate |
0x00000008 | c_entry+8 | 20 0a 00 04 |
addi $t2, $zero, 4 |
add immediate |
0x0000000c | c_entry+12 | 20 08 00 00 |
addi $t0, $zero, 0 |
add immediate |
0x00000010 | loop+0 | 11 40 00 03 |
beq $t2, $zero, 0x00000020 <done> |
branch to done (3 words from next PC) |
0x00000014 | loop+4 | 01 09 40 20 |
add $t0, $t0, $t1 |
add |
0x00000018 | loop+8 | 21 4a ff ff |
addi $t2, $t2, -1 |
add immediate |
0x0000001c | loop+12 | 08 00 00 04 |
j 0x00000010 <loop> |
jump to loop (byte address 0x10 is word address 0x04 ) |
0x00000020 | done+0 | 00 00 00 00 |
nop |
no-operation (left-shift by zero places) |
In particular, the "machine instruction" column contains a list of 32-bit words that represents the MIPS program.
In Lab 2, we built hardware which can execute such a list of instructions. An instructor-provided VHDL implementation is provided for this lab. You can either use your Lab 2 implementation, or the instructor-provided implementation for this lab.
- Click on "New Project", name your project
lab2
, select a location where your project should be stored, and selectHDL
as the top-level source type, and click "Next". - Change "Preferred Language" to
VHDL
, and change "Simulator" toModelsim-SE VHDL
, and click "Next", and then "Finish". - Click on the "New Source" icon on the left, select "VHDL Module", and type
full_adder
as the filename. - Create the following ports:
a
(in),b
(in),carry_in
(in),sum
(out),carry_out
(out), and click "Next"/"Finish". - This should add a file
full_adder.vhd
(VHDL module) to your project, that looks like this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity full_adder is
Port ( a : in STD_LOGIC;
b : in STD_LOGIC;
carry_in : in STD_LOGIC;
sum : out STD_LOGIC;
carry_out : out STD_LOGIC );
end full_adder;
architecture Behavioral of full_adder is
begin
-- PUT YOUR VHDL CODE HERE
end Behavioral;
To build a test bench for your VHDL module using ModelSim, click on the "Simulator" checkbox at the top, and then do the following:
-
Select
full_adder
in the list. -
In the "Processes" list, open the "ModelSim Simulator" item, right-click on "Simulate Behavioral Model", select "Ignore Pre-Compiled Library Warning Check", and press "Ok".
-
Double-click on "Simulate Behavioral Model".
-
In the "Wave" section, select signals
a
,b
,carry_in
, right-click, and select "Edit" and then "Delete". -
In the "Objects" section, select signal
carry_in
, right-click, select "Modify" and then "Apply Wave", and change the period to 200 ps. -
This should create a new signal
carry_in
in the "Wave" section, with the corresponding waveform. -
Repeat the above two steps for signal
a
, except set the period to 100 ps. -
Do the same for
b
, except set the period to 50 ps. -
Select your input signals in the "Wave" section, and click on "File", then "Export", then "Waveform".
-
Select "VHDL Testbench", click "Browse", and name your file
full_adder_tb.vhd
. -
In Xilinx ISE, click the "Add Source" button, select your testbench
full_adder_tb.vhd
, and press "Ok". -
Double-click on
full_adder_tb.vhd
in the "Design" section. -
Make the following substitutions in the VHDL file (and then save):
-
\full_adder_tb.vhd\
-->full_adder_tb
-
\full_adder_tb.vhd_arch\
-->full_adder_tb_arch
-
Now that you have a VHDL test bench, you can run it using ModelSim:
- In the "Design" section, change to the "Simulation" view, select
full_adder_tb
, and double-click "Simulate Behavioral Model". - In ModelSim, press the "Restart" button, and then the "Run All" button.
- Click in the "Wave" section, and press the "Zoom Full" button.
- You should see your waveforms for the adder inputs, and a red line (undefined value) for the outputs. This is because you haven't yet connected the outputs to anyting. Try modifying your
full_adder.vhd
in the following simple way:
-- PUT YOUR VHDL CODE HERE
sum <= a and b;
carry_out <= a or b or carry_in;
-- NOTE - this is not the correct definition of the outputs for a full adder - we're just using it for a test.
- Save and repeat the process of running the testbench in ModelSim.
We will use a fairly basic subset of VHDL in this class. We will use only structural (not behavioral) VHDL to model digital logic.
The CD that accompanies the textbook contains a VHDL Tutorial that you may find useful. There is a VHDL Primer that also may be useful. To refresh your memory on digital logic, please see Appendix C from the textbook CD.
It is relatively easy to produce a logical function from a truth table, but it can be tricky to produce a minimal function. Fortunately, the Espresso tool makes this easy. You can download the Espresso logic minimization tool, and it should work on Linux or Windows. There is a nice Espresso tutorial which shows an example. The following is a simplified version, using the truth table for a half adder.
Once you have downloaded the Espresso program, and added its location to your system path, type the following command:
espresso -o eqntott
Espresso will wait for input. Paste the following and press Enter:
.i 2 # number of inputs
.o 2 # number of outputs
.ilb A B # names of inputs
.ob C SUM # names of outputs
00 00 # input bits, followed by space, followed by output bits
01 01 # (use a dash "-" character for "don't care")
10 01 # THIS IS THE TRUTH TABLE FOR A HALF ADDER
11 10
.e # end of file
Espresso will produce the following output:
C = (A&B);
SUM = (A&!B) | (!A&B);
Note that this shows that the carry out for a full adder is simply the logical and of the input bits, and the sum is the logical xor of the input bits.
Remember that we ignored the bne
(branch on not-equals) instruction in lab 2.
For this part of the lab, you should modify your Lab 2 VHDL code to add support for the bne
instruction.
Modify the VHDL code for your single-cycle MIPS CPU to add support for the mult
, mfhi
, mflo
instructions.
You should use the multiplier hardware we discussed in class (using a single 64-bit register to store the intermediate results).
Note that the multiplication can take up to 32 clock cycles, so you will need to modify the Control hardware to allow the processor to stall while the the multiplication is being performed.
Modify the VHDL code for the main memory of your single-cycle CPU to contain a basic direct-mapped cache. For simplicity, the cache should have between 8 and 32 entries.
Clearly document (using source-code comments) all of your work. Also fill in the README.md file (preferably using Markdown syntax) with a brief writeup about the design choices you made in your code.
Make sure that you have named your source code files exactly as requested in the lab assignment! (If for some reason you need to use a different naming convention, make sure to carefully explain the mapping between your source code files and the requirements in the lab assignment).
Providing adequate documentation helps us see that you understand the code you've written.
Modify your VHDL code to follow a basic pipelined architecture, using the 5 pipeline stages discussed in class. You can assume that the code to be executed within the CPU will have no hazards, i.e., you do not need to implement functionality to do forwarding or stalling.
We will automatically grab a snapshot of the master branch of your lab repository at the deadline. Make a new directory in your repository for this lab.
Make sure you push all of your work before the deadline!