EE 361 Fall 01: Homework 6

Due: 10/19/01 (friday)

Turn in on paper Problems A-D in class. Turn in Problem E by email to the instructor at sasaki@wiliki.eng.hawaii.edu before class.

Problem A (2 pts) Consider the following numbers: 101011 and 010010.

Problem B (2 pts) Consider the following decimal numbers: +18 and -17.

Problem C (2 pts) Find the 5-bit sums and differences of the following additions and subtractions (if possible) assuming the numbers are twos complement numbers. Indicate when overflow occurs.

  00111
+ 11110
-------

  00010
+ 01110
-------

  00111
- 11110
-------

Problem D (2 pt). Design a verilog module for a 2-bit counter circuit. The circuit has output (Q1,Q0) which is the two-bit state of the counter. The circuit has inputs:

As an alternative, instead of (Q1,Q0), (S1,S0) and (D1,D0), you may use two-bit arrays Q, S, and D.

Turn in your program on paper. However, you should verify that it works using Veriwell, or other simulator.

Note: After designing the counter module, you need some way to test and demonstrate it. Thus, you need a test bench. You may realize a test bench in Verilog by defining another module. The module would look something like this (there may be bugs, so be careful):

module testbench;
reg  [1:0]  testS, testD;
reg  clock;
wire [1:0] q;

// Here we place a counter circuit into our testbench.

Counter testcounter(testD,q,testS,clock);

//  We now place our inputs to the circuit to drive it

//  The following is the 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.

//  Here we drive D and S
initial begin
	D = 2;
	S = 3;
	#4
	S = 1;
	#10
	S = 2;
	#10
	S = 0;
	#6
	end

//  Here you can use "display" and "monitor" to output (probe) the
//  values of the circuit, to see if it works.  I'll leave this to you
//  folks to figure out.  It's not hard after you see the Verilog
//  example in the Bucknell handbook.
.
.
endmodule

module Counter(D,Q,S,CLK);
.
.
.

Problem E. (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 "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.

To turn in your program

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.