EE 361 Fall 03: Homework 7

Due: The original due date was 10/17/03 (friday) but the NEW due date is 10/22/03 (wednesday).

Instructions:  Do the two problems below.  Email the verilog file for Problem A and the assembly language file for Problem B as attachements to the EE 361 Grader J. Ebisu (ebisu@wiliki.eng.hawaii.edu).  In addition, "cc" the email to me at sasaki@wiliki.eng.hawaii.edu.  You should also cc yourself for your records.  Have the subject heading "EE 361 Homework 7 YourName".  Email by October 17, 2003 before class at 12:30pm.  

Problem A (2 pt). You will design a verilog module called "Lights".  Use the editor in veriwell to create the file for the module, and label it "YourLastName_FirstInitial_EE361_H7.v".  The first line of the file should have "EE 361 Homework 7 Problem A," your name, and date.

The circuit has the following ports:  4-bit output port "q", a clock input "clock", and a 2-bit select input "s".  The select determines one of four possible modes for the circuit:

The circuit is synchronized with the positive edge of the clock.  

Your verilog module should have the following form:

//EE 361 Homework 7 Problem A, John Doe, October 17, 2003

module Lights(q, clock, s);
output [3:0] q;
input clock;
input [1:0] s;
.
. fill in here (see below for a hint).
.
endmodule

[Hint:  The lights circuit should have a 2-bit state.   It should be comprised of a procedural-always (and case statement) that updates the state, and another-procedural always that is used to convert the state value to the appropriate output value.  The first procedural-always corresponds to a sequential circuit, and the second corresponds to a combinatorial circuit.]

After designing the Lights module, create a testbench file using the veriwell's editor.  The following is a suggestion (warning:  could be buggy).

module testbench;
reg [1:0] tests, // This is connected to the input of the Lights circuit.
reg clock; // This will be used to generate a clock signal.
wire [3:0] testq; // This is connected to the output of the Lights circuit.

// We instantiate the Lights circuit into our testbench, and connect the testbench variables to
// its ports.

Lights testlights(testq,clock,tests);

// The following is our clock generator which creates a clock signal with period of 2 time units.
initial clock = 0; // initializes clock to 0
always #1 clock = ~clock; // inverts clock every 1 time unit.

// We will control the value of the select input of the Lights circuit so that it first
// resets, then rotates to the right for 10 time units, hold its value for 4 time units,
// and then rotate to the left for 10 time units.
initial
begin
tests = 0;
#4
tests = 1;
#10
tests = 3;
#4
tests = 2;
#10
$stop;
end

// Next use "display" and "monitor" to output (probe) the
// values of the circuit, to see if it works. This is left for you to do.
// The Bucknell Verilog handbook has some examples.
.
.
endmodule

Now create a project and test your circuit. After debugging turn in the file that
has the Lights module as per the instructions above. Do not turn in your test bench.

Problem B. (2 pts) Consider the following simple C program hw7.c:

main()
{ printf("Hello world\n");}

After compiling (using mcc) you get the following assembly language code

	.file	1 "hw12.c"

# GNU C 2.5.7 [AL 1.1, MM 40] BSD Mips compiled by CC

# Cc1 defaults:

# Cc1 arguments (-G value = 8, Cpu = default, ISA = 1):
# -quiet -dumpbase -fno-delayed-branch

gcc2_compiled.:
__gnu_compiled_c:
.rdata
.align 2
$LC0:
.ascii "Hello world!\n\000"
.text
.align 2
.globl main

.loc 1 2
.ent main
main:
.frame $fp,24,$31 # vars= 0, regs= 2/0, args= 16, extra= 0
.mask 0xc0000000,-4
.fmask 0x00000000,0
subu $sp,$sp,24
sw $31,20($sp)
sw $fp,16($sp)
move $fp,$sp
la $4,$LC0
jal printf
$L1:
move $sp,$fp # sp not trusted here
lw $31,20($sp)
lw $fp,16($sp)
addu $sp,$sp,24
j $31
.end main

Before getting to the assignment, let's take a little time to figure out what's going on with the code.

  1. The assembly language program is composed of instructions, labels, and assembler directives. Assembler directives start with periods (e.g., .ascii, .align, .globl. These assembler directives are instructions for the assembler and loader. They are not real instructions for the MIPS processor. You can find a description of assembler directives in Appendix A (pages A-51 to A-53). Here are some of the important assembler directives for the program:

  2. There are several pseudo instructions: la and move. You can also find these in Appendix A.10. Recall that "move" can be implemented using "add".
  3. There are labels that are automatically generated by the compiler: $LCO and $L1.

You can click here to down load this compiled program. This program will not run using xspim because there is no "printf" subroutine. Modify the program so that it runs on xspim:

  1. Change the line .ascii "Hello world!\n\000" to .asciiz "Hello world!\n". Now the ascii string is terminated by a null character (zero).
  2. Add a subroutine "printf" (add it after the line .end main ). The subroutine should have only one parameter passed to it through a register (which register?). It will print the character string pointed to by the register and terminated by the null character. To print characters, use the memory mapped io feature of xspim which is described in Section A.8, pages A-36 to A.38. To print characters you need to use the Transmitter Control Register at 0xffff0008, and the Transmitter Data Register at 0xffff000c. Note that these registers are similar to ones we've had in a previous homework. However, these registers are assumed to be 32 bits (even though at most 8 of those bits are ever used).
  3. When invoking xspim type xspim -mapped_io. This will load the memory mapped io feature of xspim.

Call the file containing the modified program "YourLastName_FirstInitial_EE361H7B.s".  In the first line of the file, put "EE 361 Homework 7, Problem B", your name, and date.

Here are some things to be aware of:

  1. Ignore the reference to "exceptions" (or interrupts) in Section A.8. The default is to turn off the exceptions which is what we want anyway.
  2. You may find that your program prints out "Hello world!" but not the "new line" character (i.e., "\n"). What may be happening is that your program stops the xspim simulator before the last character can be printed. To print the last character, have the subroutine "printf" check for the terminal to be "ready" before jumping to the return address. Having the terminal "ready" means that the last character has been printed.