Earlier this year the friend of mine came across this cheap board featuring Xilinx Zynq 7010 called EBAZ4205. These boards are scavenged from Ebang Ebit E9+ bitcoin miner machine and can be bought from Aliexpress. I thought I would give it a try and I was surprised how cheap and powerful these are. After playing around with this board I quickly became annoyed of configuring Zynq PS system every time I create new project. Because of that I decided to learn how to create Xilinx Vivado board files and today I will be sharing my knowledge with you.
RequirementsBefore creating board files for your custom board I strongly suggest you to read Xilinx UG895 Vivado System Level Design Appendix A. This document describes structure and content of board files.
Structure of board filesXilinx Vivado board files are stored in Vivado installation directory:
/<version>/data/boards/board_files/
In this directory we can create new folder and name it after our board (e.g. ebaz4205). Inside this catalog we will create another folder named after board version (e.g. 1.0). This folder will be holding picture of our board and three important XML files:
- board.xml - defines all of information about the board. It includes basic information (e.g. board name, description, vendor), information about components on the board (e.g. FPGA part, LEDs, buttons), information about required interfaces for components on the board and preferred IP cores to implement these interfaces.
- preset.xml - defines presets for IP cores specified in board.xml file.
- part0_pins.xml - defines physical pins and I/O standards for interfaces specified in board.xml file.
After creating all required folders and files our board file folder structure should look something like this:
ebaz4205/
└── 1.0
├── board.xml
├── ebaz4205.jpg
├── part0_pins.xml
└── preset.xml
board.xmlThe file starts with XML tag called <board> in which we will provide basic information about the board:
<board schema_version="2.1" vendor="miner.ebang.com.cn" name="ebaz4205" display_name="EBAZ4205 Development Board" url="http://miner.ebang.com.cn" preset_file="preset.xml">
Firstly we define board file schema version - attribute which tells Vivado software how to interpret data provided in the file (in Vivado 2020.1 which I am currently using the latest version of schema is 2.1). Next we define vendor name, board name and web page for the board vendor. In <board> tag we also specify name of preset file which will be used later. After this we must close <board> tag by writing </board> in the new line. All other board information must be defined between these two tags.
To ensure proper working of board files we must add <file_version> and <compatible_board_revisions> tags:
<!-- Board file revision -->
<file_version>1.0</file_version>
<!-- Board PCB revision -->
<compatible_board_revisions>
<revision id="1">1.0</revision>
</compatible_board_revisions>
<file_version> tag is used to track version of board files while <compatible_board_revisions> tag is used to specify with which board PCB revisions these files can be used.
We can add picture and description of the board by specifying image in <image> and description in <description> tags:
<!-- Image of the board -->
<images>
<image name="ebaz4205.jpg" display_name="EBAZ4205 Development Board" sub_type="board">
<description>EBAZ4205 Development Board</description>
</image>
</images>
<!-- Board description -->
<description>EBAZ4205 is mining board used in Ebang Ebit E9+ bitcoin miner machine. This board features 256MB DDR3 memory, 128MB NAND Flash memory, 10/100MBit Ethernet and speed grade -1 Zynq 7010.</description>
Most of this information will be displayed in board selection window when creating new project:
Or in Vivado Project Summary window:
After providing basic information now we can specify components on the board by adding information between <components> </components> tags:
<!-- Information about board components: fpga part, interfaces, etc. -->
<components>
<!-- FPGA part -->
<component name="part0" display_name="EBAZ4205" type="fpga" part_name="xc7z010clg400-1" pin_map_file="part0_pins.xml" vendor="xilinx" spec_url="www.xilinx.com">
<description>FPGA part on the board</description>
<!-- Associated FPGA interfaces and IP cores -->
<interfaces>
<!-- Zynq 7000 processing system -->
<interface mode="master" name="ps7_fixedio" type="xilinx.com:display_processing_system7:fixedio_rtl:1.0" of_component="ps7_fixedio" preset_proc="ps7_preset">
<preferred_ips>
<preferred_ip vendor="xilinx.com" library="ip" name="processing_system7" order="0"/>
</preferred_ips>
</interface>
<!-- User LEDs: Red and Green (LED6) -->
<interface mode="master" name="leds_2bits" type="xilinx.com:interface:gpio_rtl:1.0" of_component="leds_2bits" preset_proc="leds_2bits_preset">
<preferred_ips>
<preferred_ip vendor="xilinx.com" library="ip" name="axi_gpio" order="0"/>
</preferred_ips>
<port_maps>
<port_map logical_port="TRI_O" physical_port="leds_2bits_tri_o" dir="out" left="1" right="0">
<pin_maps>
<pin_map port_index="0" component_pin="leds_2bits_tri_o_0"/>
<pin_map port_index="1" component_pin="leds_2bits_tri_o_1"/>
</pin_maps>
</port_map>
</port_maps>
</interface>
</interfaces>
</component>
<!-- Zynq 7000 processing system -->
<component name="ps7_fixedio" display_name="PS7 fixed IO" type="chip" sub_type="fixed_io" major_group=""/>
<!-- User LEDs: Red and Green (LED6) -->
<component name="leds_2bits" display_name="LEDs" type="chip" sub_type="led" major_group="General Purpose Input or Output">
<description>LEDs, Active Low</description>
</component>
</components>
Firstly we must define FPGA part used on the board, in EBAZ4205 case it is xc7z010clg400-1. We also define vendor of this component and pin map file. All of the IP cores used to implement interfaces between FPGA and board components must be defined between FPGA <component> tags.
The first defined interface will be fixed I/O of Zynq processing system. We must specify interface mode, name, preferred IP core to implement this interface and preset name (preset_proc) which will link IP core with predefined configurations in preset.xml file:
<!-- Zynq 7000 processing system -->
<interface mode="master" name="ps7_fixedio" type="xilinx.com:display_processing_system7:fixedio_rtl:1.0" of_component="ps7_fixedio" preset_proc="ps7_preset">
<preferred_ips>
<preferred_ip vendor="xilinx.com" library="ip" name="processing_system7" order="0"/>
</preferred_ips>
</interface>
The second defined interface is for LEDs. To implement this interface we will be using AXI GPIO IP core. For this interface we must also define port pin map because AXI GPIO IP core port pins must be connected to physical FPGA pins:
<!-- User LEDs: Red and Green (LED6) -->
<interface mode="master" name="leds_2bits" type="xilinx.com:interface:gpio_rtl:1.0" of_component="leds_2bits" preset_proc="leds_2bits_preset">
<preferred_ips>
<preferred_ip vendor="xilinx.com" library="ip" name="axi_gpio" order="0"/>
</preferred_ips>
<port_maps>
<port_map logical_port="TRI_O" physical_port="leds_2bits_tri_o" dir="out" left="1" right="0">
<pin_maps>
<pin_map port_index="0" component_pin="leds_2bits_tri_o_0"/>
<pin_map port_index="1" component_pin="leds_2bits_tri_o_1"/>
</pin_maps>
</port_map>
</port_maps>
</interface>
After defining FPGA part and its interfaces we must define other components. One by default is Zynq 7000 processing system and the other is LEDs. Interfaces created earlier will be linked to these components by attribute called component name:
<!-- Zynq 7000 processing system -->
<component name="ps7_fixedio" display_name="PS7 fixed IO" type="chip" sub_type="fixed_io" major_group=""/>
<!-- User LEDs: Red and Green (LED6) -->
<component name="leds_2bits" display_name="LEDs" type="chip" sub_type="led" major_group="General Purpose Input or Output">
<description>LEDs, Active Low</description>
</component>
This declaration also let us find our components in the Board tab of the Vivado block design window:
In board.xml file we must also define JTAG chains for all components on the board if applicable. In this case we have only one JTAG chain for FPGA part:
<!-- Board jtag chains for all fpga parts -->
<jtag_chains>
<!-- Board jtag chains for part0 -->
<jtag_chain name="chain1">
<position name="0" component="part0"/>
</jtag_chain>
</jtag_chains>
And of course we must specify connection which will link our component interfaces to physical FPGA pins declared in part0_pins.xml file:
<!-- Connections between component interfaces and physical pins described in part0_pins.xml -->
<connections>
<!-- User LEDs: Red and Green (LED6) -->
<connection name="part0_leds_2bits" component1="part0" component2="leds_2bits">
<connection_map name="part0_leds_2bits_1" c1_st_index="0" c1_end_index="1" c2_st_index="0" c2_end_index="1"/>
</connection>
</connections>
Here c1_st_index and c1_end_index corresponds to pin indexes in part0_pins.xml file while c2_st_index and c2_end_index corresponds to IP core port pin indexes.
preset.xmlThe preset.xml file starts with XML tag called <ip_presets> in which we must provide this file schema version. The current schema version for preset file is 1.0:
<ip_presets schema = "1.0">
We must close <ip_presets> tag by writing </ip_presets> in the new line. The presets for IP cores will be listed between these two tags.
First we add configurations for Zynq processing system IP core. These configurations are linked to board.xml file by attribute called preset_proc_name:
<!-- Zynq 7000 processing system configuration -->
<ip_preset preset_proc_name="ps7_preset">
<ip vendor="xilinx.com" library="ip" name="processing_system7" version="*">
<user_parameters>
<user_parameter name="CONFIG.PCW_UART1_PERIPHERAL_ENABLE" value="1"/>
<user_parameter name="CONFIG.PCW_UART1_UART1_IO" value="MIO 24 .. 25"/>
<user_parameter name="CONFIG.PCW_SD0_PERIPHERAL_ENABLE" value="1"/>
<user_parameter name="CONFIG.PCW_SD0_SD0_IO" value="MIO 40 .. 45"/>
<user_parameter name="CONFIG.PCW_NAND_PERIPHERAL_ENABLE" value="1"/>
<user_parameter name="CONFIG.PCW_NAND_GRP_D8_ENABLE" value="0"/>
<user_parameter name="CONFIG.PCW_ENET0_PERIPHERAL_ENABLE" value="1"/>
<user_parameter name="CONFIG.PCW_ENET0_ENET0_IO" value="EMIO"/>
<user_parameter name="CONFIG.PCW_ENET0_GRP_MDIO_ENABLE" value="1"/>
<user_parameter name="CONFIG.PCW_ENET0_PERIPHERAL_FREQMHZ" value="100 Mbps"/>
<user_parameter name="CONFIG.PCW_GPIO_MIO_GPIO_ENABLE" value="1"/>
<user_parameter name="CONFIG.PCW_GPIO_MIO_GPIO_IO" value="MIO"/>
<user_parameter name="CONFIG.PCW_ENET_RESET_ENABLE" value="0"/>
<user_parameter name="CONFIG.PCW_USB_RESET_ENABLE" value="0"/>
<user_parameter name="CONFIG.PCW_I2C_RESET_ENABLE" value="0"/>
<user_parameter name="CONFIG.PCW_UIPARAM_DDR_BUS_WIDTH" value="16 Bit"/>
<user_parameter name="CONFIG.PCW_UIPARAM_DDR_PARTNO" value="MT41K128M16 JT-125"/>
</user_parameters>
</ip>
</ip_preset>
In Zynq 7000 processing system we enable UART1, SD0, NAND, ETHERNET0 and other peripherals, select MIO pins for these peripherals and also configure DDR memory.
Next we add configurations for AXI GPIO IP core which will be used to implement interface between FPGA and user LEDs on the board:
<!-- User LEDs: Red and Green (LED6) AXI GPIO configuration -->
<ip_preset preset_proc_name="leds_2bits_preset">
<ip vendor="xilinx.com" library="ip" name="axi_gpio" ip_interface="GPIO">
<user_parameters>
<user_parameter name="CONFIG.C_GPIO_WIDTH" value="2"/>
<user_parameter name="CONFIG.C_ALL_OUTPUTS" value="1"/>
<user_parameter name="CONFIG.C_ALL_INPUTS" value="0"/>
<user_parameter name="CONFIG.C_DOUT_DEFAULT" value="0x00000003"/>
</user_parameters>
</ip>
</ip_preset>
Here we configure AXI GPIO IP core to have only 2 pins which will be used as outputs with default logical value of 1 because LEDs on this board are active low (turned on by supplying logical 0).
part0_pins.xmlpart0_pins.xml file starts with <part_info> </part_info> tags in which we must specify FPGA part used on the board. Between these two tags we will be providing all the pin mapping information:
<!-- Physical pin location and I/O standards for component interfaces described in board.xml -->
<part_info part_name="xc7z010clg400-1">
<pins>
<pin index="0" name ="leds_2bits_tri_o_0" iostandard="LVCMOS33" loc="W14"/>
<pin index="1" name ="leds_2bits_tri_o_1" iostandard="LVCMOS33" loc="W13"/>
</pins>
</part_info>
Pins listed here are linked to IP core port pins specified in board.xml file by pin name attribute. We set I/O standard to LVCMOS33 because voltage of FPGA bank in which these pins are located is set to 3.3V on EBAZ4205 board. Finally we link IP core port pins to physical FPGA package pins by providing location attribute loc.
I hope this tutorial helped you to better understand Xilinx Vivado board file structure and how these files can be created for your custom board.
Full EBAZ4205 board files can be found in my repository here.
Comments