top of page

MicroZed Chronicles: Vivado Board Definitions

We will be releasing a new open source development board in a few weeks and will eventually be offering a free training course for it, provided the prototype arriving next week works as expected!


This board contains a Spartan 7 device and is connected to a RP2040 (RPI Pico), in addition to SDRAM, user SPI flash, PMOD, and of course the switches and LEDs you would expect for a development board.

Of course, designing the board is the simple bit. The exciting part is the board bring up and checking that all its interfaces and memories are working as expected.


Doing this will require several Vivado projects with each one building upon previous verified capabilities. Since we are going to be creating several projects, I wanted to create a board definition which makes Vivado aware of the board and its capabilities.


Doing so is pretty straight forward though we need to write several XML files to get started. I have a feeling I will be coming back with a follow up to this blog because it shows how we can do more advanced features in board definition.


For now, we are going to get started with the base design which contains a Spartan 7 xc7s6ftgb196 which gives us a footprint compatible device all the way up to the XC7s50.


We need the following files to create a basic board definition:

  • Board.xml – This file contains the majority of the information on the target device and its connections are defined.

  • Part0_pins.xml – This defines the pins for the part defined in the board.xml

  • Preset.xml – This defines the presets for any IP blocks defined within the board.xml

It might seem daunting if this is the first time you’ve written a board definition, however, it can be achieved fairly straightforwardly and Vivado has the ability to parse data and report if the files we’ve created are valid.


Let’s take a look at the board.xml file first. This uses a simple structure where we define the board, its compatible revision, and description.

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<board schema_version="2.0" vendor="adiuvoengineering.com" name="Leonidas" display_name="Leonidas"  preset_file="preset.xml" >
<compatible_board_revisions>
  <revision id="0">A.0</revision>
</compatible_board_revisions>
<file_version>1.1</file_version>
<description>Leonidas King of Spartans</description>

With the description completed, the next step is to define the component. The name given here for the component has to be the same as the <component_name>_pins.xml file. With the component declared, we can then define the interfaces for the component/FPGA. Under the interfaces, we define each of the interfaces on the FPGA that we wish to make the Vivado aware of. In this case, we will be declaring the clock, LEDS, push buttons and switches.

<component name="part0" display_name="Leonidas" type="fpga" part_name="xc7s6ftgb196-1" pin_map_file="part0_pins.xml" vendor="xilinx" >
  <interfaces>

For each interface, we can define parameters of importance such as pin maps, frequency, and what the preferred IP to be used for each interface.

<interface mode="slave" name="sys_clock" type="xilinx.com:signal:clock_rtl:1.0" of_component="sys_clock" preset_proc="sys_clock_preset">
        <parameters>
          <parameter name="frequency" value="100000000"/>
        </parameters>
        <preferred_ips>
          <preferred_ip vendor="xilinx.com" library="ip" name="clk_wiz" order="0"/>
        </preferred_ips>
          <port_maps>
          <port_map logical_port="CLK" physical_port="clk" dir="in">
            <pin_maps>
              <pin_map port_index="0" component_pin="clk"/> 
            </pin_maps>
          </port_map>
        </port_maps>
        <parameters>
          <parameter name="frequency" value="100000000" />
       </parameters>
    </interface>

Once we have declared the interfaces for the FPGA, we can close that component using the component end tag.


We can then declare the components that are aligned with the interfaces as defined under the interface section of the FPGA component.

  <component name="sys_clock" display_name="System Clock" type="chip" sub_type="system_clock" major_group="Clocks">
    <description>3.3V Single-Ended 100MHz oscillator used as system clock on the board</description>
  </component>

The final element of the boards.xml file is the JTAG chain.

<jtag_chains>
  <jtag_chain name="chain1">
    <position name="0" component="part0"/>
  </jtag_chain>
</jtag_chains>

The next file we need to write is the _pins.xml. This file defines the pins for the FPGA component defined within the board.xml file.

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<part_info part_name="xc7s6ftgb196-1">
<pins>
  <pin index="0" name ="clk" iostandard="LVCMOS33" loc="G11"/>
  <pin index="1" name ="led_4bits_tri_o_0" iostandard="LVCMOS33" loc="E11"/>
  <pin index="2" name ="led_4bits_tri_o_1" iostandard="LVCMOS33" loc="M10"/>
  <pin index="3" name ="led_4bits_tri_o_2" iostandard="LVCMOS33" loc="A10"/>
  <pin index="4" name ="led_4bits_tri_o_3" iostandard="LVCMOS33" loc="D12"/>

  <pin index="5" name ="dip_switches_4bits_tri_i_0" iostandard="LVCMOS33" loc="A13"/>
  <pin index="6" name ="dip_switches_4bits_tri_i_1" iostandard="LVCMOS33" loc="A12"/>
  <pin index="7" name ="dip_switches_4bits_tri_i_2" iostandard="LVCMOS33" loc="B14"/>
  <pin index="8" name ="dip_switches_4bits_tri_i_3" iostandard="LVCMOS33" loc="B13"/>

  <pin index="9"  name ="push_buttons_4bits_tri_i_0" iostandard="LVCMOS33" loc="M5"/>
  <pin index="10" name ="push_buttons_4bits_tri_i_1" iostandard="LVCMOS33" loc="L5"/>
  <pin index="11" name ="push_buttons_4bits_tri_i_2" iostandard="LVCMOS33" loc="N4"/>
  <pin index="12" name ="push_buttons_4bits_tri_i_3" iostandard="LVCMOS33" loc="P5"/>
</pins>
</part_info>

Within this file, we can associate a name-defined interfaces declaration within boards.xml with a physical pin on the FPGA device in addition to defining its IO standard.


The final file we need for this initial development is the preset file. This preset file defines the preset configurations for each of the components.

Each component can have multiple preset conditions to support different ways of implementation. A good example of this is the AXI GPIO used for the buttons, switches and LEDs. These can be implemented on a single AXI channel. However, if a GPIO already exists within the design, the interface could be added using the second channel if available. This ability is made possible by the preset file.

<?xml version="1.0" encoding="UTF-8" standalone="no" ?> 

<ip_presets schema="1.0">
    <ip_preset preset_proc_name="dip_switches_4bits_preset">
        <ip vendor="xilinx.com" library="ip" name="axi_gpio" ip_interface="GPIO">
            <user_parameters>
            <user_parameter name="CONFIG.C_GPIO_WIDTH" value="4"/> 
            <user_parameter name="CONFIG.C_ALL_INPUTS" value="1"/> 
        <user_parameter name="CONFIG.C_ALL_OUTPUTS" value="0"/>
            </user_parameters>
        </ip>
        <ip vendor="xilinx.com" library="ip" name="axi_gpio" ip_interface="GPIO2">
            <user_parameters>
            <user_parameter name="CONFIG.C_IS_DUAL" value="1"/> 
            <user_parameter name="CONFIG.C_GPIO2_WIDTH" value="4"/> 
            <user_parameter name="CONFIG.C_ALL_INPUTS_2" value="1"/> 
        <user_parameter name="CONFIG.C_ALL_OUTPUTS_2" value="0"/>
            </user_parameters>
        </ip>
    </ip_preset>
    <ip_preset preset_proc_name="push_buttons_4bits_preset">
    <ip vendor="xilinx.com" library="ip" name="axi_gpio" ip_interface="GPIO">
        <user_parameters>
          <user_parameter name="CONFIG.C_GPIO_WIDTH" value="4"/> 
          <user_parameter name="CONFIG.C_ALL_INPUTS" value="1"/> 
      <user_parameter name="CONFIG.C_ALL_OUTPUTS" value="0"/>
        </user_parameters>
    </ip>
    <ip vendor="xilinx.com" library="ip" name="axi_gpio" ip_interface="GPIO2">
        <user_parameters>
          <user_parameter name="CONFIG.C_IS_DUAL" value="1"/> 
          <user_parameter name="CONFIG.C_GPIO2_WIDTH" value="4"/> 
          <user_parameter name="CONFIG.C_ALL_INPUTS_2" value="1"/> 
      <user_parameter name="CONFIG.C_ALL_OUTPUTS_2" value="0"/>
        </user_parameters>
    </ip>
    </ip_preset>
    <ip_preset preset_proc_name="led_4bits_preset">
    <ip vendor="xilinx.com" library="ip" name="axi_gpio" ip_interface="GPIO">
        <user_parameters>
          <user_parameter name="CONFIG.C_GPIO_WIDTH" value="4"/> 
          <user_parameter name="CONFIG.C_ALL_INPUTS" value="0"/> 
          <user_parameter name="CONFIG.C_ALL_OUTPUTS" value="1"/>
        </user_parameters>
    </ip>
    <ip vendor="xilinx.com" library="ip" name="axi_gpio" ip_interface="GPIO2">
        <user_parameters>
          <user_parameter name="CONFIG.C_IS_DUAL" value="1"/> 
          <user_parameter name="CONFIG.C_GPIO2_WIDTH" value="4"/> 
          <user_parameter name="CONFIG.C_ALL_INPUTS_2" value="0"/> 
          <user_parameter name="CONFIG.C_ALL_OUTPUTS_2" value="1"/>
        </user_parameters>
    </ip>
    </ip_preset>
     <ip_preset preset_proc_name="sys_clock_preset">
    <ip vendor="xilinx.com" library="ip" name="clk_wiz" ip_interface="clk_in1">
        <user_parameters>
          <user_parameter name="CONFIG.PRIM_IN_FREQ" value="100"/> 
          <user_parameter name="CONFIG.PRIM_SOURCE" value="Single_ended_clock_capable_pin"/> 
          <user_parameter name="CONFIG.RESET_TYPE" value="ACTIVE_LOW"/>
          <user_parameter name="CONFIG.RESET_PORT" value="resetn"/>           
        </user_parameters>
    </ip>
    <ip vendor="xilinx.com" library="ip" name="clk_wiz" ip_interface="clk_in2">
        <user_parameters>
        <user_parameter name="CONFIG.USE_INCLK_SWITCHOVER" value="true"/>
        <user_parameter name="CONFIG.SECONDARY_IN_FREQ" value="100"/>
        <user_parameter name="CONFIG.SECONDARY_SOURCE" value="Single_ended_clock_capable_pin"/> 
        <user_parameter name="CONFIG.RESET_TYPE" value="ACTIVE_LOW"/> 
        <user_parameter name="CONFIG.RESET_PORT" value="resetn"/> 
        </user_parameters>
    </ip>
  </ip_preset>
</ip_presets>

We can use the board file linter to validate our board files. We call this from the TCL command line in Vivado. The command to run this is as follows:

validate_board_files  -doctype_inject "" <board files directory>

Once we have the board files validated, we can add in a board file location to the board repository in the Vivado settings.


This means I can create projects to my heart’s content and be confident the project settings are all correct when we are ready to start bringing up the board.


You will be able to see the board just created on the board selection tab.

Yes, I did call the board Leonidas because it is the king of Spartans!


Workshops and Webinars


If you enjoyed the blog why not take a look at the free webinars, workshops and training courses we have created over the years. Highlights include


Embedded System Book Do you want to know more about designing embedded systems from scratch? Check out our book on creating embedded systems. This book will walk you through all the stages of requirements, architecture, component selection, schematics, layout, and FPGA / software design. We designed and manufactured the board at the heart of the book! The schematics and layout are available in Altium here Learn more about the board (see previous blogs on Bring up, DDR validation, USB, Sensors) and view the schematics here.



Sponsored by AMD

0 comments

Commentaires


bottom of page