How to interface with two 16-bit Flash parts working as a single 32-bit Flash in EDK 12.1 using XPS MCH EMC

From steamWiki
Jump to: navigation, search

This guide will explain how to setup an EDK 12.1 project to interface with two 16-bit Atmel (AT49BV322D, AT49BV322DT, AT49BV322A, AT49BV322AT) Flash Memory parts organized in parallel acting as a single 32-bit Flash Memory using the Xilinx XPS_MCH_EMC IP Core. The following image shows the Schematics for this design.

Parallel 16-bit Flash Schematics.png

Tweaking of the XPS_MCH_EMC Properties is necessary because this Flash Configuration is addressed like a 16-bit Flash but data is read & written like a 32-bit Flash. By default, the XPS_MCH_EMC is not setup to handle this situation. The XPS_MCH_EMC is designed not to allow a user to write to a none word width boundary. That is to say, each address location specifies 8 bits of data. Each time the lowest bit of the address is incremented the internal Flash pointer shifts ahead by 8 bits. If we use an 8-bit word the XPS_MCH_EMC lets us write to any location. If we use a 16-bit word we can write to every other address location (we cannot write a 1 to the bottom most bit). If we use a 32-bit word we can write to every 4th address location (we cannot write a 1 to the bottom 2 bits). Here in lies the problem because our Flash architecture (using 2 16-bit Flash parts with their data bits in parallel) is addressed like a 16-bit data word but is, in fact, a 32-bit data word. We must trick the XPS_MCH_EMC into thinking we are using a 32-bit data word. This crux of the solution is to ignore the least 2 significant bits of the Address. This is possible because the XPS_MCH_EMC supports a 32-bit address but we only need 21 bits of address. When we shift left by 2 we align any address we write onto a 32-bit boundary. We then, simply, ignore the bottom 2 bits.

Though this guide has been written from experimentation with EDK 12.1, the procedures should be extremely similar to for earlier version of EDK.



  1. Create a standard EDK project.
  2. Add an XPS_MCH_EMC Core. In this case, I have named it Flash_Mem.
    1. Open the Properties sheet, navigate to the User tab and ensure that the Common properties match those shown below.
      Xps mch emc-prop-user-common.png
    2. Now ensure that the Bank 0 properties match those shown below.
      Xps mch emc-prop-user-bank0.png
    3. Leave all other Properties as they are. Most are ignored.
  3. Add a UTIL_BUS_SPLIT Core. In this case I have named it Flash_A_Bus_Split. Ensure that the properties match those shown below.
    Util bus split-prop-user-all.png
  4. Add an XPS_GPIO Core. In this case I have called it Flash_Rdy.
    1. Open the Properties sheet, navigate to the User tab and ensure that the Common properties match those shown below.
      Xps gpio-prop-user-common.png
    2. Now ensure that the Channel 1 properties match those shown below.
      Xps gpio-prop-user-channel1.png
  5. Create the following External Ports
    1. Flash_RPN_pin, O
    2. Flash_CEN_pin, O
    3. Flash_OEN_pin, O
    4. Flash_WEN_pin, O
    5. Flash_DQ_pin, IO, [0:31]
    6. Flash_A_pin, O, [0:20]
    7. Flash_Rdy_pin, I
  6. Create the following connections between the 3 Cores & External Ports we just created.
    1. Connect Flash_Mem/Mem_A to Flash_A_Bus_Split/Sig
    2. Connect Flash_Mem/Mem_RPN to External Ports/Flash_RPN_pin
    3. Connect Flash_Mem/Mem_CEN to External Ports/Flash_CEN_pin
    4. Connect Flash_Mem/Mem_OEN to External Ports/Flash_OEN_pin
    5. Connect Flash_Mem/Mem_WEN to External Ports/Flash_WEN_pin
    6. Connect Flash_Mem/Mem_DQ to External Ports/Flash_DQ_pin
    7. Connect Flash_Rdy/GPIO_IO_I to External Ports/Flash_Rdy_pin
    8. Connect Flash_A_Bus_Split/Out1 to External Ports/Flash_A_pin
    • The following image shows all of the connections between the External Ports, Flash_Mem (XPS_MCH_EMC), Flash_Rdy (UTIL_BUS_SPLIT), & Flash_Rdy (XPS_GPIO).
    32-bit Flash Example Ports.png
  7. In the Addresses tab, ensure that the Flash_Mem Size is set to 8M.
  8. The UCF file should include the following entries (your LOC values will be different).
    • Note that the DQ pins are in reverse order when compared to the Atmel Flash datasheet. This must be done to overcome a Big Endian/Little Endian inconsistency between the Xilinx XPS_MCH_EMC and the Atmel Flash part. In this case, flash_DQ_pin<0 - 15> represents the "1st" flash part and flash_DQ_pin<16 - 31> represents teh "2nd" flash part.
    • Note that the A pins are also in reverse order to overcome a Big Endian/Little Endian inconsistency.
    Net flash_DQ_pin<31> LOC=F24;
    Net flash_DQ_pin<30> LOC=F25;
    Net flash_DQ_pin<29> LOC=L17;
    Net flash_DQ_pin<28> LOC=L18;
    Net flash_DQ_pin<27> LOC=F23;
    Net flash_DQ_pin<26> LOC=E24;
    Net flash_DQ_pin<25> LOC=K18;
    Net flash_DQ_pin<24> LOC=K19;
    Net flash_DQ_pin<23> LOC=G22;
    Net flash_DQ_pin<22> LOC=F22;
    Net flash_DQ_pin<21> LOC=J20;
    Net flash_DQ_pin<20> LOC=J19;
    Net flash_DQ_pin<19> LOC=D26;
    Net flash_DQ_pin<18> LOC=E26;
    Net flash_DQ_pin<17> LOC=D24;
    Net flash_DQ_pin<16> LOC=D25;
    Net flash_DQ_pin<15> LOC=K26;
    Net flash_DQ_pin<14> LOC=K25;
    Net flash_DQ_pin<13> LOC=M22;
    Net flash_DQ_pin<12> LOC=M21;
    Net flash_DQ_pin<11> LOC=K22;
    Net flash_DQ_pin<10> LOC=K23;
    Net flash_DQ_pin<9> LOC=M18;
    Net flash_DQ_pin<8> LOC=M19;
    Net flash_DQ_pin<7> LOC=J22;
    Net flash_DQ_pin<6> LOC=J23;
    Net flash_DQ_pin<5> LOC=K21;
    Net flash_DQ_pin<4> LOC=L22;
    Net flash_DQ_pin<3> LOC=G24;
    Net flash_DQ_pin<2> LOC=G23;
    Net flash_DQ_pin<1> LOC=K20;
    Net flash_DQ_pin<0> LOC=L20;
    Net flash_A_pin<20> LOC=U20;
    Net flash_A_pin<19> LOC=V21;
    Net flash_A_pin<18> LOC=AA25;
    Net flash_A_pin<17> LOC=AA24;
    Net flash_A_pin<16> LOC=U18;
    Net flash_A_pin<15> LOC=U19;
    Net flash_A_pin<14> LOC=Y23;
    Net flash_A_pin<13> LOC=Y22;
    Net flash_A_pin<12> LOC=T20;
    Net flash_A_pin<11> LOC=U21;
    Net flash_A_pin<10> LOC=Y25;
    Net flash_A_pin<9> LOC=Y24;
    Net flash_A_pin<8> LOC=T17;
    Net flash_A_pin<7> LOC=T18;
    Net flash_A_pin<6> LOC=V22;
    Net flash_A_pin<5> LOC=W23;
    Net flash_A_pin<4> LOC=V25;
    Net flash_A_pin<3> LOC=V24;
    Net flash_A_pin<2> LOC=U22;
    Net flash_A_pin<1> LOC=V23;
    Net flash_A_pin<0> LOC=R20;
    Net flash_WEN_pin LOC=U23;
    Net flash_OEN_pin LOC=U24;
    Net flash_CEN_pin LOC=R19;
    Net flash_RPN_pin LOC=N21;
    Net flash_Rdy_pin LOC=P22;
  9. In your C code, when writing to the Flash memory the Address must be Left-Shifted 2 bits. Therefore your write data call should look something like this
    • FLASH_ADDR is a pointer to the base address of the XPS_EMC_MCH.
    • ui_waddr is the write address and is an Xuint32.
    • ui_wdata is the write data and is an Xuint32.
    XGpio_WriteReg(FLASH_ADDR, ui_waddr << 2, us_wdata);;
  10. When reading from the Flash memory, the Address must again be Left-Shifted by 2 bits. Your read data call should look something like this
    • FLASH_ADDR is a pointer to the base address of the XPS_EMC_MCH.
    • ui_raddr is the write address and is an Xuint32.
    XGpio_ReadReg(FLASH_ADDR, ui_raddr << 2)