Reading from SD – Part 1

It’s been a while since my last post, my apologies for that. Anyways I hope you can find this post useful as me; I used the next information in a project that consisted in perform a grayscale filter to an image using an AXI-Stream IP in the programmable logic part. To do so, I stored the image into the SD then read the raw of the file (which is the data without any compression or file headers) and sent it to the IP using AXI Stream functions at the associated addresses. On this post I am going to show you, how to configure the hardware in order you to do tasks like the mentioned above. So, by the end of this post, you will be able to:


  • Understand how the SD slot is to connect to the Zynq on the Zybo board.
  • Perform the necessary configuration in the Zynq to enable transfer SD to PS.
  • Write a software application which can read and write from/to the SD card, using FATFs library.

Tools and materials:

Main steps:

  • Vivado
    • Create new project
    • Create block design
    • Configure Zynq IP
  • Xilinx SDK
    • Import Xilffs libraries into board support package (BSP)
    • Create new project with the modified BSP
  • Preparing the SD card

Hardware design

Create new project

The hardware part of a project that only involves read or write from/to the SD card is the simplest that I have done. First of all, we have to create our Vivado project named sd_card_reader there won’t be any external files (neither zybo_default.xdc) because this time we won’t need to perform assignations over constraints. So, Figure 1 shows our first step:

Create block design

When you are done creating the project, next step is to create a block design. To do so, look at the left panel in Vivado over IP integrator options group and choose “Create block design,” provide a name like sd_card_reader_hw and immediately upon that perform the next sequence over a blank part in the design, look at Figure 2:

Right-click -> choose the option Add Ip and write Zynq -> choose the IP that is shown.


At the end of that action, you will see, like in Figure 3, the Zynq ready for us to be configured. By the way, don’t forget to perform Run Block Automation to expand DDR and Fixed IO port.

Configure Zynq IP

I am assuming that you must know what we have to do now, but don’t worry I have always said that assuming is not a proper way to explain to others. So, you have to remember that Vivado is not only for Zybo boards instead for all Zynq board families of Xilinx and that means we have to load the default configuration to be sure that settings like Clocks configuration, DDR configuration, and I/O configurations have the proper values. So, must of the time the way we do our project is to load the default configurations and then change them. As a consequence, our previous design will change. To do so, perform the next sequence:

Double-click on Zynq IP, click on “Import XPS Settings,” look for ZYBO_zynq_def.xml file and load it.

NOTE: If you don’t have ZYBO_zynq_def.xml don’t worry is here for you. See Figure 4 to figure out what this is about.


Now that you are done with this, we can move forward to change the default configuration. In general, to change configurations depend on what from the hardware you are planning to use. For instance, in your applications, if you don’t need UART MIO signals then you must uncheck these I/O peripheral options. In conclusion, proper design is one which its configuration fits into the identified necessities.

Having said this, we have to uncheck the peripherals those we don’t need, to do so, choose Peripherals I/0 Pins at the panel on the left side, then on the right side expand I/O Peripheral node. You must be sure to check only SD 0 and UART 1 Peripherals. Furthermore, be sure you that the signal for “CD” (MIO47) is enabled. Although the remaining signals appear disabled, Xilinx SD driver functions are in charge to change them; the “CD” signal is needed for them to be sure that the SD Card is in the slot. Therefore, “CD” signal must be enabled.

The IO Type signal must be set to LVCMOS 1.8V since these are MIO signal, but the SD slot is powered by 3.3V. Therefore, a TI TXS02612 level shifter performs the translation from 1.8V to 3.3V. If you want to read more or want to know where I found this information, this is the link you must look at. To summarize the signal that we are discussing here is a list:

  1. Four signals for data transfer(D0-D3).
  2. One signal for synchronizing clock (Clk).
  3. One signal for command/response (CMD).
  4. One signal to detect whether a card is present in the connector or not (CD).
  5. One signal to read the write protect lock on the card(WP).
  6. One signal for power.
  7. Two signals for ground.

WP signal could be set in MIO 46 or EMIO; you can choose and see the design differences. Figure 5 shows the configurations.

By the end of all these settings, our design must present an aspect like in Figure 6.

To finish this step, we have to generate the wrapper from our design, generate block design, and run Synthesis-Implementation-Bitstream generation. All these actions are on the left panel. First of all, in the sources panel perform right-click on our block design and look for “Create HDL wrapper” at the emergent menu. When you are done, will appear a superstructure which encapsulates our design in a single structure just like in Figure 7.

We proceed to perform all necessary steps to create the Bitstream, over IP integrator at the left panel, click on “Generate block design.” Hold on here; all these next steps are sluggish. Therefore, if you have more threads performing the job, then you will finish early. To do so, over Run settings options in the emergent window that appeared just after you clicked on “Generate block design.” Choose the number of jobs (threads) that you want to dedicate. This depends on your machine setup and what other programs are running beside of Vivado. We live on the edge of danger, so choose four jobs and click on Generate.

After this process is finished, continue with the next ones. It’s true that whether you choose the last one, then Vivado will ask you to perform the previous one unless you are interested to see which are the options in each step you can take this way. Go through all the steps and when you are done the Bitstream will be ready to be exported to our Xilinx SDK environment. This last step is performed for click on File menu and choose Export->Export Hardware.

Having done this, we proceed to write the necessary code to work with the SD card. First, run Xilinx SDK for clicking on the File menu and then Launch SDK. A based on eclipse environment will show up. Therefore, if you already have experience with Eclipse IDE, this will be less confusing.

NOTE: By this time, Take a moment to rest and try to figure out what we did, just give to your mind time to processing all the new information.

Xilinx SDK

Import Xilffs libraries into board support package (BSP)

In Xilinx SDK at the Project Explorer panel you will see two things:

  1. The hardware design XXX_wrapper_hw_platform_0
  2. A based on board support package XXX_bsp

If you don’t have the second one don’t worry, you can create it. Although, I can’t go deep in how to create BSP I guarantee you this is as simple as create a project in Eclipse, just click on the File menu->New->Board support package. You will be asked for the project name, the CPU where the application will run, and the hardware platform. Having chosen all these options click on finish and done.

Going back to Project Explorer, expand the Board Support Project, double-click on system.mss and click on Modify this BSP’s Settings button, Figure 8 shows this.

Next, you must check “xilffs – Generic Fat File System Library” at Supported Libraries. Sure, you must realize that a new node appeared at the left side of this windows under standalone. So, if you click on the new node you will see the options to configure the library, I won’t attribute me the explanation for this library exists a good source where you can find all the documentation about it. Figure 9 shows what I am saying. We left the option as they are set and move forward, click on OK.

After performing this configuration, the BSP project will Re-generate; if you want to be sure, you can click on Re-generate BSP Sources button. These settings just add the ff.h library to the ps7_cortexa9_0/include directory, where all the libraries are. Next step involves creating a project. This process is slightly sensitive because when we create the software project, the latter takes BSP libraries references and its configuration is based on these (Compiler and linker references). So, whereas something goes wrong a not proper configure is made, producing a project that doesn’t find the functions inside .h files.

Before we go through this “possible” problem, we first create the project by clicking on “File menu->New->Application project.” Provide a name, and ensure the options OS Platform, hardware platform, processor, and Board Support Package, are set to standalone, XXX_wrapper_hw_platform_0, ps7_cortexa9_0, and XXX_bsp_0 respectively. By clicking on Next button you will be asked to choose a template for your project, Hello World is a good option, follow Figure 10.


Over our HelloWorld.c file, we code the software beginning with the necessary includes:

  • stdlib.h: malloc function and standard types
  • platform.h: Xilinx configuration
  • xsdps.h: some useful constants
  • xil_printf.h: standard console-out stream in Xilinx platform
  • ff.h: FatFs library

Now, we have all necessary libraries.

We have to think about how we can structure our code in a way that it meets some aspect like legible, scalable, and easy to replicate. Must of people could think “This is just a simple example written in a web post stop trying to be smarty pants.” I guarantee you that an explanation like this is also useful for those people. I am going to cover the rest of the code in the second part of this post. See you, soon.

Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>