Computer Architecture Lab Instructor: Engr. Sumair Aziz Department of Electronics Engineering University of Engineering and Technology, Taxila 1 TABLE OF CONTENTS Sr. No. Experiment Title Page No. 1 Getting Started with SPIM – MIPS Simulator 03 2 Data Transfer and Arithmetic Operations in MIPS 11 3 Logical and Shift Operations in MIPS 20 4 Control Structures in MIPS 25 5 Procedures in MIPS 31 6 Array and pointers in MIPS 38 7 Architecture Design and Implementation of 32-Bit Adder using Verilog 48 8 Design and Simulation of 32-Bit Subtractor 52 9 Design of Overflow Detection Mechanism in 32-bit Adders 56 10 Design of 32-Bit Serial Multiplier 60 11 Design of Algorithmic and Logic Unit (ALU) 63 12 Design of Enhanced Algorithmic Logic Unit 67 13 Course Project Week – I 14 Course Project Week – II 2 EXPERIMENT NO. 1 Getting Started with SPIM – MIPS Simulator Objectives After this lab exercise you will be able to: • Load MIPS programs (assembly language) and execute them • Examine memory locations • Examine registers • Execute programs step by step • Set/remove breakpoints Introduction SPIM S20 is a simulator that can run programs for the MIPS R2000 and R3000 architectures. The simulator may load and execute assembly language programs. The process through which a source file (assembly language) is translated to an executable file contains two stages: • assembling (implemented by the assembler) • linking (implemented by the linker) An executable file must be loaded before the CPU can actually run that program. This is done by a loader. Figure 1.1 shows the relation between the processes involved in translation and loading and various types of files they manipulate. The assembler performs the translation of an assembly language module into machine code. Note that a pro- gram may have several modules, each of them a part of the program. This is usually the case when you bulid an application from several files. The output of the assembler is an object module for each source module. Object modules contain machine code. The translation of a module is not complete if the module uses a symbol (a label) that is defined in a different module or is part of a library. 3 The linker enters now the picture. It’s main goal is to resolve external references. In other words the linker will match a symbol used in a source module with it’s definition found in a different module or in a library. The output of the linker is an executable file. The loader may be as simple as a program that copies the executable in the memory at the appropriate loca- tion(s), or it may be more involved if loading occurs at different locations at different times. This second case is called relocation and it involves the translation of some addresses as to correspond with the actual loading address. Source modules Object modules Linker Executable file Loader Figure 1.1 The translation process File Names File suffixes indicate the type of the file. Files that contain assembly code have the suffix “.s’ or “.asm”. Compilers use the first convention. Files with object programs have the suffix “.o” and executables don’t usually have any suffix. 4 Translation in SPIM The process of translation in SPIM is transparent to the user. This means that you don’t have to deal with an assembler, a linker and a loader as separate programs. Provided you have written a correct assembly language program, the only thing you have to do is to start the simulator and then indicate what program you want to execute. The whole process of translation is hidden. Program 1: Load some registers # Lab 1 Program 1 .data .text # load some registers li $t0, 0x0 li $t1, 0x1 li $t2, 0x2 li $t3, 0x3 li $t4, 0x4 li $t5, 0x5 li $t6, 0x6 li $t7, 0x7 li $t8, 0x8 li $t9, 0x9 #Load Immediate #Load Immediate #Load Immediate #Load Immediate #Load Immediate #Load Immediate #Load Immediate #Load Immediate #Load Immediate #Load Immediate #Exit the program li $v0, 10 syscall Program 2: Load and perform addition # Lab 1 : program 2 # Filename: add # Addition of registers # Data Section .data #Text Section .text 5 .globl my_main my_main: # Main Codes goes here li $t1, 0x1111 li $t2, 0x2222 add $t3, $t1, $t2 # Exit the program li $v0, 10 syscall Lab Procedure: Step 1: Open the QtSpim simulator from program files. Reinitialize Simulator. Simulator > Reinitialize Simulator 6 Step 2: Load the .s or .asm code file into SMIP simulator File > Load Files Step 3: Now analyze the code in the Text tab. Run the assembly code from the button visible in toolbar Or use this option from menu : Simulator > Run/Continue 7 Step 4: Examine the contents of registers visible in the left window 8 LAB TASK Task 1: Type and run the program 1 in SPIM simulator Examine the contents of registers $t0, $t2…… $t9; Fill the table below with registers values before and after running the simulation Register number Register name 1 $at 2 $v0 3 $v1 4 $a0 5 $a1 6 $a2 7 $a3 8 $t0 9 $t1 10 $t2 11 $t3 12 $t4 13 $t5 14 $t6 15 $t7 Before the program run After the program run Table 1: Register Values for program 1 9 Task 2: Modify the program 2 such that register $t1 is equal to 0x05 + $t0. Load $t0 with 0x02. Type and run the program with modifications in SPIM simulator Examine the contents of registers; Fill the table below with registers values before and after running the simulation Register number Register name 1 $at 2 $v0 3 $v1 4 $a0 5 $a1 6 $a2 7 $a3 8 $t0 9 $t1 10 $t2 11 $t3 Before the program run After the program run Table 2: Registers Values for program 2 with modifications 10 EXPERIMENT NO. 2 Data Transfer and Arithmetic Operations in MIPS Objectives After this performing this lab you will be able to understand and implement following MIPS instructions • Load word from memory • Store word on memory • Add instruction • Subtract instruction • Add immediate (addi) instruction • Addition of negative numbers Instruction Set Architecture The operands of arithmetic instructions are restricted; they must be from a limited number of special locations built directly in hardware called registers. Registers are primitives used in hardware design that are also visible to the programmer when the computer is completed, so you can think of registers as the bricks of computer construction. The size of a register in the MIPS architecture is 32 bits; groups of 32 bits occur so frequently that they are given the name word in the MIPS architecture MIPS assembly language Arithmetic Instructions 11 Although we could simply write instructions using numbers for registers, from 0 to 31, the MIPS convention is to use two-character names following a dollar sign to represent a register. For now, we will use $s0, $s1, . . . for registers that correspond to variables in C and Java programs and $t0, $t1, . . . for temporary registers needed to compile the program into MIPS instructions. Data Transfer Instructions Arithmetic operations occur only on registers in MIPS instructions; thus, MIPS must include instructions that transfer data between memory and registers. Such instructions are called data transfer instructions. To access a word in memory, the instruction must supply the memory address. Memory is just a large, single-dimensional array, with the address acting as the index to that array, starting at 0. For example, in Figure 2.2, the address of the third data element is 2, and the value of Memory [2] is 10. Figure. Memory Address and contents of memory at those locations MIPS Architecture: Arithmetic and Data Transfer Instructions 12 The instruction complementary to load is traditionally called store; it copies data from a register to memory. Th e format of a store is similar to that of a load: the name of the operation, followed by the register to be stored, then off set to select the array element, and finally the base register. Once again, the MIPS address is specified in part by a constant and in part by the contents of a register. The actual MIPS name is sw, standing for store word. Category Instruction Example Meaning Load word lw $s1, 20($s2) $s1=Memory[$s2+20] Store word sw $s1, 20($s2) Memory[$s2+20]=$s1 Data Transfer Comments Word from memory to register Word from register to memory Lab Procedure: Type the codes given below in notepad or notepad++ and save as (.s) or (.asm) file. Load them into SPIM simulator as done in previous lab and perform step by step program execution. Code used for Addition and Subtraction Assembly Codes: Program 1: Load data into SPIM Simulator #data MIPS # The Data Segment .data a1: .ascii a2: .ascii a3: .ascii name: .ascii course: . ascii "123" "5" "4" "Ali" "Computer Architecture" # The Text Segment .text .globl my_main my_main: # Normal Termination of Program li $v0, 10 syscall 13 Program 2: Load word from memory # Load Word from memory # This program demonstrates the "lw" command # The Data Segment .data temp: .ascii "0123456789ABCDEF" # The Text Segment .text .globl my_main my_main: li lw $s0, 0x10010000 $t1, 0($s0) # our base address #will cause and error since not word-aligned #lw $t1, 1($s0) #lw $t1, 2($s0) #lw $t1, 3($s0) lw lw lw lw $t1, 4($s0) $t2, 8($s0) $t3, 12($s0) $t4, 0x0c($s0) #R[$t2] = M[R[$s0]+4] #R[$t2] = M[R[$s0]+8] #R[$t2] = M[R[$s0]+12] #R[$t2] = M[R[$s0]+12] #exit the program li $v0, 10 syscall Program 3: Storing a register to memory # Storing a register to memory # This program demonstrates the "sw" command # The Data Segment .data my_main: li li $t0, 0x30 $t1, 0x10010000 14 sw $t0, 0($t1) # the following will cause an Error #sw $t0, 1($t1) #sw $t0, 2($t1) #sw $t0, 3($t1) addi sw $t0, 1 $t0, 4($t1) addi sw $t0, 0x12345678 $t0, 8($t1) li sw $t0, $t0, 0xA5A5A5A5 12($t1) #exit the program li $v0, 10 syscall Program 4: Shift Left and Right Instructions # shifting left and right # The Data Segment .data my_main: li $t0, 0xFFFFFFFF sll sll sll sll sll sll sll $t0, $t0, 1 $t0, $t0, 1 $t0, $t0, 1 $t0, $t0, 1 $t0, $t0, 1 $t0, $t0, 1 $t0, $t0, 1 # shift left logical li srl srl srl srl srl srl srl $t1, 0x10010000 $t1, $t1, 1 # shift Right logical $t1, $t1, 1 $t1, $t1, 1 $t1, $t1, 1 $t1, $t1, 1 $t1, $t1, 1 $t1, $t1, 1 15 srl $t1, $t1, 1 #exit the program li $v0, 10 syscall Program 5: # Addition of registers # Data Section .data #Text Section .text .globl my_main my_main: # Main Codes goes here li $t1, 0x1111 li $t2, 0x2222 add $t3, $t1, $t2 li $t1, 0x00000001 li $t2, 0x0000FFFF add $t3, $t1, $t2 li $t1, 0xFFFFFFFF #-1 li $t2, 0x00000002 #+2 add $t3, $t1, $t2 li $t1, 0xFFFFFFFC # -4 li $t2, 0xFFFFFFFD # -3 add $t3, $t1, $t2 # Exit the program li $v0, 10 syscall Program 6: # subtraction # Data Section .data 16 #Text Section .text .globl my_main my_main: # Main Codes goes here li li sub $t1, 0x2222 $t2, 0x1111 $t3, $t1, $t2 # t3=t1-t2 li li sub $t1, 0xFFFF $t2, 0x0001 $t3, $t1, $t2 # t3=t1-t2 # RESULT IS NEGATIVE (2's COMPLEMENT) li $t1, 0x1111 li $t2, 0x2222 sub $t3, $t1, $t2 # t3=t1-t2 li li sub $t1, 0x0001 $t2, 0xFFFF $t3, $t1, $t2 # t3=t1-t2 li li sub $t1, 0x00000001 $t2, 0xFFFFFFFF $t3, $t1, $t2 # t3=t1-t2 li li sub $t1, 0xFFFFFFFF $t2, 0xFFFFFFFE $t3, $t1, $t2 # t3=t1-t2 # Exit the program li $v0, 10 syscall 17 LAB TASK Task 1: Write a program which takes two numbers as input from memory as given in example code. Perform the addition operation and store the results in memory location. Examine the contents of registers $t0, $t2…… $t9; Fill the table below with registers values before and after running the simulation Register number Register name 1 $at 2 $v0 3 $v1 4 $a0 5 $a1 6 $a2 7 $a3 8 $t0 9 $t1 10 $t2 11 $t3 12 $t4 13 $t5 14 $t6 15 $t7 Before the program run After the program run Table 1: Register Values for program 1 18 Task 2: Write a program which takes two numbers as input from memory as given in example code. Perform the subtraction operation and store the results in memory location. Examine the contents of registers $t0, $t2…… $t9; Fill the table below with registers values before and after running the simulation Register number Register name 1 $at 2 $v0 3 $v1 4 $a0 5 $a1 6 $a2 7 $a3 8 $t0 9 $t1 10 $t2 11 $t3 Before the program run After the program run Table 2: Registers Values for program 2 19 EXPERIMENT NO. 3 Logical and Shift Operations in MIPS Architecture Objectives After performing this lab, you will be able to understand and implement following MIPS instructions • OR instruction • AND instruction • NOR instruction • AND immediate instruction • Shift Right instruction • Shift Left instruction Logical Operations Logical operations supported by MIPS architecture are AND, OR and NOR. Example of usage of these instructions in given in table 1. These logical instructions are of type R. Category Logical Shift Instruction Example Meaning And and $s1, $s2, $s3 $s1 = $s2 & $s3 Or or $s1, $s2, $s3 $s1 = $s2 | $s3 Nor nor $s1, $s2, $s3 $s1 = ~ ($s2 | $s3) And Immediate andi $s1, $s2, 20 $s1 = $s2 & 20 shift left logical sll $s1,$s2,10 $s1 = $s2 << 10 shift right logical srl $s1,$s2,10 $s1 = $s2 >> 10 Comments Three reg. operands; bit-bybit AND Three reg. operands; bit-bybit OR Three reg. operands; bit-bybit NOR Bit-by-bit AND reg with constant Shift left by constant Shift right by constant Table 1: Logical Operators in MIPS 20 Shift Operations Shift operations are used to shift the contents of registers in right or left direction by specified offset by filling the emptied bits with 0s. For example, if register $s0 contained 0000 0000 0000 0000 0000 0000 0000 1001two = 9ten and the instruction to shift left by 4 was executed, the new value would be: 0000 0000 0000 0000 0000 0000 1001 0000two = 144ten The dual of a shift left is a shift right. The actual name of the two MIPS shift instructions are called shift left logical (sll) and shift right logical (srl). The following instruction performs the operation above, assuming that the original value was in register $s0 and the result should go in register $t2: sll $t2,$s0,4 # reg $t2 = reg $s0 << 4 bits Procedure: Program 1: And, Or, Nor Operation # And, Or, Andi, Ori and Nor # The Data Segment .data # The Text Section .text .globl my_main my_main: li $t1, 0x5555aaaa li $t2, 0xaaaa5555 and or $t3, $t1, $t2 $t4, $t1, $t2 andi ori $t5, $t1, 0x00FF $t6, $t2, 0xFF00 21 nor $t7, $t5, $t6 #exit the program li $v0, 10 syscall Program 2: Shift Left and Right Instructions # shifting left and right # The Data Segment .data my_main: li $t0, 0xFFFFFFFF sll sll sll sll sll sll sll $t0, $t0, 1 $t0, $t0, 1 $t0, $t0, 1 $t0, $t0, 1 $t0, $t0, 1 $t0, $t0, 1 $t0, $t0, 1 # shift left logical li srl srl srl srl srl srl srl srl $t1, 0x10010000 $t1, $t1, 1 # shift Right logical $t1, $t1, 1 $t1, $t1, 1 $t1, $t1, 1 $t1, $t1, 1 $t1, $t1, 1 $t1, $t1, 1 $t1, $t1, 1 #exit the program li $v0, 10 syscall 22 LAB TASK Task 1: Modify the program 1 such that it takes data from memory using lw and sw instructions and perform logical operations and store back the results in memory. Examine the contents of registers and validate the operation of your code. Fill the table below with registers values before and after running the simulation Register number Register name 1 $at 2 $v0 3 $v1 4 $a0 5 $a1 6 $a2 7 $a3 8 $t0 9 $t1 10 $t2 11 $t3 12 $t4 13 $t5 14 $t6 15 $t7 Before the program run After the program run 23 Task 2: Type and run the program 2 in SPIM simulator with following modifications. a. It should take input from memory location b. Perform the shift operations c. Output must be stored in memory location Examine the contents of registers; Fill the table below with registers values before and after running the simulation Register number Register name 1 $at 2 $v0 3 $v1 4 $a0 5 $a1 6 $a2 7 $a3 8 $t0 9 $t1 10 $t2 11 $t3 12 $t4 13 $t5 14 $t6 15 $t7 Before the program run After the program run Registers Values for program 2 24 EXPERIMENT NO. 4 Control Structures in MIPS Objective After performing this lab exercise you will be able to understand and implement following MIPS instructions • Branch if equal (beq) instruction • Branch if not equal (bne) instruction • Jump Instructions Introduction Except for some very simple programs all others use instructions that control the program flow. In a high level language they may be called if (with its associated then and else), goto (which fans of structured programming hate), for, while, do. In assembly language they may be called branch, jump, call, return. They all have the fundamental property that they change the order in which instructions are executed. They allow the programmer to specify different sequences of instructions to be executed based on the input and/or results calculated earlier in the program. The pointer to the present instruction is the Program Counter (PC). PC is normally updated as to point to the next sequential instruction to execute. Control instructions that may change the PC based on testing some condition are called conditional (or more often branches). Control instructions that always change the PC are called unconditional (or jumps). Any branch must indicate the condition which is tested as to decide whether the branch is taken (change the PC) or not (continue with the next sequential instruction). Any branch instruction must also indicate where to start fetching instructions in case the branch is taken. In other words the instruction must also provide the target). Since branches are usually used to implement loops, and because loops tend to have a small number of instructions, the target is in most cases close to the current instruction. In other words, the difference between the target address and the current PC is small in absolute value. There is no need to include the absolute value of the target in the instruction1. What the instruction can specify instead, is the distance in bytes from the current instruction to the target. This distance (offset) can be positive (for forward branches) or negative (backward branch). If the branch is taken, then the offset is added to the current PC to obtain the address from which the next instruction will be fetched. This is called PC-relative addressing. This laboratory is focused on branches and the regular jump (j). 25 Implementing if-then-else The if-then-else is one of the fundamental programming constructs. The following example indicates how such a construct would be translated in assembly language. Note that then is not a keyword in C. However, the construct presented below is of the type ‘if-then-else’, where the block of code #1 corresponds to the ‘then’ part. Example 1: if (var1 == var2) { .... /* block of code #1 */ } else { .... /* block of code #2 */ } Let’s assume that the values of variables var1 and var2 are in registers $t0 and $t1. Then, this piece of C code would be translated as: bne $t0, $t1, Else # go to Else if $t0 != $t1 .... # code for block #1 beq $0, $0, Exit # go to Exit (skip code for block #2) Else: .... # code for block #2 Exit: # exit the if-else The instruction beq $0, $0, Exit is equivalent to an unconditional jump since the test always succeeds (you could substitute any register name in place of $0 but then it wouldn’t be that obvious what you want to do). The same effect would be obtained by using j Exit (unconditionally jump to label ‘Exit’). Lab Procedure: Program # 1: use of branch instructions # lab 3 - conditional structures in MIPS .data msg1: .asciiz "The nmbers are equal\n" msg2: .asciiz "Numbers are not equal." .text main: 26 addi $t0, $zero, 20 addi $t1, $zero, 20 beq $t0, $t1, numbersEqual addi $t2, $zero, 10 addi $t3, $zero, 15 bne $t2, $t3, numbersDifferent numbersEqual: li $v0, 4 la $a0, msg1 syscall numbersDifferent: li $v0, 4 la $a0, msg2 syscall #Syscall to end program li $v0, 10 syscall Program 2: use of jump instruction # # Jump instruction - unconditional branch # The Data Segment .data Name: Course: NT: .asciiz .asciiz .asciiz "Usman\n" "Computer Architecture\n" "Normal Termination of Program" # The Text Section .text .globl my_main my_main: # Print Name to the console li $v0, 4 27 la $a0, Name syscall #Print Course to Console li $v0, 4 la $a0, Course syscall li $s0, 0x1111 # unconditional branch to label 'L1' j addi addi addi addi L1: L1 # Jump instruction $s1, $s0, 0x01 $s2, $s0, 0x02 $s3, $s0, 0x03 $s4, $s0, 0x04 # label "L1" is here # Normal Termination of main li $v0, 4 la $a0, NT syscall #exit the program li $v0, 10 syscall 28 LAB TASK Reserve space in memory for three variables called var1 through var3. The initial values of var1 and var2 will be the first and the second digit of your Registration number respectively. var3 will be initialized to minus the number of this year. Pseudo code for the lab task is given below. if (var1 == var2) { var1 = var3; /* change the values of var1 and .. */ var2 = var3; /* var2 to the value of var3 */ } else { /* execute when var1 != var2 */ tmp = var1; /* swap the values of var1 and var2 */ var1 = var2; var2 = tmp; } What values do you expect for var1 and var2 after executing this code? Variable Expected Value Var1 Var2 Fill out the ‘Before run’ section of the table below. Use print to look in the memory for the values of var1 and var2. Variable Before Run After Run Var1 Var2 Fill the table below with registers values before and after running the simulation Register number Register name 1 $at 2 $v0 3 $v1 4 $a0 5 $a1 6 $a2 Before the program run After the program run 29 7 $a3 8 $t0 9 $t1 10 $t2 11 $t3 12 $t4 13 $t5 14 $t6 15 $t7 30 EXPERIMENT NO. 5 Procedures in MIPS Objective After completing this lab exercise you will: be able to write procedures in MIPS assembly language use of jal instruction use of jr instruction Introduction In this exercise, we introduce the basic procedure call mechanism in MIPS. Only simple, nonnested, calls are presented. We want to see in detail what happens when a procedure (the caller) calls another procedure (the callee), and when the control is transferred back from the callee to the caller. Along the way we introduce the instructions (jal and jr) that make the mechanism work. The four steps needed to execute a procedure are: a. save the return address (which is the address of the instruction just after the calling point) b. call the procedure c. execute the procedure d. restore the return address and return To compile a procedure, the compiler must know which registers need to be preserved and which can be modified without worry. These rules for register-use are also called procedure call conventions. The following table presents the MIPS register usage convention. 31 Register number Register name Usage 0 zero Always zero 1 $at Reserved for the assembler 2 - 3 $v0 - $v1 Expression evaluation and procedure return results 4 - 7 $a0 - $a3 The first four parameters passed to a procedure. Not preserved across procedure calls 8 - 15 $t0 - $t7 Temporary registers. Not preserved across procedure calls 16 - 23 $s0 - $s7 Saved values. Preserved across procedure calls 24 - 25 $t8 - $t9 Temporary registers. Not preserved across procedure calls 26 - 27 $k0 - $k1 Reserved for kernel usage. 28 $gp Global pointer (pointer to global area) 29 $sp Stack pointer 30 $fp Frame pointera 31 $ra Return address $f0 - $f2 Floating point procedure results $f4 - $f10 Temporary registers. Not preserved across procedure calls $f12 - $f14 $f16 - $f18 The first two floating point parameters. Not preserved d ll Temporary floating point registers. Not preserved across procedure calls $f20 - $f30 Saved floating point values. Preserved across procedure calls MIPS software follows the following convention for procedure calling in allocating its 32 registers. $a0–$a3: four argument registers in which to pass parameters $v0–$v1: two value registers in which to return values $ra: one return address register to return to the point of origin “Not preserved across procedure calls” means that the register may change value if a procedure is called. If some value is stored in that register before the procedure is called, then you may not make the assumption that the same value will be in the register at the return from the procedure. “Preserved across procedure calls” means that the value stored in the register will not be changed by a procedure. It is safe to assume that the value in the register after the procedure call is the same as the value in the register before the call. 32 The MIPS architecture provides two instructions which are used in conjunction to perform the call (while sav- ing the return address) and the return. jal procedure_name – jump and link instruction – jumps to the called procedure jr $ra – unconditional jump to the address specified in the a register JAL ‐‐ Jump and link Description: Jumps to the calculated address and stores the return address in $31 Operation: $31 = PC + 8 (or nPC + 4); PC = nPC; nPC = (PC & 0xf0000000) | (target << 2); Syntax: jal target Encoding: 0000 11ii iiii iiii iiii iiii iiii iiii JR ‐‐ Jump register Description: Jump to the address contained in register $s Operation: PC = nPC; nPC = $s; Syntax: jr $s Encoding: 0000 00ss sss0 0000 0000 0000 0000 1000 Lab Procedure Program # 1: Use of Procedure # # Program demo for procedures # The Data Segment .data message1: .asciiz "Lab Demo for Procedures\n" # The Text Section .text main: 33 jal displayMessage addi $s0, $zero, 5 #Print number 5 to the screen li $v0, 1 add $a0, $zero, $s0 syscall #exit the program otherwise it will start repetition li $v0, 10 syscall displayMessage: li $v0, 4 la $a0, message1 syscall jr $ra # go back to the called procedure Program # 2: Passing Arguments to the Called Procedure #Arguments can be passed to procedures in MIPS just in other programming languages. # Passing Arguments to the Called Procedure .data .text main: addi $a1, $zero, 50 addi $a2, $zero, 100 jal addNumbers # call the procedure #print the value li $v0, 1 addi $a0, $v1, 0 34 syscall #Syscall to end program li $v0, 10 syscall #Tell the system that the program is done addNumbers: # label add $v1, $a1, $a2 # $v1 is for return values jr $ra # go back to calling place Program # 3: Use of Recursive Calling # This procedure computes the factorial of a non-negative integer # The parameter (an integer) received in $a0 # The result (a 32 bit integer) is returned in $v0 # The procedure uses none of the registers $s0 - $s7 so no need to save them # Any parameter that will make the factorial compute a result larger than # 32 bits will return a wrong result. Factorial: subu $sp, $sp, 4 sw $ra, 4($sp) # save the return address on stack beqz $a0, terminate # test for termination subu $sp, $sp, 4 # do not terminate yet sw $a0, 4($sp) # save the parameter sub $a0, $a0, 1 # will call with a smaller argument jal Factorial # after the termination condition is reached these lines # will be executed lw $t0, 4($sp) # the argument I have saved on stack mul $v0, $v0, $t0 # do the multiplication lw $ra, 8($sp) # prepare to return addu $sp, $sp, 8 # I’ve popped 2 words (an address and jr $ra # .. an argument) terminate: li $v0, 1 # 0! = 1 is the return value 35 lw $ra, 4($sp) # get the return address addu $sp, $sp, 4 # return # adjust the stack pointer jr $ra Program steps: ‘main’ prompt the user to enter an integer; store it in $t0 check if the number entered is negative: if it is negative, then print a message saying so and prompt the user again for a number call the procedure named ‘Factorial’ whose parameter will be the integer read from the user, and which returns the factorial of that number pass the parameter in a register prints a message and the value returned by ‘Factorial’ 36 LAB TASK Type and run the program 1 in SPIM simulator with following modifications. a. Program should load 2 values from the memory. b. These values must be passed to the called procedure and addition will be performed c. Called procedure should print the results on console and return control to the main procedure Fill the table below with registers values before and after running the simulation Register number Register name 1 $at 2 $v0 3 $v1 4 $a0 5 $a1 6 $a2 7 $a3 8 $t0 9 $t1 10 $t2 11 $t3 12 $t4 13 $t5 14 $t6 15 $t7 Before the program run After the program run Table 1: Register Values for program 1 37 EXPERIMENT NO. 6 Arrays and Pointers in MIPS Objective After completing this lab exercise you will Understand use of array in MIPS Understand use of pointers in MIPS programs Introduction Since arrays can store lots of data, and since we have only a small (~32) number of registers, it is infeasible to use the registers for long-term storage of the array data. Hence, arrays are stored in the Data Segment of a MIPS program. Fundamentally, there are three operations which one can perform on an array: Getting the data from an array cell Storing data into an array cell Determining the length of an array For purposes of this step in the lab, you may assume that the length of the array is 3. To access the data in the array requires that we know the address of the data and then use the load word (lw) or store word (sw) instructions. Words (which is how integers are stored) in MIPS take up 32 bits or 4 bytes. Therefore, if we have a declaration such as: myArray: .space 12 # allocate space in RAM This will store 12 bytes in memory and the array name is myArray. Program # 1: Storing and Retrieving Data in Array # Data Section .data myArray: .space 12 # allocate space in RAM # 12 for 3 integers as integer take 4 byte .text main: 38 addi $s0, $zero, 4 addi $s1, $zero, 10 addi $s2, $zero, 12 # these numbers are in registers # indext = $t0 addi $t0, $zero, 0 # clear t0 sw $s0, myArray($t0) addi $t0, $t0, 4 sw $s1, myArray($t0) addi $t0, $t0, 4 sw $s2, myArray($t0) lw $t6, myArray($zero) li $v0, 1 addi $a0, $t6,0 syscall #Syscall to end program li $v0, 10 syscall Program # 2: Printing the array data using while loop # Data Section .data myArray: .space 12 # allocate space in RAM # 12 for 3 integers as integer take 4 byte newLine: .asciiz "\n" .text main: addi $s0, $zero, 4 addi $s1, $zero, 10 addi $s2, $zero, 12 # these numbers are in registers 39 # index = $t0 addi $t0, $zero, 0 # clear t0 sw $s0, myArray($t0) addi $t0, $t0, 4 sw $s1, myArray($t0) addi $t0, $t0, 4 sw $s2, myArray($t0) #Clear $t0 to 0 addi $t0, $zero, 0 while: beq $t0, 12, exit # when index t0 #is greater than 12, break out of loop lw $t6, myArray($t0) addi $t0, $t0, 4 #Print current number li $v0, 1 move $a0, $t6 syscall #Print a new line li $v0, 4 la $a0, newLine syscall j while exit: #Syscall to end program li $v0, 10 syscall 40 Stack Memory Suppose a compiler needs more registers for a procedure than the four argument and two return value registers. Since we must cover our tracks after our mission is complete, any registers needed by the caller must be restored to the values that they contained before the procedure was invoked. The ideal data structure for spilling registers is a stack—a last-in-first-out queue. A stack needs a pointer to the most recently allocated address in the stack to show where the next procedure should place the registers to be spilled or where old register values are found. The stack pointer is adjusted by one word for each register that is saved or restored. MIPS software reserves register 29 for the stack pointer, giving it the obvious name $sp. Stacks “grow” from higher addresses to lower addresses. This convention means that you push values onto the stack by subtracting from the stack pointer. Procedure A stored subroutine that performs a specific task based on the parameter with which it provided. Jump-and-link instruction An instruction that jumps to an address and simultaneously saves the address of the following instruction in a register ($ra in MIPS). Return Address A link to the calling site that allows a procedure to return to the proper address; in MIPS it is stored in register $ra 41 Caller A procedure that instigates a procedure and provides the necessary parameter values. Callee A procedure that executes a series of stored instructions based on parameter provided by the caller and then returns control to the caller. Program Counter (PC) The register containing the address of the instruction in the program being executed. Stack Pointer A value denoting the most recently allocated address in a stack that shows where registers should be spilled or where old register values can be found. In MIPS, it is a register $sp. Push Add element to stack Pop Remove element from stack Program # 3: working with stack pointers # Simple subroutine call using the Jump and Link (jal) instruction # with pushing and popping on/off the stack .data msg: sub1Msg: NT: .asciiz .asciiz "Demo Program: Jump and Link with Stack\n\n" "Inside Sub1\n" .asciiz "Normal Termination of Program" .text .globl my_main my_main: #Beginning of the Main Program li $v0, 4 la $a0, msg syscall li $s0, 0 li $s1, 1 li $s2, 2 li $s3, 3 42 li $s4, 4 li $s5, 5 li $s6, 6 li $s7, 7 # Call subroutine #1 jal sub1 #Call subroutine #1 jal sub1 #Normal Termination of Main li $v0, 4 la $a0, NT syscall li $v0, 10 syscall ## main end ### ######################################## sub1: # Create room on the Stack addi $sp, $sp, -32 #sub1 begin# #Push 's' registers onto the stack sw $s0, 28($sp) sw $s1, 24($sp) sw $s2, 20($sp) sw $s3, 16($sp) sw $s4, 12($sp) sw $s5, 8($sp) sw $s6, 4($sp) sw $s7, 0($sp) #Do something li $v0, 4 la $a0, sub1Msg syscall # print msg on console #Change values of 's' registers li $s0, -1 li $s1, -1 li $s2, -1 li $s3, -1 li $s4, -1 43 li $s5, -1 li $s6, -1 li $s7, -1 #Pop 's' registers off of the stack lw $s7, 0($sp) lw $s6, 4($sp) lw $s5, 8($sp) lw $s4, 12($sp) lw $s3, 16($sp) lw $s2, 20($sp) lw $s1, 24($sp) lw $s0, 28($sp) # Restore stack pointer addi $sp, $sp, 32 # Return to the calling program jr $ra ### sub1 End ### ############################################### 44 LAB TASK Task 1: Do the following modification in program 1 and run it on simulator. a. Store 5 bytes of data in array on memory b. Retrieve only first and last byte store in the array and print it on console Examine the contents of registers; Fill the table below with registers values before and after running the simulation Register name Before the program run After the program run $at $v0 $v1 $a0 $a1 $a2 $a3 $t0 $t1 $t2 $t3 $t4 $t5 $t6 $t7 $s0 $s1 $s2 $s3 $s4 45 $s5 $s6 $s7 $sp Task 2: Modify and run program # 3 with following modifications. a. Add the sum of s0 and s1 and store result in s5 b. Subtract s3 from s4 and store result in s6 c. Add s6 and s5 and return this result to the calling function Examine the contents of registers; Fill the table below with registers values before and after running the simulation Register number Register name Before the program run After the program run Inside the main Procedure 1 $at 2 $v0 3 $v1 4 $a0 5 $a1 6 $a2 7 $a3 8 $s0 9 $s1 10 $s2 11 $s3 12 $s4 13 $s5 14 $s6 15 $s7 29 $sp 46 Inside the Calle Procedure 1 $at 2 $v0 3 $v1 4 $a0 5 $a1 6 $a2 7 $a3 8 $s0 9 $s1 10 $s2 11 $s3 12 $s4 13 $s5 14 $s6 15 $s7 29 $sp 47 EXPERIMENT NO. 7 Architecture Design and Implementation of 32-Bit Adder using Verilog Objective To understand and design 32-bit binary adder for MIPS architecture based processor Binary Addition Addition of two number 7 (base 10) and 6 (base 10) is show below. Both numbers are represented below in 32-bit binary format. 0000 0000 0000 0000 0000 0000 0000 0111two = 7ten + 0000 0000 0000 0000 0000 0000 0000 0110 two = 6ten = 0000 0000 0000 0000 0000 0000 0000 1101 two = 13ten The 4 bits to the right have all the action; Figure 1 shows the sums and carries. The carries are shown in parenthesis, with the arrows showing how they are passed. Figure 1: Binary addition, showing carries from right to left The rightmost bit adds 1 to 0, resulting in the sum of this bit being 1 and the carry out from this bit being 0. Hence, the operation for the second digit to the right is 0+1+1. This generates a 0 for this sum bit and a carry out of 1. The third digit is the sum of 1+1+1, resulting in a carry out of 1 and a sum bit of 1. The fourth bit is 1+0+0, YIELDING a 1 sum and no carry. 48 32-Bit Binary Adder Design Verilog HDL (Hardware Description Language) will be used to design a complete 32-bit binary adder. Hierarchal Design Approach will be used to design 32-bit adder. Following steps will be performed while designing a 32-bit adder. 1. Gate Level Design methodology of Verilog HDL will be used to design a 1 bit full adder. Circuit for 1 bit full adder is shown in Figure below. 2. In this stage, 4-bit full adder will be designed. Four 1-bit full adders designed in step 1, will be utilized for designing 4-bit adder. 3. During this stage, four 4-bit full adders will be used to construct 16-bit adder. 4. In this stage, two 16-bit adders will be used to design 32-bit adder. Figure. 4-bit Adder Design using 4 1-bit Full Adders 49 Figure. 16-bit Adder using four 4-bit Full Adders B(31:16) A(31:16) 16-bit Full Adder Cout S(31:16) A(15:0) 16-bit Full Adder Cin Cout B(15:0) Cout Cin S(15:0) Figure. 32-bit Full Adder using two 16-bit Full Adders 50 Verilog HDL Code for 1-bit Full Adder module adder1(A,B,Cin, S,Cout); input A,B, Cin; output S,Cout; assign S = Cin ^(A ^ B); assign Cout = (A&B) | (Cin &(A^B)); endmodule Verilog HDL Code for 4-bit Full Adder module adder4(A,B,Cin, S,Carry); input [3:0]A,B; wire [3:0] Cout; input Cin; output [3:0] S; output Carry; adder1 a1(A[0],B[0],Cin, S[0],Cout[0]); adder1 a2(A[1],B[1],Cout[0], S[1],Cout[1]); adder1 a3(A[2],B[2],Cout[1], S[2],Cout[2]); adder1 a4(A[3],B[3],Cout[2], S[3],Cout[3]); assign Carry=Cout[3]; endmodule LAB TASK Design a 32-bit Adder using Verilog HDL. Simulate your design in ModelSim environment. RTL diagram Show the timing diagrams (waveforms) showing the input and output signals during simulation. 51 EXPERIMENT NO. 8 Design and Simulation of 32-Bit Subtractor Objective To understand and design2 32-bit binary subtraction mechanism for MIPS architecture based processor Binary Subtraction Computer program calculate both positive and negative numbers, so we need a representation that distinguishes the positive from the negative. The most obvious solution is to add a separate sign, which conveniently can be represented in a single bit; the name for this representation is sign and magnitude. But sign and magnitude representation has several shortcomings. To make the hardware simple, the final solution to the problem was to represent numbers in two’s complement format. Figure 1: Two’s Complement Representation 52 Figure 2: Two’s complement method In two’s complement form, a negative number is the 2’s complement of its positive number with the subtraction of two numbers being A – B = A + (2’s complement of B) using much the same process as before as basically, two’s complement is one’s complement + 1. Arithmetic operations are relatively easier to perform when the numbers are represented in the two’s complement format. Let’s look at the subtraction of our two 8-bit numbers 115 and 27 from above using two’s complement, and we remember from above that the binary equivalents are: 11510 in binary is: 0 1 1 1 0 0 1 1 2 2710 in binary is: 0 0 0 1 1 0 1 1 2 Our numbers are 8-bits long, then there are 28 digits available to represent our values and in binary this equals: 1000000002 or 25610. Then the two’s complement of 2710will be: (28)2 – 00011011 = 100000000 – 00011011 = 111001012 The complementation of the second negative number means that the subtraction becomes a much easier addition of the two numbers so therefore the sum is: 115 + ( 2’s complement of 27 ) which is: 01110011 + 11100101 = 1 010110002 As previously, the 9th overflow bit is disregarded as we are only interested in the first 8-bits, so the result is: 010110002 = 8810 in decimal the same as before. 53 Design of 32 Bit Subtractor 32-bit adder designed in previous lab will be utilized to design subtractor In order to get subtraction Result = A+ (– B), we need to take 2’s complement of input B First, input B will be inverted, using bitwise negation operator (assign Binv = ~B) Carry input (Cin) will be high for subtraction, as it adds 1 to the input Binv, this in turns changes the B input into 2’s complement format i.e. B (2’s complement) = Binv +1 Now normal addition operation will take place on input A and (-B) i.e. Result = A + (-B) B (31:0) A (31:0) Cin Cin = High (for Subtraction) Result (31:0) 11 Figure. 32-bit Subtractor Design using 32-bit Full Adder 54 LAB TASK Design a 32-bit Subtraction using Verilog HDL. Simulate your design in ModelSim environment. Generate the RTL diagram of subtractor Show the timing diagrams (waveforms) showing the input and output signals during simulation. 55 EXPERIMENT NO. 9 Design of Overflow Detection Mechanism in 32-bit Adders Objective To understand and design overflow detection mechanism in 32-bit binary adder for MIPS architecture based processor Binary Addition Addition of two number 7 (base 10) and 6 (base 10) is show below. Both numbers are represented below in 32-bit binary format. The 4 bits to the right have all the action; Figure 1 shows the sums and carries. The carries are shown in parenthesis, with the arrows showing how they are passed. Figure 1: Binary addition, showing carries from right to left The rightmost bit adds 1 to 0, resulting in the sum of this bit being 1 and the carry out from this bit being 0. Hence, the operation for the second digit to the right is 0+1+1. This generates a 0 for this sum bit and a carry out of 1. The third digit is the sum of 1+1+1, resulting in a carry out of 1 and a sum bit of 1. The fourth bit is 1+0+0, yielding a 1 sum and no carry. 56 Overflow in Signed Arithmetic Overflow occurs when the result from an operation cannot be represented with the available hardware, in this case a 32-bit word. When can overflow occur in addition? When adding operands with different signs, overflow cannot occur. The reason is the sum must be no larger than one of the operands. For example, -10+4 = -6. Since the operands fit in 32 bits and the sum is no larger than an operand, the sum must in 32 bits as well. Therefore, no overflow can occur when adding positive and negative operands. There are similar restrictions to the occurrence of overflow during subtract, but it’s just the opposite principle: when the signs of the operands are the same, overflow cannot occur. To see this, remember that x-y = x+(-y) because we subtract by negating the second operand and then add. So, when we subtract operands of the same sign we end up by adding operands of different signs. From the prior paragraph, we know that overflow cannot occur in this case either. Having examined when overflow cannot occur in addition and subtraction, we still haven’t answered how to detect when it does occur. Overflow occurs when adding two positive numbers and the sum is negative, or vice versa. Clearly, adding or subtracting two 32 bit numbers can yield a result that needs 33 bits to be fully expressed. The lack of a 33rd bit means that when overflow occurs the sign bit is being set the value of the result instead of the proper sign of the result. This means that carry out occurred into the sign bit. Overflow occur in subtraction when we subtract a negative number from a positive number and get a negative result, or when we subtract a positive number from a negative number and get positive result. This means a borrow occurred from the sign bit. 57 Table 1: Overflow Conditions for Addition and Subtraction Here are some facts about overflow in Signed Arithmetic. If x and y have opposite signs (one is negative, the other is non-negative), then the sum will never overflow. Just try it out. The result will either be x or y or somewhere in between. Thus, overflow can only occur when x and y have the same sign. One way to detect overflow is to check the sign bit of the sum. If the sign bit of the sum does not match the sign bit of x and y, then there's overflow. This only makes sense. Suppose x and y both have sign bits with value 1. That means, both representations represent negative numbers. If the sum has sign bit 0, then the result of adding two negative numbers has resulted in a non-negative result, which is clearly wrong. Overflow has occurred. Suppose x and y both have sign bits with value 0. That means, both representations represent non-negative numbers. If the sum has sign bit 1, then the result of adding two non-negative numbers has resulted in a negative result, which is clearly wrong. Overflow has occurred. Block Diagram of the Overflow Detection System Figure 1. Overflow Detection mechanism for Addition and Subtraction 58 One way to detect overflow is to look at the sign bits of the two most significant bits and compare it to the sum. A(sign bit) B (sign bit) Result (sign bit) 0 1 0 1 0 1 0 1 0 1 1 0 0 1 1 0 x x Overflow Status No Overflow No Overflow Overflow Overflow No Overflow NO overflow Table 2: Overflow Logic for Addition and Subtraction Lab Task Design the overflow detection mechanism for 32-bit Adder in Verilog HDL. Write a testbench and simulate your design in ModelSim environment. Generate RTL diagram of your overflow detector and attach it with report. Show the timing diagram (waveform) which shows the input and output signals. Figure 2. Circuit for Overflow Detection in Addition and Subtraction 59 EXPERIMENT NO. 10 Design of 32-Bit Serial Multiplier Objective To understand and design 32-bit binary serial multiplier, specifically used in MIPS architectures. Introduction Assume that the multiplier is in the 32-bit Multiplier register and that the 64-bit Product register is initialized to 0. We need to move the multiplicand left one digital each step, as it may be added to the intermediate products. Over 32 steps a 32-bit multiplicand would move 32 bits to the left. 60 Figure 1: Multiplication algorithm, using the hardware Hence we need 64-bit Multiplicand register, initialized with the 32-bit multiplicand in the right half and 0 in the left half. This register is then shifted left 1 bit each step to align the multiplicand with the sum being accumulated in the 64-bit Product register. Algorithm Step 1: If the least significant bit of the multiplier is 1, add the multiplicand to the product. If not, go to the next step.1 Step 2: Shift multiplicand register left 1 bit Step 3: Shift multiplier register right 1 bit These three steps are repeated 32 times. Figure 2: Hardware for the multiplication Multiplicand Register => 64 bit Product Register => 64 bit Multiplier Register => 32 bit 61 Lab Task Design 32-bit Serial Multiplier in Verilog HDL. Write a testbench and simulate your design in ModelSim environment. Generate RTL diagram of your overflow detector and attach it with report. Show the timing diagram (waveform) which shows the input and output signals. 62 EXPERIMENT NO. 11 Design of Basic Algorithmic Logic Unit (ALU) Objective To understand, design and Implement Basic Algorithmic and Logic Unit used in MIPS architectures. Algorithmic Logic Unit The arithmetic logic unit (ALU) is the brain of the computer, the device that performs the arithmetic operations like addition and subtraction or logical operations like AND and OR. This section constructs an ALU from four hardware building blocks (AND and OR gates, inverters, and multiplexors) and illustrates how combinational logic works. In the next section, we will see how addition can be sped up through more clever designs. Because the MIPS word is 32 bits wide, we need a 32-bit-wide ALU. Let’s assume that we will connect 32 1-bit ALUs to create the desired ALU. We’ll therefore start by constructing a 1-bit ALU. Figure 1: The symbol commonly used to represent an ALU 63 1-Bit ALU The 1-bit logical unit for AND and OR looks like Figure 2. The multiplexor on the right then selects a AND b or a OR b, depending on whether the value of Operation is 0 or 1. Notice that we have renamed the control and output lines of the multiplexor to give them names that reflect the function of the ALU. The next function to include is addition. An adder must have two inputs for the operands and a single-bit output for the sum. There must be a second output to pass on the carry, called CarryOut. Since the CarryOut from the neighbor adder must be included as an input, we need a third input. This input is called CarryIn. Figure 2: 1-Bit ALU that performs And, Or, Add and Subtract Operations 64 ALU Control Lines Function 0000 AND 0001 OR 0010 add 0110 subtract 0111 set on less than 1100 NOR Table 1: The value of the three ALU control lines, Ainvert, Binvert and the corresponding ALU operations 32-Bit ALU To further tailor the ALU to the MIPS instruction set, we must support conditional branch instructions. These instructions branch either if two registers are equal or if they are unequal. The easiest way to test equality with the ALU is to subtract b from a and then test to see if the result is 0, since (a - b = 0) a= b. Thus, if we add hardware to test if the result is 0, we can test for equality. The simplest way is to OR all the outputs together and then send that signal through an inverter: Figure 3 shows the revised 32-bit ALU. We can think of the combination of the 1-bit Ainvert line, the 1-bit Binvert line, and the 2-bit Operation lines as 4-bit control lines for the ALU, telling it to perform add, subtract, AND, OR, or set on less than. Table 1 shows the ALU control lines and the corresponding ALU operation. Finally, now that we have seen what is inside a 32-bit ALU, we will use the universal symbol for a complete ALU, as shown in Figure 1. 65 Lab Task Design a 32-bit ALU by cascading 1-bit 32 ALUs in Verilog HDL. Write a testbench and simulate your design in ModelSim environment. Generate RTL diagram of your system design and attach it with report. Show the timing diagram (waveform) which shows the input and output signals. Figure. The final 32-bit ALU 66 EXPERIMENT NO. 12 Design of Enhanced Algorithmic Logic Unit Objective To enhance the operational capability of Basic ALU designed in previous lab by adding following operations. Shift left logical (sll) Shift Right logical (srl) Shift left logical variable (sllv) Shift right logical variable (srlv) Multiply (mult) Enhanced Algorithmic Logic Unit ALU designed in previous lab exercise is now modified and enhanced by adding other operations which are used in MIPS. Functionality of shift operations and multiplication is added. A shift left logical of one position moves each bit to the left by one. The low-order bit (the rightmost bit) is replaced by a zero bit and the high-order bit (the left-most bit) is discarded. Shifting by two positions is the same as performing a one-position shift two times. Shifting by zero positions leaves the pattern unchanged. Shifting an N-bit pattern left by N or more positions changes all of the bits to zero. The picture shows the operation performed on eight bits. The original pattern is1010 0111. The resulting pattern is 0100 1110. The MIPS processor always performs the operation on a 32-bit register and puts the result in a 32-bit register. sll d,s,shft # $d gets the bits in $s # shifted left logical # by shft positions, 67 # where 0 ≤ shft < 32 MIPS also has a shift right logical instruction. It moves bits to the right by a number of positions less than 32. The high-order bit gets zeros and the low-order bits are discarded. If the bit pattern is regarded as an unsigned integer, or a positive two's comp. integer, then a right shift of one bit position performs an integer divide by two. A right shift by N positions performs an integer divide by 2N. srl d,s,shft # $d gets the logical # right shift of $s # by shft positions. # shft is a 5-bit # integer, 0 ≤ shft < 32 Shift left logical by a variable (sllv) instruction in MIPS shifts the towards left by number of bits defined by register $s, shown in table 1. Shift right logical by variable instruction in MIPS shifts the towards right by number of bits defined by register $s, shown in table 1. instruction opcode/function syntax operation sll 000000 $d, $t, a $d = $t << a srl 000010 $d, $t,a $d=$t>>>a sllv 000100 f $d, $t, $s srlv 000110 f $d, $t, $s $d = $t >>> $s mult 011000 $s, $t hi:lo = $s * $t $d = $t << $s Table 1: Shift and multiplication Instructions 68 Figure 1: The symbol commonly used to represent an ALU Multiplication (mult) The generic form of the mult (signed 2C integer multiplication) is mult $rs, $rt. Multiplier has been designed on hardware in previous labs. Format and usage of mult instruction is presented in table 1. 69 Lab Task Design and implement the enhanced 32-bit ALU in Verilog HDL. Write a testbench and simulate your design in ModelSim environment. Generate RTL diagram of your system design and attach it with report. Show the timing diagram (waveform) which shows the input and output signals. Figure. The final 32-bit ALU 70