EE 361 Fall 05

Homework 6

Due: 10/21/05 (fri)

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 Alex Gomera (agomera@hawaii.edu).  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 6 YourName".  Email by October 21, 2005 (fri before class at 12:30pm.

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

The circuit has a 1-bit input port "s", a clock, and a 4-bit output port "y".  The input port "s" receives a string of bits, which is a series of "pulses".  A pulse is a string of 1s preceeded by a 0 and followed by a 0, and its length is the number of 1s, e.g., ....0011110.... is a pulse of length 4.  A "short pulse" is of length 1 or 2, a "medium pulse" is of length 3 or 4, and a "long pulse" is of length 5 or more. 

The circuit has a counter, whose value is output at "y".  When the circuit receives a complete "long pulse" then the counter is cleared to 0, i.e., y = 0.  When the circuit receives a complete "medium pulse" then the counter is incremented by 1.  When the circuit receives a complete "short pulse" then the counter is decremented by 1.

Your verilog module should have the following form:

//EE 361 Homework 7 Problem A, John Doe, October 19, 2004

module Serial(y, clock, s);
output [3:0] y;
input clock;
input s;
.
. fill in here 
.
endmodule

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]  s, // This is connected to the input of the Lights circuit.
reg  clock;        // This will be used to generate a clock signal.
wire [3:0] y;  // 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.

Serial testSerial(y,clock,s);

//  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.

//  Note that a clock period = 2 time units. The testbench drives the
// circuit to clear, increment, increment, decrement, then clear.
//  
initial 
   begin
   s = 0
   #4
   s = 1;
   #16 // pulse of length 8: clear
   s = 0;
   #4
   s = 1;
   #8 // pulse of length 4: increment
s = 0;
#2
s = 1;
#6 // pulse of length 3: increment
s = 0;
#6
s = 1;
#4 // pulse of length 2: decrement
s = 0;
#2
s = 1;
#12 // pulse of length 6: clear
s = 0;
#4
   $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 Serial module as per the instructions above.  Do not turn in your test bench.
Problem B. (2 pts)

Consider the following simple C program hw6.c:

main()
{ printf("Hello world\n");}
After compiling (using mcc) you get the following assembly language code
        .file   1 "hw6.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 download 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_EE361H6B.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".