EE 361 Fall 04

Homework 7

Due: 10/20/04 (wed)

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 Steven Williamson (WILLSTEVO@aol.com).  In addition, "cc" the email to me at sasaki@spectra.eng.hawaii.edu.  You should also cc yourself for your records.  Have the subject heading "EE 361 Homework 7 YourName".  Email by October 20, 2004 (wed) 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_H7A.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 19, 2004

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 left for 10 time units (or 5 clock cycles), hold its value for 4 time units,
//  and then rotate to the right for 10 time units (or 5 clock cycles).  
initial 
   begin
   tests = 2;
   #4
   tests = 1;
   #10
   tests = 3;
   #4
   tests = 0;
   #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)

[Hi EE 361, there are a few changes in "red"..]

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 "hw7.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 pcspim.  The io feature is described in Section A.8, pages A-36 to A.38 (for spim and xspim, you must invoke "-mapped_io" flag but for pcspim this is not required.  For pcspim, you can verify if the Mapped I/O is checked by going to the Simulation menu and then going to Settings.  The default is for it to be on.  See Appendix Section A.9 for a description of spim). 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. If your new program works properly, you should have "Hello world!" displayed on the "console", which is a separate window from the main window of PCspim.
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 pcspim 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.
  3. To load a register such as $t0 with the value 0xffff0000 (recall "0x" prefix means hexadecimal), do not use "lui $t0,-1".  A correct implementation would be "lui $t0,0xffff".