Skip to content

Instantly share code, notes, and snippets.

@LispEngineer
Created May 28, 2023 02:46
Show Gist options
  • Save LispEngineer/6031c0f9d1bbb5debd2929f3c08620ba to your computer and use it in GitHub Desktop.
Save LispEngineer/6031c0f9d1bbb5debd2929f3c08620ba to your computer and use it in GitHub Desktop.
ZedBoard / Zynq Explorations

ZedBoard

References

DDR References from Digilent: (Not really related to ZedBoard)

Vivado and VS Code

Set up Vivado 2022.2 to use VS Code (Windows 10 Pro) as the editor.

I added C:\Program Files\Microsoft VS Code and ...\bin to my PATH.

See here and use code.cmd -g [file name]:[line number].

Vivado and Virus Protection

Protected folder access blocked

  • App: vivado.exe
  • Protected folder: %userprofile%\Documents\
  • Blocked by: Controlled folder access
  • Action chosen: Allow on device

Antivirus sent a lot of Vivado files to see if they were safe.

Setting up the board files

Reference: Digilent Walkthrough

  1. Clone the GitHub repo

  2. Run Vivado 2022.2

  3. Settings -> Vivado Store -> Board Repository

  • Add the cloned repo's new/board_files directory

Note that the Vivado Store inside Vivado gets its board files from this GitHub repository and branch 2022.2. If you update the Vivado Store repository it adds it to the settings automatically. Then, in the Boards selector (below) you will see three ZedBoards: An Avnet one, and two Digilents - the 1.0 from Xilinx Board Store and the 1.1 from the repo above.

Open Questions

  • The Avnet ZedBoard has an Add Companion Card option
    • This has the FMC XM105 Debug Card selectable
    • I have one of these! :)
    • How can I get that usable in the Digilent Zedboard?
    • What does it mean/do?

PL LED Blinking

Using: Vivado 2022.2

References:

  1. Run Vivado 2022.1 and create a new project
  • RTL project with no sources to start with
  • Use the Zedboard 1.1 board definition (This says it is for board D.3 but I have E)
  1. Add a constraint file from the GitHub Repo to the project
  • Be sure to Copy constraints files into project is selected
  • This now appears in Sources -> Constraints -> constrs_1 -> Zedboard-Master.xdc
  1. Uncomment the constraints for the pins we will use
  • Add a create_clock as well
    • I am assuming the GCLK is 100 MHz
  1. Create the SystemVerilog blinker code

  2. Create the bitstream with Generate Bitstream

  • This takes an unreasonable amount of time. Quite a few minutes on my laptop (Alienware 13R3, 32G RAM)
  1. Open Hardware Manager
  • Plug a USB Micro-B cable to the PROG port next to the power jack
  • Open Target -> Auto Connect
  • Program Device -> xc7z020_1

Voila. The LED should be blinking about 3 times a second.

Open Questions

  • After powering on and letting the Zedboard boot from the default image with Linux and all that - I have no idea if the previously running Linux is still running!

Bare Metal Blinking

References:

  1. Create blank project (as above)

  2. Project Manager -> IP INTEGRATOR -> Create Block Design

  • Give it a name, I chose BMBlock
  1. Add an IP block for the Zynq processor
  • Click the + in the Diagram pane
  • Add a ZYNQ7 Processing System
    • Two additional tabbed panes will show up, Address Editor and Address Map
    • The block will be named processing_system7_0
  • Click the Run Block Automation link that pops up in a green bar in the Diagram pane
    • A window will pop up, just click OK
    • (Apply Board Preset is checked, we have that ZedBoard Digilent 1.1 preset, and it says that checking it will discard the existing IP configuration, of which we have none.)
  • This added a bunch of ports to the Zynq block in the Diagram pane, including connections to DDR and FIXED_IO.
    • There are also these unconnected:
      • MDIO_ETHERNET_0
      • SDIO_0
      • USBIND_0
      • M_AXI_GP0 - with an odd dotted port
      • TTC0_WAVE#_OUT for 0, 1, 2
      • M_AXI_GP0_ACLK (seems to be an input?)
      • FCLK_CLK0 and FCLK_RESET0_N - see below
  • Double-clicking the Zynq block opens up a Re-customize IP window saying ZYNQ7 Processing System (5.5) with a lot of pages. The first page is the Zynq Block Design which has (double?) clickable green blocks that take you to other pages. Some have checkmarks next to them. (You can also right-click and choose Customize Block...)
    • Clicking Summary Report generates a huge HTML page and opens it in your browser.
  • To see what the DDR and FIXED_IO are:
    • See the Design pane, under External Interfaces
    • This lists all the pins for that external interface
    • FIXED_IO includes mio, srstb, clk, and porb
    • Not sure what some of those are
  • NOTE: Changes in the Block Diagram have to be saved with Control-S like a text file.
  1. Deal with PS-generated clocks
  • The block has a FCLK_CLK0 added by default, unconnected
    • (There is also an FCLK_RESET0_N - meaning?)
  • By using Customize Block... on the Zynq, then going to the Clock Configuration page, and then the PL Fabric Clocks you can see the speed of this clock, which is curently 100 MHz.
  • You can add 3 more at whatever speed you want.
    • Using IO PLL it does not have good granularity - the actual speed will not usually match the requested speed. For example, I couldn't get any 1280x1024 VGA pixel clock speed close for any refresh rate.
  • "All board files for Digilent Zynq boards enable a single Zynq PL clock by default, which is intended to be used with peripherals connected to the Zynq's M_AXI_GP0 port."
  1. Add GPIO for LEDs to Block Diagram
  • Note the Board pane in the BLOCK DESIGN, and the General Purpose Input or Output which contains buttons, LEDs and switches. (The switches are called "DIP switches" but the ZedBoard has regular sliders switches.)
  • Right click the LED and choose Connect Board Component...
  • Choose AXI GPIO -> GPIO and click OK
  • A new block appears in the diagram, called axi_gpio_0
    • Contains a pre-connected output to leds_8bits
      • Tutorial says this pre-connection "will not require any further work to constrain."
  • Rename it to AXI_GPIO_LED
  1. Add GPIO for buttons to Block Diagram (in a different way)
  • Click the + in the Diagram pane and add an AXI GPIO block
  • Name it AXI_GPIO_BUTTONS
  • Right click the GPIO output and select Make External which will add a linkage to GPIO_0.
    • "This option creates a new external interface port that does not rely on the board files."
    • So this will require us to make our own .xdc file.
  1. Deal with constraints file & board design
  • Add the Digilent-provided ZedBoard constraints file (as above)
    • Uncomment the 5 BTNx lines
  • Back to the Diagram pane
  • Expand the GPIO output of the AXI_GPIO_BUTTONS to reveal three connections, for Tristates: _i, _o and _t
    • When constrained to Tristate buffers these are combined into tri_io, the docs say, but I don't see it.
  • Edit the .xdc file to rename the BTNx lines to btn_tri_io[#] for the appropriate # (in this case, 5 for the ZedBoard)
  • In the diagram, double-click AXI_GPIO_BUTTONS to get the Re-customize IP window
    • Choose the IP Configuration pane
    • Change GPIO Width to the number of buttons (5 for the ZedBoard)
  • Click Run Connection Automation in the green bar
    • Select All Automation which includes the S_AXI for the two AXI blocks we added, and hit OK
  • The diagram turns into a rats nest!
    • An AXI Interconnect and a Processor System Reset are added
    • Move things around to make it look nice
    • Change the Default View dropdown box to see other perspectives of the same boxes
  1. Deal with Addresses
  • Open the Address Editor pane
  • Update the Range for the two GPIOs to 4k (they defaulted to 64k) - this is probably unnecessary
  • Go back to the Diagram
    • Right click it and choose Validate Design or hit F6
    • This gave Critical warnings for four DDR_DQS_TO_CLOCK_DELAY things (ignore?).
      • "These warnings are ignorable and will not affect the functionality of the project. See the Hardware Errata section of your board's reference manual for more information."
      • These Errata are the only Errata I could find; I saw none on Digilent's web site. This errata shows nothing useful.
      • This board post says to ignore it for a Zybo board.
      • Here is the Zybo Errata which mentions this
  1. Create an HDL Wrapper of the Block Design
  • Sources pane -> Design Sources -> BMBlock (right click) -> Create HDL Wrapper...
  • Select Let Vivado manage wrapper and auto-update (the default choice)
  • The Design Sources now shows BMBlock_wrapper instead with BMBLock_wrapper.v and BMBlock.v
  • There is also a Simulation Sources entry for the BMBlock_wrapper
  • You can double-click the BMBLock_wrapper.v and see it in your editor
    • This contains only top-level instantiations:
    • BMBlock
    • Five IOBUFs for the five button tristates (which really should be inputs only)
  • And look at the BMBlock.v
  1. And build it!
  • Click Generate Bitstream in the Flow Navigator
  • I have no idea how to monitor what it is doing
    • It took a while to generate stuff for IP Integrator blocks in Tcl Console
    • Project Summary pane shows Synthesis, Implementation are Queued
    • It shows Running multple block runs at the top corner, with a green spinny
    • Occasionally a small window will pop up in the bottom right of the screen with a quick update that quickly disappears (how useless is that?!)
  • Eventually it gets to Synthesis with 585 warnings
  • Then to Implementation
    • Critical warnings (which we can ignore) in the .xdc file:
      • set_property IOSTANDARD LVCMOS18 [get_ports -of_objects [get_iobanks 35]];
      • set_property IOSTANDARD LVCMOS33 [get_ports -of_objects [get_iobanks 13]];
      • Since evidently we didn't use those IO Banks
  • This probably took 10-15 minutes (!!!)
    • Vivado is sooooo sloooooow
  • "Critical warnings about how IPs included within another IP were packaged with a different board value can be safely ignored. The same is true for warnings related to negative CK-to-DQS delays seen on some Zynq boards."
    • I did not see any critical warnings other than the DQS and the .xdc ones.
  1. Get ready for Vitis
  • File -> Export -> Export Hardware
  • In Output pane, choose to Include bitstream that we just generated
  • Choose the default location for the .xsa file in the Files pane
  • And let it do it's thing
  • The .xsa file is a binary file of some sort

Vitis

Now we move into Vitis! (This IDE seems to be based on Eclipse.)

  1. Launch Vitis
  • From Start Menu
  • From Tools -> Launch Vitis IDE in Vivado
  1. Choose a workspace when it pops up
  • I chose C:\src\FPGA\dpf-zb-barmetal-workspace
  1. Create Application Project
  • Project -> Create Application Project in the Vitis welcome window
  • In the Platform pane, click the Create a new platform from hardware (XSA) tab
    • XSA = Xilinx Shell Architecture
  • Browse for the .xsa file we just exported
  • Select it in the Hardware Specification XSA File: list
  • Select Generate boot components
  • Give it a platform name (I chose DPF-BareMetal)
  • Click Next to see Application Project Details pane
  • Application Project Name: BareMetal1
  • Target ps7_cortexa9_0 (for now)
  • Click Next to see the Domain pane
    • We will use defaults in Domain
  • Click Next to see the Templates pane
  • Choose Empty Application(C) and click Finish
  • ...and the Vitis IDE opens with the BareMetal1 and BareMetal1_system panes available
  1. Create Source
  • Explorer pane
  • Right-click src directory, New -> File
  • Name it main.c
  • COpy the code from the tutorial
  • Edit the BTN_MASK and LED_MASK
  1. Build!
  • Assistant pane
  • Select BareMetal1_system
  • Click Build hammer icon or right-click and select Build
  • It does its thing for a while, building a .bif file and stuff

Programming the Board

  1. Update the board settings to boot from JTAG
  • Default as shipped ZedBoard MIO[6:2] jumpers are 01100 to boot from SD card (MIO[5:3])
  • Hardware guide says JTAG boot is MIO[5:3] of 3'b000
    • Set Jumpers 7-11 appropriately
  1. Connect TeraTerm at 115.2kbps and no flow control

  2. Power the board on with both JTAG and UART Micro-USB cables connected to computer

  3. Run it!

  • Explorer pane
  • BareMetal1_system (right click) -> Run As -> 1 Launch Hardware
  • The blue LED marked DONE should light up (LD12)
  • TeraTerm will say "Entered function main"
  • Tap any of the 5 buttons
    • All 8 LEDs should light up
  • Tapping PROG button will clear the PL and things will break (blue light goes out)
  • Tapping PS-RST will reset the PS and things will also break
  • You can re-program exactly the same way and the blue light will come back

Next up

Modifying the code to do something more interesting

Software Developer Guide

  • Make the LEDs display each button
    • And "all on" or "all off" or "any on" lights
  • Send console message with each button change

Further modifications: Add Switches

  1. Go to Vivado and add GPIO switches to the Block Diagram
  • I also seem to have accidentally turned my buttons into input-only, and consequently needed to add new constraints for btn_tri_i instead.
  • Set the address window to 4K again
  1. Regenerate the bitstream

  2. Re-export the hardware

  3. In Vitis, in the Assistant pane, right click the [Platform] (called DPF-BareMetal in mine) and Update Hardware Specification

  • Give it the re=exported .xsa from the step above and let it do its thing
  • THen right-click it again and pick Open Platform Editor
  • Click the Board Support Package for either zynq_fsbl or standalone_ps7_cortexa9_0
    • You will see AXI_GPIO_SWITCHES under the Operating System -> Drivers tab
  • It says Out-of-date and if you look in xproperties.h you see no reference to the switches we just added
  • Let's see what happens if I now hit Build on the [Platform]
    • THIS WORKED
    • The Out-of-date goes away on the system
    • xparameters.h now has a section on Definitions for peripheral AXI_GPIO_SWITCHES
  1. Modify the C code to use the switches however you like
  • In Assistant pane, click Build on the BareMetal1_system [System]
  • Run 1 Launch Hardware to build the software (in the Explorer pane)
  • Test it on the board
  • If the board works, you're golden, otherwise, fix it and repeat this step (or possibly go to step 1)

Make a bootable SD card of the above baremetal application

Digilent Tutorial to follow along with.

  1. Apparently this is automatically built due to having selected Generate boot components earlier (above)
  • See dpf-zb-baremetal-workspace/BareMetal1_system/Debug/sd_card directory
  1. Prepare SD card
  • FAT32 formatted microSD (so up to 32G will work)
  • Copy BOOT.BIN file into its root directory (about 4 Mbytes long)
  1. Set the ZedBoard to boot from SD card (see above)
  • Insert the SD card
  • Boot
  • It literally configures in under a second
  • Windows can't configure the UART fast enough to get the introductory message
  1. Other buttons
  • PROG button will kill the application
  • PS-RST will reload the application quickly
    • The initial startup printf will show up on console

Notes on Vivado Diagram view

Zooming and movement:

  • Center-drag to move the window
  • Control-scroll wheel to zoom in and out
  • Left-drag to do various zooms:
    • Area (downward right diagnonal)
    • To fit (upward left diagonal)
    • In or out (along a one diagonal) by 0.5

Open Questions

  • How are the pre-made DDR and FIXED_IO connections in the Block Design set up and/or connected?

  • Where do I get documentation on all the APIs available in the Vitis project?

    • Like documentation on XGpio_CfgInitialize or xil_printf and so forth?
    • What about the xxx_CHANNEL parameter to XGpio_SetDataDirection

Ideas for simple Zynq projects

  • Build my own AXI LED & button/switch interface from scratch

    • Instantiate it in the diagram
    • Read buttons/switches and send LED outputs from bare metal
    • ...and from Linux
  • Build character RAM based external display (e.g. I2C or SPI display with one of my other character display drivers, or VGA)

    • Build AXI interface to the character memory using true dual-port RAM (?)
      • Since I never built anything with AXI this will be the real challenge
    • Change character buffers from bare metal
      • Since I never built anything using Zynq in general this will be challenge #2
    • Change character buffer from a Linux device driver
      • Since I never built PetaLinux or Ubuntu with Zynq this will be challenge #3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment