1 Lab 5 Embedded MIPS Core Programming Jacobi Zakrzewski Andrew Healy 11/22/2009 Grading Points Item Points Possible Title page, Table of Contents, Introduction 5 Software Design and Documentation (see attached) 10 Demonstrations 30 Conclusions 5 Appendices: VHDL code, MIPS Assembly code. 10 Effort and Quality 5 Total 65 2 Table of Contents 1—Title Page 2—Index 3—Introduction, Design Description 4—Design Description, VHDL Code 5—Conclusion, Appendices 6—Appendices 3 Introduction The purpose of lab 5 was to program a small microprocessor into VHDL. With that goal in mind, we had to use our Spartan 3E board, Xilinx Project Navigator, and code taken off of eLearn. In order for our project to work correctly we had to add to and modify the code already given to us. The first part of the lab was to implement the design already given to us, after that we were to modify the code in order to complete the objective of reading in a value, entering it, read in another value, enter that, and add the two previous numbers. The sum should display on the 8 LEDS. Design Description Our design started off with all the files taken off of eLearn, all of this had included constraints and coding that dealt with the counter on the seven-segment display and the rotary switch. We had to add a few things to this in order for our lab to be completed though. First we started a new project in Xilinx Project Manager, integrated all the files given to us on eLearn. The program didn’t work out of the box and we had to create a file called RegisterFile.vhdl, take more code off of eLearn, and implement that into the new file. Finally, we synthesized, implement design, and generated a programming file. We hooked up the Spartan 3E board and used iMPACT in order for the hardware to talk to each other. After that was all said and done, we tested the board and our rotary switch displayed hexadecimal digits on the seven-segment display. Now we just had to begin part two. Part two we were to read two inputs from two different locations on the board, add them, and store the result. Simply put, we were to use the rotary switch to enter in the two numbers, press it down each time you enter a number, and then display the result on the 8 LEDS. To start this process we took an example from the file ‘ifetch.vhld’ and modified it to adhere to our objective. We then wrote the program in MIPster, including memory locations for two numbers, an addition, and a result. We had to use specific locations for the two numbers entered (0XC004 and 0XC000) because that is where the 4 binary and push buttons are stored. We then ran it through PCSpim, and copied down the instructions to put into our VHDL program. After that we recompiled our VHDL project and implemented it onto our Spartan 3E board. We ran our program and were able to add two hexadecimal numbers from our rotary switch, add them and have it display on the 8 LEDS. VHDL Code: ########################################################################## ########################### #Programmer(s) name(s): Jacobi Zakrzewski, Andrew Healy #Date last modified: 11/20/2009 #File Name: Lab_05_JZ_Ah.s #Description of contents: This program will store, and add two #different locations from the board, and then store the result #back into a location. #Then it loops back infinitely ########################################################################## ############################ .data # Data declaration section .text ############################################################# # Main: Read two integers from two locations on the board, #add them and store them back in the first location # Inputs: 0XC004: rotary switch used to input number # 0XC000: Binary counter used to input number # Outputs: 0XC000: Result from adding the 2 numbers is stored here ############################################################# main: # Start of li $t1, 0xC004 li $t2, 0xC000 lw $t1, 0($a0) lw $t2, 0($a1) add $t1, $t1, $t2 sw $t1, 0xC000 (0Xc000) beq $zero, $zero, main # END OF PROGRAM code section #load number into t1 from 0XC004 #load second number into t2 from 0XC000 #load number into t1 from a0 #load number into t2 from a1 #add t1 and t1, store back in t1 #store result in t1, as well as address on board #branch, loop infinitely 5 Conclusion From this, we learned how to convert assembly language to something VHDL will recognize. To do this we started a new project in Xilinx, implemented many files from eLearn, analyzed the code given to us, and modified that code in order to complete our objective. We had to convert from assembly to something VHDL would recognize by writing a program in MIPster, and taking those instructions over to VHDL. This process was quick, but took a lot of integrating and transferring of code/files in order for it to work. Appendices Assembly used to add two inputted numbers, stored ########################################################################## ########################### #Programmer(s) name(s): Jacobi Zakrzewski, Andrew Healy #Date last modified: 11/20/2009 #File Name: Lab_05_JZ_Ah.s #Description of contents: This program will store, and add two #different locations from the board, and then store the result #back into a location. #Then it loops back infinitely ########################################################################## ############################ .data # Data declaration section .text ############################################################# # Main: Read two integers from two locations on the board, #add them and store them back in the first location # Inputs: 0XC004: rotary switch used to input number # 0XC000: Binary counter used to input number # Outputs: 0XC000: Result from adding the 2 numbers is stored here ############################################################# main: # Start of li $t1, 0xC004 li $t2, 0xC000 lw $t1, 0($a0) lw $t2, 0($a1) add $t1, $t1, $t2 sw $t1, 0xC000 (0Xc000) beq $zero, $zero, main # END OF PROGRAM code section #load number into t1 from 0XC004 #load second number into t2 from 0XC000 #load number into t1 from a0 #load number into t2 from a1 #add t1 and t1, store back in t1 #store result in t1, as well as address on board #branch, loop infinitely 6 Modified ifetch.vhdl X"3404c004", X"3405c000", X"8c890000", X"8caa0000", X"012a4820", X"ac09c000", X"1000fffb", -------- ori $4, $0, -16380 ; 2: li $t1, 0xC004 ori $5, $0, -16384 ; 3: li $t2, 0xC000 lw $9, 0($4) ; 4: lw $t1, 0($a0) lw $10, 0($5) ; 5: lw $t2, 0($a1) add $9, $9, $10 ; 6: add $t1, $t1, $t2 sw $9, -16384($0) ; 6: sw $t1, 0xC000 beq $0, $0, -20 [main-0x00400038]; 7: beq $zero, $zero, main RegisterFile.vhdl library IEEE; use IEEE.STD_LOGIC_1164.all; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; USE IEEE.numeric_std.ALL; entity RegisterFile is -- three-port register file generic(datapath_size : integer); port(clk: in STD_LOGIC; we3: in STD_LOGIC; ra1, ra2, wa3: in STD_LOGIC_VECTOR(4 downto 0); wd3: in STD_LOGIC_VECTOR(datapath_size - 1 downto 0); rd1, rd2: out STD_LOGIC_VECTOR(datapath_size - 1 downto 0)); end RegisterFile; architecture Behavioral of RegisterFile is type ramtype is array (31 downto 0) of STD_LOGIC_VECTOR(datapath_size - 1 downto 0); signal mem: ramtype; begin -- three-ported register file -- read two ports combinationally -- write third port on rising edge of clock process(clk) begin if (clk'event and clk = '1') then if we3 = '1' then mem(CONV_INTEGER(wa3)) <= wd3; end if; end if; end process; rd1 <= conv_std_logic_vector(0,datapath_size) when (conv_integer(ra1) = 0) -- register 0 holds 0 else mem(CONV_INTEGER(ra1)); rd2 <= conv_std_logic_vector(0,datapath_size) when (conv_integer(ra2) = 0) -- register 0 holds 0 else mem(CONV_INTEGER(ra2)); end;