Search code examples
fpgaxilinxzynq

Zynq7 / Zedboard: Xil_in32 alters data when reading from DRAM


I have a Zedboard with the following setup in the PL (FPGA):

Custom AXI (full) master -> Interconnect -> Zynq_PS (HP0 slave port)

  • The custom AXI master produces data (simple counter, written to DRAM, starting at 0x00000000).
  • The data are written to DRAM (according to XMD console -> mrd 0x00000000 10)
  • When the PS wants to read the data (main.c -> calls "Xil_in32(0x00000000)") the data is altered !!!

Question: Is calling the function Xil_in32 (for reading data from DRAM) altering the data itself in certain situations ? (when and why ?)

The data are not altered unless Xil_in32 is called. This is proved by reading data from XMD console before calling Xil_in32 from main.c

C-code:

#include <stdio.h>
#include "platform.h"
#include <unistd.h>

#include "xparameters.h"
#include "xil_io.h"
#include "xstatus.h"
#include "xscugic.h"
#include "xil_exception.h"

#include "ps7_init.h"

#define PARAM_BASE_ADDRESS               0x00000000

int main()
{
    // initialization
    init_platform();
    //ps7_init();
    ps7_post_config();

    // variables
    u32 offset;
    u32 param;
    int i = 0;
    xil_printf(" PL WRITING & PS READING DRAM MEMORY TEST ");

    // loop
    while ( 1 ) {

        getchar();

        offset = 0X00000000;
        for (i = 0; i < 50 ; i++){
            offset = offset + 4;
            param = Xil_In32(PARAM_BASE_ADDRESS + offset);
            xil_printf("mem_read %d : %x \n\r",i , param);
        }
    }

    cleanup_platform();
    return 0;
}

XMD reading data: This shows where I have stopped reading the memory, the counter then continues:

  C8:   7252E9D5
  CC:   D7387D6F
  D0:   1E998873
  D4:   5DD8305F
  D8:   C4FEC147
  DC:   347EBE2F <------ last memory read by Xil_in32
  E0:   0000003F <------ counter
  E4:   00000040 
  E8:   00000041
  EC:   00000042
  F0:   00000043
  F4:   00000044
  F8:   00000045
  FC:   00000046
 100:   00000047
 104:   00000048
 108:   00000049
 10C:   0000004A

Solution

  • SOLUTION 1)

    disabling caches, by running either cleanup_platform(), or the disable_caches(); (defined in platform.c) solves the problem of altering data.

    QUESTIONS:

    2) What disabling caches mean for practical application ? Everything is directly taken/written to DRAM ?

    3) Is there any workaround, so that only part of memory is read/written directly ? (Not using caches seems terribly inefficient when the ARM is calculating something, therefore I would like to avoid it)

    SOLUTION 2)

    flush the cache before reading the data from DRAM by calling Xil_DCacheFlushRange(PARAM_BASE_ADDRESS, 4*1); (defined in xil_cache.c)

    #include <stdio.h>
    #include "platform.h"
    #include <unistd.h>
    
    #include "xparameters.h"
    #include "xil_io.h"
    #include "xstatus.h"
    #include "xscugic.h"
    #include "xil_exception.h"
    
    #include "ps7_init.h"
    #include "xil_cache.h"
    
    #define PARAM_BASE_ADDRESS               0x00000000
    
    int main()
    {
        // initialization
        init_platform();
        //ps7_init();
        ps7_post_config();
        // cleanup_platform();                                  // DISABLING CACHES
    
    
        // variables
        u32 offset;
        u32 param;
        int i = 0;
        xil_printf(" PL WRITING & PS READING DRAM MEMORY TEST ");
    
        // loop
        while ( 1 ) {
    
            getchar();
    
            Xil_DCacheFlushRange(PARAM_BASE_ADDRESS, 4*1);      // CACHE FLUSHING
            offset = 0X00000000;
            for (i = 0; i < 50 ; i++){                          // LOOP FOR READING DATA
                param = Xil_In32(PARAM_BASE_ADDRESS + offset);
                xil_printf("mem_read %d : %x \n\r",i , param);
                offset = offset + 4;
            }
        }
    
        cleanup_platform();
        return 0;
    }