ARM project: Week 4
Reading the mouse from the ARM

ARM project home | Tasks (weeks): 1 | 2 | 3 | 4

This week concludes the project, so it's time to learn a bit about hardware/software codesign! Your task is to interface and access the mouse from the ARM. You will be writing a small program for the ARM as well as reusing and modifying some of the Verilog you have written previously. The work is split into two jobs to help you build up the hardware and software in stages.

Job 1 (ARM writing to FLEX)

Your first job is to interface the ARM to the 7-segment LEDs controlled by the FLEX. This will be used in job 2 to display mouse data, but for this job you could just display an incrementing number. The FLEX chip has been allocated a chunk of the ARM's address space and so it needs to act like an memory device to allow the ARM to write data to it. In job 2 the FLEX will also allow the ARM to read data from it.

You need to write some Verilog code for the FLEX to latch data written by the ARM, decode the data (using the HexToLEDs module you know and love) and output the hex digits on the LEDs.

To make the FLEX respond to write requests from the ARM, you will need to:

Pin definitions for the FLEX chip are in week4.acf. To get you started with your Verilog code, below is a suitable header including the mouse interface and data output bits needed for job 2 (which you can ignore for now) and the tristate buffer for nWAIT mentioned above:

module week4(ledA, ledB, mdata, mclk, d, a, XCLK, nCE2, nOE, nWE, INT4, nWAIT);

  output [7:0] ledA, ledB;           // 8-bit outputs to LEDs
  inout  mdata, mclk;                // mouse serial interface
  inout  [7:0] d;                    // bidirectional data bus
  input  [7:0] a;                    // address bus
  input  XCLK, nCE2, nOE, nWE;       // clock and memory bus control
  output INT4;                       // interrupt 4 line
  inout  nWAIT;                      // bidirectional memory timing control

  TRI    tbuf_for_nWAIT(1,0,nWAIT);  // make nWAIT tristate
  wire   [7:0] data_out=0;           // zero data output to ARM for now
  wire   enable_data_out=0;          // don't output data to ARM for now
  TRI    tbuf_for_D0(data_out[0],enable_data_out,d[0]);
  TRI    tbuf_for_D1(data_out[1],enable_data_out,d[1]);
  TRI    tbuf_for_D2(data_out[2],enable_data_out,d[2]);
  TRI    tbuf_for_D3(data_out[3],enable_data_out,d[3]);
  TRI    tbuf_for_D4(data_out[4],enable_data_out,d[4]);
  TRI    tbuf_for_D5(data_out[5],enable_data_out,d[5]);
  TRI    tbuf_for_D6(data_out[6],enable_data_out,d[6]);
  TRI    tbuf_for_D7(data_out[7],enable_data_out,d[7]);
  assign INT4=0;                     // disable interrupts for now
  assign mdata=1'bz;                 // don't use mouse data for now (tristate)
  assign mclk=1'bz;                  // don't use mouse clock for now (tristate)

Write an accompanying piece of ARM assembler to write values to the LEDs. The ARM to FLEX data bus is just 8-bits wide so use the strb instruction to store a byte to the FLEX since a str instruction will result in 4 bytes being written. The FLEX chip is memory mapped onto the ARMs memory map over the area 0x08000000 to 0x0bffffff. Since the FLEX is only fed the first 8 address lines, only addresses 0x08000000 to 0x080000ff are useful, the higher addresses mapping onto the lower ones (e.g. 0x08000103 looks the same as 0x08000003 to the FLEX).

For more detail on the interface between the FLEX and the ARM, see memo 21.

Job 2 (Bringing it all together)

The task for this week, and in fact for the whole project, is to interface the mouse to the ARM in such a way that pressing either mouse button causes the ARM to print the current "position" of the mouse in the debugger. The position should be an (X, Y) pair where X and Y are both signed 16 bit numbers. The lower 8 bits of the X value should be written back from the ARM to the 7-segment LEDs of the FLEX when a mouse button is pressed. If both mouse buttons are pressed simultaneously then the program should terminate. To aid testing, pressing button 1 of the FLEX should reset the mouse position to (0,0).

To do this you will need:

The program should only print the X and Y values when the buttons are first pressed, not while they are held down.

To allow the ARM to read data from the FLEX, you will need to:

	assign enable_data_out = !nOE && (your equations here);

Note that the ARM is configured to treat this bus as 8 bits wide so if you use ldr to load a 32 bit word the ARM will do four 8 bit reads on your behalf.

Hint: to multiplex a set of buses together you can use the `?' operator multiple times, e.g.:

        assign data_out = (select_bus == 2'd0) ? bus0 :
                          (select_bus == 2'd1) ? bus1 :
                          (select_bus == 2'd2) ? bus2 : bus3;


To avoid confusion and misunderstanding over the requirements, let me point out some obvious things to which you should nevertheless pay attention.

Question 1

W4-Q1: The X and Y values are 16-bit wide, but the ARM accesses them over an 8-bit bus. Is there any risk of a race condition? Discuss. Then, either propose a fix or prove that there is no danger.

Question 2

W4-Q2: You have used memory-mapped I/O. Imagine you needed to talk to 5 different peripherals from your microprocessor. Would there be any advantage in mapping these 5 I/O ports to a pattern of addresses such as, say,


as opposed to the more obvious pattern of


? Explain.

Weekly mini-report

Submit the following to one of the demonstrators before the end of the last session of this week on Thursday morning.

  1. Your Verilog and ARM code for job 2 must be cleanly formatted and commented. Don't submit the code for job 1.
  2. The Verilog code must be strictly synchronous with all clocks coming from one of the two clock distribution networks. Derived clocks which are distributed over programmable wiring are dangerous because clock skew can vary widely.
  3. You must give a live demonstration of your solution. Remember that this week's demo is worth an extra 5 marks, since it sums up the whole project.
  4. You must make good use of modular decomposition to ensure that no module (whether hardware or software) is too complex.
  5. Answers to the two questions for this week must be added to the end of your code.
  6. The following header must be added to all code submitted:
    // ARM Project - Week 4
    // Your name
    // Your college
    // date
  7. Complete one of the supplied cover sheets and prepend it to the listing.
Please don't leave this to the last moment: expect queues for the demonstrators' attention during the last hour, and remember that the laboratory is booked by another course from 13:00 onwards. The penalty for not submitting by Thursday is 3 marks per weekday.

Final report

Submit it to the Teaching Office before 17:00 on Friday 7th June (hard deadline!). Please adopt the following format, which guarantees that you will not use more than 10 sides of A4. (If you use only 6 it's still fine, but anything below that is probably going to be a bit too thin for full marks.)

  1. Introduction (up to 1 page).
  2. Individual descriptions of the 4 weekly tasks, highlighting the major challenges you found in each (up to 4 pages in total).
  3. The final design, without having to repeat the stuff in the previous section but highlighting any important features and design decisions (up to 1 page).
  4. Debugging methodologies (for both Verilog and ARM) you adopted and found useful (up to 2 pages).
  5. Commented list of problems encountered and lessons learned. For items previously covered, mentioning the issue and referencing the relevant section is sufficient (up to 1 page).
  6. Conclusions (up to 1 page).
  7. Appendix: your weekly mini-reports and their cover sheets (only the first three, since the last one will not have been returned to you yet).
  8. Complete the last of your supplied cover sheets and prepend it to the report.