Readings
- Counters (Program Counter - PC):
- N2T: Chapter 3 Intro, 3.1 (Counters), 3.2.4, 3.3 (Counter), 3.4, 3.5 (slides 47-50, 59, 60-end)
- Assembly Language:
Description
This assignment will focus on the following tasks:
- building the program counter and jump/branch module
- writing programs that use functions and recursion in Assembly (at the end)
Build the
PC
circuit described in Project 3:
N2T: Project 3
Chapters 3 provides the contract for each chip, i.e. description of its behavior, names and number inputs, names and state of outputs. The API is available here:
The Hack Chipset
Assembly Language Programming
vvv
vvv Scroll to the bottom. Consider starting with the Assembly section.
vvv
Design in Logisim
Note the following requirements:
- create empty folder
cs221/05/
and save the Logisim files there
- label the input pins exactly as specified in the contract:
- if there are multiple circuits in the same file, add pin index, i.e. a1, a2, a3
- if a name is rejected, add _pin, i.e. in_pin, out_pin
Here are additional specific requirements:
PC
:
- save in file named PC.circ
- hint: this is a register that increments by 1
- the bus widths of in/out will be 16 bit
- use existing components from Logisim (all implemented previously)
- for testing will need to attach a clock
- minimal use of basic gates
Jumper
[not in the book, combinational gate]:
Chip name: Jumper
Inputs: zr, ng, // same meaning as ALU
opcode[3] // 001=BGT, BEQ, BGE, BLT, BNE, BLE, BAL=111
// 000=no jump
Outputs: jump
Function: jump = 1, if zr and ng correspond to the given opcode; else jump=0
Recall that the ALU from Chapter produces two single-bit outputs:
zr
- to indicate whether the result was zero
ng
- to indicate whether the result was negative
Create a circuit that with the following inputs and outputs:
- save in Jumper.circ
- 1-bit inputs:
zr, ng
: same meaning as in ALU
- 3-bit input:
in
: indicates what branch we are attempting to achieve; corresponds to the ARM instructions BXX
- 1-bit output: indicates whether the program should jump/branch or not; for example:
opcode=011, zr=0, ng=1
produces out=0
; user wanted to jump on BGE
but the latest result was a negative number
opcode=011, zr=0, ng=0
produces out=1
; user wanted to jump on BGE
and the latest result was a positive number
opcode=011, zr=1, ng=0
produces out=1
; user wanted to jump on BGE
and the latest result was zero
opcode=011, zr=1, ng=1
produces out=0
; this combination of zr,ng
is not possible
- moderate use of basic gates
Splitter
: Logisim has a component called Splitter
under Wiring
; it can be used to select a single bit from a bus (or a group of bits)
Constants
: note that Constants
components can be given width which makes it possible to propagate multiple 1s or 0s on a wide bus
Design in HDL
Note the following additional requirements:
- in folder cs221/05/ and cs221/05/ copy one at a time the starter code for the required circuits:
Here are additional specific requirements:
PC
:
- hint: this is a register that increments by 1
- use existing HDL components (all implemented previously)
- minimal use of basic gates
Jumper
:
- see description in Logisim section
- save in Jumper.hdl
- create Mux8Way.hdl and Mux4Way.hdl based on the 16-bit versions from Project 5
- download test files: Jumper.tst, Jumper.cmp
- moderate use of basic gates
Splitter
: to achieve the effect of splitting wires in HDL you write gatepin=wire[i..j]
or gatepin[i..j]=wire
(the widths have to match)
more generally, you can write gatepin[i..j]=wire[p..q]
(the widths have to match), but this general version will not be needed for this assignment
gatepin
could be an input or output pin of the gate
Constants
: to achieve the effect of sending the constant values 1 or 0 to a pin in HDL you write gatepin=true
or gatepin=false
(should work regardless of pin width)
Modify and test the respective .hdl file given by the authors:
- Win users: could use Notepad (shows line numbers at bottom right)
- Mac users: could use TextEdit; ensure file is edited and saved in Plain Text: "Format Menu:Make Plain Text"
Assembly Language Programming
Note the following:
R12
is FP
(cannot write FP
)
- put at the very top (see examples code above):
MOV SP, #0x1100
this will allow you to view the stack contents in Memory Viewer
Arrays as Parameters
Modify the example from class
sum_array.asm (linked at the top), so that it can be used as a function of two parameters that returns the sum of the first
n
numbers:
def sum_array( numbers, n ):
...
...
return the-sum-of-first-n-numbers
- the code should be put in a function section
- the function should take two parameters:
- the base to the beginning of the array
- the number of elements in the array
- the function should return the overall sum of the numbers in the array up to the given length
At the top declare two different arrays of different lengths and run the function as follows:
- once for each array and its true size
- once for each array for half its size
- once for each array for size 1
- indicate in a comment at the top whether the function worked or not for each of the cases
Fibonacci Numbers
In file
fibonacci.asm write a recursive function that computes the
n-th
Fibonacci number:
def fib( n ):
if n == 1:
return 0
elif n == 2:
return 1
else:
return fib(n-1) + fib(n-2)
At the top run the function 4 times times one after the other:
- once for the required cases
- once for
n=6, 10
- indicate in a comment at the top whether the function worked or not for each of the cases
Recursive Binary Search
In file
binarySearch.asm write a recursive function that search for a value in an array using binary search.
Recall that binary search requires a sorted array and works as follows:
- check the middle index in the current range
- if value at middle is bigger than value to find, search in left half of range; otherwise, search in right half
- do not include the middle index as part of the next range to search
def binarySearch( i, j, numbers, value ):
if i > j:
return 0, -1
m = (i+j) / 2
if numbers[m] == value:
return 1, m
elif numbers[m] > value:
return binarySearch( i, m-1, numbers, value )
else:
return binarySearch( m+1, j, numbers, value )
The function takes 4 parameters in this order:
i, j
(inclusive) of current section to search
- the base of the array
- the value to search for
The function returns two numbers:
- either 1 or 0 to indicate the result
- the index where the value was found (or -1 if value not found)
Note that ARM does not have instruction to divide, but division by 2 can be accomplished via right shift:
LSR DestReg, RegToShift, NumShifts
At the top declare two different arrays of different lengths and run the function several times:
- look for first, last, inside, missings
- indicate in a comment at the top whether the function worked or not for each of the cases
Note the following:
- the test array must be sorted, so just list the numbers in order
- the "fail" base case in Java is
i > j
- when a recursive call is made, the mid index is not included in the recursion, since that cell has been examined already