CST 331 Lab 3 -- EBI Introduction Lab

Replace the values of the following two config pragmas with the indicated values so that the system clock will run at 96 MHz.  Also leave the PBCLK8 divider at its default value of 2. This will mean that the EBI is clocked at 48MHz.

#pragma config FPLLMULT = MUL_64  // System PLL Multiplier (PLL Multiply by 64) FVco = 6MHz * 64 = 384MHz (350 < FVco < 700)
#pragma config FPLLODIV = DIV_4   // System PLL Output Clock Divider (4x Divider) 384MHz / 4 = 96 MHz

Use the following EBI setup code which was presented in class and is based on Example 47-5 from the reference manual. Note that SRAM_ADDR_CS0 has been changed to 0xE0000000 so that the cache does not interfere with EBI accesses.

// Global Defines
#define SRAM_ADDR_CS0 0xE0000000
#define MyEBIuint (*(unsigned int*) 0xE0000000)
#define RAM_SIZE 2*1024*1024
#include <stdint.h>

int main(void){

    unsigned int * myptr = (unsigned int *)SRAM_ADDR_CS0;
    unsigned int myread, mywrite =
0xA5A5BDBD;

    // Enable address lines [0:19]

    CFGEBIA = 0x800FFFFF;   

    CFGEBIC = _CFGEBIC_EBIWEEN_MASK |
              _CFGEBIC_EBIOEEN_MASK |
              _CFGEBIC_EBIBSEN1_MASK |
              _CFGEBIC_EBIBSEN0_MASK |
              _CFGEBIC_EBICSEN0_MASK |
              _CFGEBIC_EBIDEN1_MASK |
              _CFGEBIC_EBIDEN0_MASK;

    //Set CS0 to base physical address 0z20000000
    EBICS0 = 0x20000000;     

    EBIMSK0 = ((6 << _EBIMSK0_MEMSIZE_POSITION) &
                     _EBIMSK0_MEMSIZE_MASK) |
              // 2^(6+15) = 2^21 = 2MB
              ((1 << _EBIMSK0_MEMTYPE_POSITION) &
                     _EBIMSK0_MEMTYPE_MASK) |
              // 1 = SRAM
              ((0 << _EBIMSK0_REGSEL_POSITION) &
                     _EBIMSK0_REGSEL_MASK);
              // Use Timing Reg set 0    

    EBISMT0 = ((10 << _EBISMT0_TRC_POSITION) &
                      _EBISMT0_TRC_MASK) |
              (( 3 << _EBISMT0_TAS_POSITION) &
                      _EBISMT0_TAS_MASK) |
              (( 1 << _EBISMT0_TWR_POSITION) &
                      _EBISMT0_TWR_MASK) |
              ((10 << _EBISMT0_TWP_POSITION) &
                      _EBISMT0_TWP_MASK);
    // TBTA, TPRC, PAGEMODE, PAGESIZE and
    // RDYMODE bits all 0

    //Keep default data width to 16-bits
    EBISMCON = 0x00000000;

    while(1) {

        // Your code entered here

        asm volatile("nop"); // for a breakpoint
    }
}

You will add code to do individual reads and writes targeting the EBI memory as required in the steps below. Set up the logic analyzer, in order to observe the EBI bus cycles that are produced. You will need to observe at least CS0, EBIA1, EBIA0, BS1, BS0, OE, and WE.  Please make sure that exactly these labels appear on the logic analyzer screens!

Note: This lab can be done on a uP1 board with the HMZ144 so long as there is no LCD mounted on the uP1 board, and there is no keypad connected (since these devices are connected to pins that the EBI will use). Otherwise it will need to be done on a uP2 board.
The uP1 board also uses EBIA23/RH15 and EBIRDY2/RH11 (an input for the EBI) for board LEDs. Also, EBIRP/RH2 is connected to the HMZ144 board LED, and EBICS1 is connected to the SD card unit on the HMZ144, and EBIRDY1 (an input for the EBI) is connected to a pin in the HMZ144 UEXT 10 pin connector. But these pins are not needed in this lab. Be careful not to enable them if you are using a uP1 board.  In general don't enable any pins that are not strictly necessary.

Also note that there actually isn't any memory added to the EBI bus yet (on either a uP1 or uP2), so the data returned by a read will just be whatever the data bus happens to float to. It can be helpful for future labs to note what value(s) the bus usually floats to.  Note that it can take a long time for a driven bus to return to its floating level, so reading from the bus relatively soon after writing to it will likely return the same value.

1) Add the following code to do a 32 bit write to and a 32-bit read from the EBI memory, both operations at address 0xE0000000 (note the #define for MyEBIuint in the code above).
MyEBIuint = 0xA5A5BDBD;
myread = MyEBIuint;

Remember that since the example initialization code sets up CS0 for a 16-bit bus width, 32-bit operations will be implemented via two 16-bit cycles. Obtain and print out black on white background logic analyzer screen shots for these (you may be able to get both the read and a write in one screen shot). Try to get the position and zoom set so that the read and/or write fill the screen shot. 
i) In this step, what processor address bits will be placed on EBIA1 and EBIA0? (Note that it is not processor address bits A1 and A0.  If you are unsure what is going on, review the class lecture material or homework assignment, or redo this exercise at address 0xE0000004, or talk to the professor.)
ii) Indicate, by making notes on the printout(s), which operation is the read, which is the write, and what processor address was targeted in each case and whether the more or less significant half of the 32-bit word is being read or written in each 16-bit cycle. Do this by indicating the processor A1, A0 value associated with the LSByte of each half word. That is, say "this 16-bit cycle reads the half word at processor A1, A0 = ...", etc. Make sure to report the processor address A1 and A0, not the EBIA1 and EBIA0 values.


2) Verify the timing values chosen in the sample code by doing the following:
a) What values were chosen for timing for each of tRC, tAS, tWP and tWR in the EBISMT0 setting? Give your answer in terms of PBCLK8 cycles, not the encoded values for each bit field.
b) How much time in ns was actually used for tRC, tAS, tWP and tWR in your read and write cycles?
i) Mark the time spans covered by tRC, tAS, tWP and tWR on your printouts. Note the scale used on each logic analyzer printout.
ii) List the times that were obtained for each of these parameters using the logic analyzer.
c) One question we had when we went through the EBI documentation was whether SYSCLK or PBCLK8 would be used for EBI timing. With the information you collected, determine for certain which clock is being used. Justify your answer by showing your work.

3) Make sure that the 32 bit read cycle follows the 32 bit write cycle as closely as is possible in C. Measure the time between the end of the write cycle and the start of the read cycle using the current timing settings. (Don't forget to account for tWR in this case .)  Obtain a screenshot of this time if you haven't done so already. Then, change the timing setup in EBISMT0 so that tBTA now has a value of 7 rather than the 0 it had originally.  Again, measure the time between the write and read cycles.  Did increasing tBTA increase the time between the two 32 bit cycles?  Don't forget to account for tWR! If it doesn't increase the time between the two cycles, demonstrate this fact to the professor.  Obtain a screen shot showing the increased time. How much time did setting tBTA to 7 add to the time between the cycles?  Does it appear that the two cycles in the screenshot obtained before increasing tBTA were back to back? [You might have to try replacing the C code doing the write and read with the following inline assembly: asm("lui $at, 0xE000; sw  $at, 4($at); lw  $0, 0($at)"); and redoing the two screenshots (one with tBTA 0 and one with it at 7)].  Also, check the two screen shots to see if setting tBTA to 7 changed the timing between the two 16 bit write cycles making up the 32 bit write and between the two 16 bit read cycles making up the 32 bit read. Why shouldn't you expect to see tBTA make any changes to the timing between the two 16-bit reads, or the two 16-bit writes?  Did it?

4) Change the bus width to 8-bit (the sample code was set for a 16-bit width) and repeat part 1 above, including the analyzer screen shot printouts.  (If the screenshots don't look different you probably haven't switched to 8-bit mode!)   Indicate on the printout(s) which operation is the read, which is the write, and what address was targeted in each case and which byte of the 32-bit word is being read or written in each 8-bit cycle.  Do this by indicating the processor A1, A0 value associated with each byte. That is, say "this 8-bit cycle reads the byte at (processor address bits) A1, A0 = ...", etc.  How does the EBI treat processor address bits A0 and A1 differently for the 8 bit bus width compared to the 16 bit bus width?

5) Set back to a 16-bit bus width. We can use the following inline assembly to exercise the bus using lwr and swr instructions:
asm("lwr %0, 0xE0000001":"=r"(myread));
asm("swr %0, 0xE0000001"::"r"(mywrite));
Note that these are each pseudo/macro instructions which will be implemented as an lui for the address followed by the lwr or swr respectively.  Thus the lwr and swr will not be executed back to back.  Also note that the lwr and swr will only need to read/write the 3 bytes of memory starting at 0xE0000001 through 0xE0000003 (bytes B C and D in the following table).

  A1 A0:
 11
 10
 01
 00

B C
D


Predict what 16-bit bus cycles will be needed in order to implement each of these operations.  Give diagrams showing what you will expect to see on the logic analyzer before you actually observe them on the logic analyzer. (Include all the signals connected to the logic analyzer in your diagrams).  Then, run the experiment and obtain printouts of  logic analyzer screenshots showing these operations.  Indicate on the printout(s) which operation is the read, which is the write, and which byte or bytes of the 3 byte quantity is being read or written in each 16-bit cycle.  Do this by indicating the processor A1, A0 value associated with each byte.  What inconsistency or unexpected finding do you observe?

6) Change the bus width to 8-bit and setup to test and observe pagemode accesses with a page size of 4.  Choose a tPRC setting smaller that tRC.  Read a 32-bit quantity and obtain a printout of a logic analyzer screen shot showing the operation.  Label the printout showing the tRC times and the tPRC times. Also indicate on the printout what your tPRC and tRC (in PBCLK8 cycles) settings were.

7) In some systems, for a pagemode access to be started requires that the first access be at EBIA1, EBIA0 = 00 (A1, A0 in 8-bit mode).  Still in 8-bit mode, use a lwr instruction to determine if a pagemode access will be started if the first access is at processor address A1, A0 = 01, and if a pagemode access will be started if the first access is at processor address A1, A0 = 10.   Record your conclusions and appropriately labeled logic analyzer screenshots showing your results in each of these two cases.  Report what lwr instruction was used in each screenshotAlso, one of your observations should confirm the inconsistency you found in part 5.  Describe this and say what you think is happening.


For your report, turn in labeled printouts of screen shots and your answers to any questions posed above as a pdf file in Canvas..