In this lab, you will gain experience writing assembly-language programs and interacting with I/O devices. This assignment is to be done individually.
Each person will write a device driver and test program for one of the following I/O devices: speaker, microphone, PS/2 keyboard, USB mouse, touchscreen, LCD display, VGA monitor, SD card, camera, serial send, serial receive. Each member of your team should choose a different I/O device. I recommend one member write the device driver for the serial send controller, because you can use this as console to help debug future programs.
This handout also provides information about other I/O devices (SDRAM, real-time clock, Fast Fourier Transform co-processor, PWM, SPI), but these should not be chosen for this lab.
You should develop and debug your device driver and program initially on ase100. You should then run your device driver and program on a hardware E100 processor, which you will create by adding I/O controllers to your E100 processor.
E100 programs communicate with I/O devices by reading and writing to variables provided by those devices. These variables are called device registers. Each device register is assigned a memory address, and E100 programs read and write a device register via normal instructions (e.g., cp, bne) to its assigned address. This method for accessing I/O device registers is called memory-mapped device registers.
Some device registers can be read to determine their current value; for example, cp switch 0x80000000 reads the current value of SW[17:0]. Other device registers may be written to change their value; for example, cp 0x80000001 tmp writes the value of tmp to LED_RED[17:0].
The following table lists the I/O devices available for the E100, along with the addresses (in hexadecimal) assigned to each device registers and whether the register can be read or written. The links in the right column of the table provide detailed information about the behavior of each device and the test program that you should write for that device.
|0x80000000||read||bits 17-0: SW[17:0]||binary input|
|0x80000001||write||bits 17-0: LED_RED[17:0]||binary output|
|0x80000002||write||bits 7-0: LED_GREEN[7:0]||binary output|
|0x80000003||write||bits 15-0: HEX3-HEX0||hexadecimal output|
|0x80000004||write||bits 15-0: HEX7-HEX4||hexadecimal output|
|0x80000005||read||bits 31-0: real-time clock||measure time|
|0x80000010||write||bit 0: lcd_command||LCD display|
|0x80000011||read||bit 0: lcd_response|
|0x80000012||write||bits 3-0: lcd_x[3:0]|
|0x80000013||write||bit 0: lcd_y|
|0x80000014||write||bits 7-0: lcd_ascii[7:0]|
|0x80000020||write||bit 0: ps2_command||PS/2 keyboard|
|0x80000021||read||bit 0: ps2_response|
|0x80000022||read||bit 0: ps2_pressed|
|0x80000023||read||bits 7-0: ps2_ascii[7:0]|
|0x80000030||write||bit 0: sdram_command||SDRAM memory|
|0x80000031||read||bit 0: sdram_response|
|0x80000032||write||bit 0: sdram_write|
|0x80000033||write||bits 24-0: sdram_address[24:0]|
|0x80000034||write||bits 31-0: sdram_data_write|
|0x80000035||read||bits 31-0: sdram_data_read|
|0x80000040||write||bit 0: speaker_command||speaker|
|0x80000041||read||bit 0: speaker_response|
|0x80000042||write||bits 31-0: speaker_sample|
|0x80000050||write||bit 0: microphone_command||microphone|
|0x80000051||read||bit 0: microphone_response|
|0x80000052||read||bits 31-0: microphone_sample|
|0x80000060||write||bit 0: vga_command||VGA monitor|
|0x80000061||read||bit 0: vga_response|
|0x80000062||write||bit 0: vga_write|
|0x80000063||write||bits 9-0: vga_x1[9:0]|
|0x80000064||write||bits 9-0: vga_y1[9:0]|
|0x80000065||write||bits 9-0: vga_x2[9:0]|
|0x80000066||write||bits 9-0: vga_y2[9:0]|
|0x80000067||write||bits 23-0: vga_color_write[23:0]|
|0x80000068||read||bits 23-0: vga_color_read[23:0]|
|0x80000070||write||bit 0: mouse_command||USB mouse|
|0x80000071||read||bit 0: mouse_response|
|0x80000072||read||bits 31-0: mouse_deltax|
|0x80000073||read||bits 31-0: mouse_deltay|
|0x80000074||read||bit 0: mouse_button1|
|0x80000075||read||bit 0: mouse_button2|
|0x80000076||read||bit 0: mouse_button3|
|0x80000080||write||bit 0: sd_command||SD card|
|0x80000081||read||bit 0: sd_response|
|0x80000082||write||bits 0: sd_write|
|0x80000083||write||bits 29-0: sd_address[29:0]|
|0x80000084||write||bits 31-0: sd_data_write|
|0x80000085||read||bits 31-0: sd_data_read|
|0x80000090||write||bit 0: serial_receive_command||
(wired and wireless)
|0x80000091||read||bit 0: serial_receive_response|
|0x80000092||read||bits 7-0: serial_receive_data[7:0]|
|0x800000a0||write||bit 0: serial_send_command|
|0x800000a1||read||bit 0: serial_send_response|
|0x800000a2||write||bits 7-0: serial_send_data[7:0]|
|0x800000b0||write||bit 0: camera_command||camera|
|0x800000b1||read||bit 0: camera_response|
|0x800000b2||write||bits 9-0: camera_x[9:0]|
|0x800000b3||write||bits 9-0: camera_y[9:0]|
|0x800000b4||write||bits 1-0: camera_scale[1:0]|
|0x800000b5||write||bit 0: camera_mirror|
|0x800000c0||write||bit 0: fft_send_command||Fast Fourier Transform|
|0x800000c1||read||bit 0: fft_send_response|
|0x800000c2||write||bits 31-0: fft_send_real|
|0x800000c3||write||bits 31-0: fft_send_imaginary|
|0x800000c4||write||bits 0: fft_send_inverse|
|0x800000c5||write||bit 0: fft_send_end|
|0x800000d0||write||bit 0: fft_receive_command|
|0x800000d1||read||bit 0: fft_receive_response|
|0x800000d2||read||bits 31-0: fft_receive_real|
|0x800000d3||read||bits 31-0: fft_receive_imaginary|
|0x800000e0||write||bit 0: touch_command||touchscreen|
|0x800000e1||read||bit 0: touch_response|
|0x800000e2||read||bits 9-0: touch_x|
|0x800000e3||read||bits 8-0: touch_y|
|0x800000e4||read||bit 0: touch_pressed|
|0x800000f0||write||bit 0: pwm_command||PWM|
|0x800000f1||read||bit 0: pwm_response|
|0x800000f2||write||bits 31-0: pwm_period|
|0x800000f3||write||bits 31-0: pwm_high|
|0x80000100||write||bit 0: spi_command||SPI|
|0x80000101||read||bit 0: spi_response|
|0x80000102||write||bits 7-0: spi_send_data|
|0x80000103||read||bits 7-0: spi_receive_data|
At first glance, it seems easy to send data to/from an I/O device. For example, one could send a sample to the speaker simply by copying data to the speaker_sample device register. However, this is not quite enough to send a sequence of values. One problem is that the speaker controller doesn't know when the program has sent the next value to the speaker_sample device register. Another problem is that the program doesn't know when the speaker controller has read the last sample and is ready to receive the next sample. These problems are addressed by an I/O device protocol.
A protocol is used to guide the interaction between two parties. In the context of I/O devices, an I/O protocol is used to guide the interaction between an E100 program and an I/O device. A protocol defines the steps involved in the interaction and includes how each party knows when the current step is complete. We will use a protocol to send commands to an I/O device and receive the response from that device.
The part of an E100 program that implements the E100's side of an I/O protocol is called a device driver.
The I/O protocol uses four types of signals to allow an E100 program to send commands to a device and receive the response from that device.
The steps involved in sending data to an output device are:
|0||0||System is idle.|
|1||0||E100 program sets the command parameters to describe the desired command, then sets command to 1 to ask the device to execute the command. After setting command to 1, the E100 program waits for device to execute the command.|
|1||1||After the device executes the command, it sets the response parameters for the command, then sets response to 1 to tell the E100 program that it has executed the command and is sending back the response. After setting response to 1, the device waits for the E100 program to set command to 0.|
|0||1||E100 program sets command to 0 to tell the device that the program has seen the device's response. After this state, the device sets response back to 0, and the system returns to the Idle state.|
Your pre-lab assignment is to write, test, and debug your device driver and test program. These tasks can be done by running the E100 assembler and simulator, ase100. Debugging on ase100 is much easier than debugging on the DE2-115 because you can control the execution of your program and view its state as it executes.
Your test program and device drivers should be in separate files. Include the device driver file in your test program by adding a line at the end of your test program, such as:
Most of your testing and debugging should occur before your lab section. The lab section is meant for running final tests on the DE2-115 board and for demonstrating your program to a lab instructor.
One of the surest ways to waste a lot of time when programming is to try to write and test the entire program all at once. This is especially true when you are trying a new task, language, or unfamiliar environment (such as this lab!).
A better way to program is to write and test a little at a time. The less familiar you are with the material, the smaller the piece you should write and test. For example, since you are new to assembly-language programming, you might write a program consisting of a single instruction (plus halt), then run that program and verify that it changed memory and the IAR as you expected.
For this lab, I strongly recommend you first write and test your device driver before you write your full test program. To test your device driver, write a trivial test program that initializes the input parameters (if any), calls the device driver, displays the output parameters (if any) to the hex digits, then halts. After this works, write a second test program that calls your device driver twice (this verifies that the first call to your device driver left things in the right state).
After you verify that your device driver is correct, then write your test program. Again, do this a little at a time. For example, if your test program requires a loop, test one iteration of the loop before running multiple iterations.
Demonstrate your test program and device driver on the DE2-115 to a lab instructor. After you've demonstrated your program, submit the final version of your test program and device driver here.