Vivado Error [Opt 31-67], and How I Fixed It.

So I am dealing with the following scenarios:

Scenario 1 – Genesys Zynq with SYZYGY SFP

I have the Genesys Zynq UltraScale+ MPSoC 3EG board that does not provide direct access to the PHY pins, but has a SYZYGY port that I have plugged in to the SZG-DUALSFP module with an SFP connector.

Scenario 2 – Arty A7 Artix-7 with 10/100 Mbit PHY

I have the Arty A7 Artx-7 FPGA Development Board that gives me direct access to the pins of a 10/100 Mbit PHY.

All I want to do is connect directly to a PHY so I can implement a LabVIEW based TCP/IP core, and as a starting Proof-of-Concept, I will take the already existing LabVIEW FPGA implementation (see their examples) and bring the UDP echo sample in.

So I create a design using the Arty board using a MicroBlaze processor, write a simple program and add an AXI Stream FIFO core and connect that to a custom verilog node that will hold the LabVIEW FPGA code.  I do this because I want a way of communicating with the code running on the FPGA.  The AXI Stream FIFO will bridge the LabVIEW FPGA code with the MicroBlaze processor, and what I will do is send some or all data received from the Ethernet PHY over the AXI Stream FIFO to a C++ application running on the MicroBlaze, and then via a UART connection that I make from my host computer to the Arty, see the results.

I can also use this as a way to properly figure out how to use the SZG-DUALSFP module as well.

Long story short, I add an AXI-Stream FIFO that is connected to a labview_ip node which will house my LabVIEW FPGA exported code.  And for now I create a simple file that echoes a random packet of five 32-bit WORDS once per second.

Optimization Error

So I create this custom Verilog code, and click Generate Bitstream.  After a few minutes I get the error mentioned in the title of this article.  I originally had no idea how to debug this, but after some time on Xilinx Forums I figured it out… I forgot to wire up one value, and the design optimization removed it since it was unwired.  Anyway, if you are using Vivado and you get this error, please continue…

[Opt 31-67] Problem: A LUT3 cell in the design is missing a connection on input pin I2, which is used by the LUT equation. This pin has either been left unconnected in the design or the connection was removed due to the trimming of unused logic. The LUT cell name is: design_1_i/axi_fifo_mm_s_0/U0/COMP_IPIC2AXI_S/gtxd.COMP_TXD_FIFO/gfifo_gen.COMP_AXIS_FG_FIFO/COMP_FIFO/xpm_fifo_base_inst_i_1.

So the LUT cell name is:

design_1_i/axi_fifo_mm_s_0/U0/COMP_IPIC2AXI_S/gtxd.COMP_TXD_FIFO/gfifo_gen.COMP_AXIS_FG_FIFO/COMP_FIFO/xpm_fifo_base_inst_i_1

I manually run ‘Optimize Design’ with the the following commands:

set_param messaging.defaultLimit 100000
opt_design -verbose

(See: https://www.xilinx.com/support/answers/58616.html for more details on using this approach)

This reproduces the error, but the error appears in the TCL Console this time.

I open the Synthesized Design (‘Open Synthesized Design’ option on the left side-bar):

Show the object/cell by using the TCL console:

show_objects [ get_cells {design_1_i/axi_fifo_mm_s_0/U0/COMP_IPIC2AXI_S/gtxd.COMP_TXD_FIFO/gfifo_gen.COMP_AXIS_FG_FIFO/COMP_FIFO/xpm_fifo_base_inst_i_1}]

Which shows me this:

Then I go to the schematic by right-clicking on the cell and selecting ‘Schematic’:

So this schematic shows that the signal I2 is unconnected. Now what is I2? I have no idea… 

So I get more information by right-clicking and selecting ‘Expand Cone->To Selected Cells’:

The schematic will be pretty big, however the selected cell will be highlighted in blue and zoomed in like so:

 

Then I follow the output wire until I find where it goes, notice that the wire is connected to ‘rd_en’, which sounds a lot like ‘Read Enable’ which is a port that the FIFO should have connected. 

Now this might be too vague, so what if I wanted to know what component or cell the rd_en signal is going to? I right-click on the border of this cell/component and select ‘Expand/Collapse->Collapse Inside’:

With this view, I know immediately what is wrong, I must have never wired the ready or ‘Ready for Input’ signal somewhere between the AXI-Stream FIFO and my custom IP.

And here is a slightly zoomed out view:

I go back to my Verilog code and realize that I never assigned a value to the ‘Transmit Ready’ signal – even though I would have expected this to work and to default to a value of 0.

For the curious, adding line 128 fixed the error:

 

 

 

 

Plans Using Arty Artix-7

Here is the new plan:

Step 1 – Create a design using a MicroBlaze processing system, enable a UART connection and listen on an AXI FIFO and dump packets to the screen as they are received in chunks of X bytes.

Step 2 – Insert some LabVIEW FPGA code to send one packet of data every second.

Step 3 – Replace this LabVIEW FPGA code to listen to the MII Ethernet interface pins and to dump some data to the screen as before.

Step 4 – Insert the LabVIEW FPGA UDP/IP library that is included with LabVIEW

Now if you want to follow along, get the board from here:

http://store.digilentinc.com/arty-a7-artix-7-fpga-development-board-for-makers-and-hobbyists/

(I recommend getting the Arty A7-100T, but if you are a complete newbite, stick to the one that you find the most documentation for)

Then follow these videos from FPGA Developer on YouTube:

And Another Alternative

I no longer have to look into figuring out how to code up or wire up the SZG-DUALSFP daughter board to the Digilent Genesys Zynq UltraScale MPSoC+ board.

Why? Because I have a really old board that cost only $99 dollars that gives me direct access to the pins of an old 10/100 MBit PHY! That’s the Arty Artix-35T mini board!

Anyway… I found a corresponding NI “no longer national instruments” board that targets the same family of FPGAs so I can get started.

What that means is:

  • Create a LabVIEW FPGA project that targets the CompactRIO 9053 board
  • Use the LabVIEW FPGA IP Export the Netlist utility to get a design checkpoint
  • Import that checkpoint in to my Arty project
  • Generate an Arty Bitstream
  • Load it to the FPGA
  • Enjoy my FIX parsing code on this board with full ethernet connectivity.

References:

However, the Genesys Board will still remain in my consciousness and will be a secondary hobbyist project that I will look into and play with whenever I am tired of the Arty board…

Rebuilding Genesys Zynq UltraScale MPSoC+ Out of Box Demo

So I spent some time to rebuild the out-of-box demo for the Genesys Zynq UltraScale MPSoC+ board.  Not everything worked for me right away, so I made this post to include all the things I did to get it to work.:

My system:

  • Windows 10
  • Windows Subsystem for Linux 2
  • Ubuntu 18.04 (<= Ubuntu 20 does not work unless you make a lot of changes)

References:

These are comments generated after following this guide:

Run Out of Box Demo

I followed the instructions on the page linked above and everything worked and the instructions were very easy to follow.  Some things to keep in mind:

  • I used the wrong serial port and had to deal with some issues killing that Putty Window.
  • Looks like sshd is not automatically configured/turned on for the PetaLinux distribution.
  • The default configuration mounts to root filesystem in RAM – aka – initramfs.  So if you make any changes rebooting will not work.

After connecting I noted my MAC address by running ‘ip a’ as the tutorial mentioned and set up my router to always give it the same ip address.

I then played around with setting some LEDs on and off by running the command:

for i in {0..4}; do uio-test -t led -i $i -v 1; done


Part 1 – Rebuilding the Out of Box Hardware Design

Step 1 – Create a directory for work

I used WSL 2 running Ubuntu 18, and I created a directory for my work on my regular windows/ntfs partition:

cd /mnt/c/work
mkdir -p Genesys/Rebuild
cd Genesys/Rebuild

Step 2 – Clone Hardware Design

Then I cloned the source code for the hardware design – making sure to get all submodules.  Well, there is only one submodule, but that’s fine.

git clone --recurse git@github.com:Digilent/Genesys-ZU-OOB-hw.git

(Browse the repository here: https://github.com/Digilent/Genesys-ZU-OOB-hw)

Here are some notes about git and sub-modules:

You can clone the code this way to get all sub-modules:

git clone --recurse <git-url>

but if you have already cloned the repository and want to get the submodules without re-cloning:

git submodule update --init --recursive

You can verify this by looking at the .gitmodules files in the root of the repository, it should look like this:

cat .gitmodules

[submodule "repo/vivado-library"]
path = repo/vivado-library
url = https://github.com/Digilent/vivado-library.git
branch = master

And you can also verify the code was downloaded with:

ls -l repo/vivado-library

Total space used after a fresh cloine with the sub-module: 148 Mebabytes

Step 3 – Start Vivado

In the Tcl Console (pronounced ‘tickle’) go to the directory where the Genesys-ZU-OOB-hw git repository has been cloned to:

cd C:/work/Genesys/Rebuild/Genesys-ZU-OOB-hw/

(Vivado has some great auto-complete, just press tab)

Step 4 – Re-create Out-of-Box Project

Then source the create_project.tcl file.

source ./proj/create_project.tcl

Step 5 – Build the Vivado Project

Just click ‘Generate Bitstream’

Took around 15 minutes on my computer, relatively modern desktop – around 6 years old.

Step 6 – Export Hardware

Click File->Export->Export Hardware

 

Make sure you click ‘include bitstream’

The HDF file gets placed in the following directory:

C:\work\Genesys\Rebuild\Genesys-ZU-OOB-hw\proj\GZU3EG_demo.sdk

Part 2 – Building the PetaLinux Image

Caveats:

  • Your distribution of Linux is important
  • WSL (Windows Subsystem for Linux) is good, but not perfect, so be careful using it.

I followed the instructions using WSL 2 using Ubuntu 18.04

Step 1 – Install PetaLinux for your Distribution

I used Ubuntu 18.04 LTS running inside WSL 2 with the following updates:

sudo apt-get install -y gcc git make net-tools libncurses5-dev tftpd zlib1g-dev libssl-dev flex bison libselinux1 gnupg wget diffstat chrpath socat xterm autoconf libtool tar unzip texinfo zlib1g-dev gcc-multilib build-essential libsdl1.2-dev libglib2.0-dev screen pax gzip python
 
Troubleshooting:
  • To install zlib1g:i386
    • sudo dpkg –add-architecture i386
    • sudo apt-get update
    • sudo apt-get install zlib1g:i386

Then make sure you copy the petalinux-v2019.1-final-install.run file to a non-NTFS mount:

sudo mkdir -p /opt/pkg/petalinux/2019.1
sudo chown john:john /opt/pkg/petalinux/2019.1
bash ./petalinux-v2019.1-final-install.run /opt/pkg/petalinux/2019.1

Step 2 – Source the Petalinux settings.sh file

source /opt/pkg/petalinux/2019.1/settings.sh
echo ${PETALINUX}
(Check for the PETALINUX environment variable to verify)
echo ${PETALINUX}

Step 3 – Clone the Repository

cd
mkdir -p Genesys/Rebuild
cd Genesys/Rebuild
git clone git@github.com:Digilent/Genesys-ZU-OOB-os.git
cd Genesys-ZU-OOB-os
For this to work, you should not be on an NTFS partition, there are some  issues with PetaLinux config tools.  Hopefully by the time you read this these issues are fixed.

Step 4 – Configure PetaLinux

Go to where you have cloned the OS repository (Genesys-ZU-OOB-os) and run the command:
 
petalinux-config --get-hw-description= /mnt/c/work/Genesys/Rebuild/Genesys-ZU-OOB-hw/proj/GZU3EG_demo.sdk/
 
Go through this DOS-like menu system and explore.  I made the following changes:
 
 
Write image to tftp root directory
  • Check TFTP destination
    • Image Packaging Configuration —>
      • Check “Copy final images to tftpboot”
      • Set tftpboot directory to /mnt/c/TFTP-Root/tftpboot/zuca-3eg

Click Exit and let it run

Now configure the rootfs
petalinux-config -c rootfs
  • Enable the ssh server
    • Filesystem Packages —>
      • console —>
        • network —>
          • dropbear —>
            • Enable dropbear
          • Admin —>
            • sudo —>
              • Enable sudo
Create a Regular User:
 
Edit the last line of the file:
 
nano project-spec/meta-plnx-generated/recipes-core/images/petalinux-user-image.bb
 
to contain:
 
EXTRA_USERS_PARAMS = "usermod -P password root; useradd -P password john;"

Step 5 – Build the Image

Just run petalinux-build

time petalinux-build

Took around 20 minutes on my Desktop with (24GB Ram and  an Intel i7-4930K)

Step 6 – Package

petalinux-package --boot --force --fsbl images/linux/zynqmp_fsbl.elf --fpga images/linux/system.bit --u-boot

Step 7 – Copy Files to SD Card

Copy the BOOT.BIN and image.ub to the root of the SD Card – make sure the SD Card is FAT32 formatted.

Step 8 – Ssh to Genesys Board

I looked up and found the ip address of my board in my local router and it is ‘192.168.1.203’, I was able to ssh in as user john with password password.

Now you can play around with the commands I mentioned at the start of this article.

But what about the SYZYGY connector and 10 gigabit ethernet? If I just plug in it, how will I know if it is plugged in correctly and getting appropriate data?

I don’t know.  Perhaps I am better off spending my time proving out how you can use LabVIEW FPGA along with the IP Export utility to show how you can parse FIX messages using an FPGA, and without Verilog/VHDL…

SZG-DUALSFP Update

I went to the Opal Kelly website again and noticed that there are a lot of menu options that I previously did not notice at the top menu.

I found a sample board that uses their SZG-DUALSFP board:

XEM7320

So now I can read the documentation for this board and be on my way!

I also had some fun reading the specification documents for the SYZYGY specification, the SZG-DUALSFP board, and for the Finisar Tranceiver (Model #FTLF8524P2BNV)

And I also discovered a Community Forum as well, where I could post any questions as well as any of my findings:

https://forums.opalkelly.com/

 

 

 

SZG-DUALSFP Howto?

So I have the Genesys Zynq UltraScale + MPSoC board, I bought the SZG-DUALSFP from Opel Kelly, and I want to figure out how to wire this thing up.

What pin goes where? I dunno.  I spent some time reading the SFP+ specification.  Everything makes sense.  Then I read through the SYZYGY specification.  Again, things make sense.

So what does the interface look like? Anybody know?

One though is to look at a sample from a similar board that uses an FMC based SFP connector.

And then I was reminded of the book “How Would You Move Mount Fuji” – a book about interviewing at Microsoft.  It included questions asked at Microsoft – including How Would You Move Mount Fuji.  Rename it? How many dump trucks?  All about out-of-the-box thinking.

Lesson? Who said I need to use this Genesys board.  I may have to switch to a more expensive board that has an SFP connector integrated.  Or maybe I should just look at a sample from such a board, and then everything will become clear.

I think I will go with the latest NetFPGA board.  They seem to support the open-source community and Universities well.

References:

Zynqberry Board Pause

After my previous post showing how to use the NI LabVIEW FPGA IP Export Utility to run LabVIEW FPGA code on a Zynqberry (http://fpganow.com/index.php/2020/09/28/zynqberry-with-breakout-board-and-labview/), I continued following the examples I could find on the internet and was able to connect to the board by using the PS (Processing System) built-int UART, and to communicate to the GPIO by using C code.

Then I wanted to access the PHY or the ETH pins directly and to map them to some LabVIEW IP have that can function as an Ethernet MAC with some IP and UDP/TCP processing.

After stumbling upon this post on hackster.io:

https://www.hackster.io/news/an-fpga-take-on-the-raspberry-pi-petalinux-on-the-zynqberry-67dd421d25aa?fbclid=IwAR1l1ZmnCwhxk3aGbeGyPZGBNChTaLKoGMYXj52ur3QeTc3I8IaV4ZRwI6g

I realized that I cannot access the pins of the PHY or onboard Ethernet MAC directly.  This kinds of defeats the whole purpose of what I am trying to do, and is the main reason why I am stopping my work with the Zynqberry and will return to it at a later time.

Anyway, here is a list of my references:

This post helped me run a basic C program on the Zynqberry that I can talk to using the UART.

https://www.knitronics.com/the-zynqberry-patch/getting-started-with-the-zynqberry-in-vivado-2018-2

Here is an official forum on the Trenz Electronic’s website – manufacturer of the Zynqberry board.  I tried registering for an account and am still waiting for the confirmation email two hours later.  Probably because their mail servers and gmail’s servers don’t like each other.

https://forum.trenz-electronic.de/index.php/board,2.0.html

I also found a cool online schematic generator:

https://www.circuitlab.com/editor/#

Here is another guide I read during the start of my journey with the Zynqberry board:

https://www.digikey.com/eewiki/display/Motley/Getting+Started+with+the+ZynqBerry

A Petalinux guide that I have yet to follow:

https://www.instructables.com/id/Getting-Started-With-PetaLinux/

Yoiu can look up the pins used in your constraints file on this page:

https://wiki.trenz-electronic.de/display/PD/TE0726+TRM

And finally, a link to a site describing the ULPI specification, which as per the hackster.io article mentioned above is the only way the FPGA on the Zynqberry can interface to the ethernet port.

mentor.com/products/ip/usb/usb20otg/phy_interfaces

Zynqberry with Breakout Board and LabVIEW

Source Code:

https://github.com/fpganow/Blink_LEDS

Introduction

There is a saying out there that goes ‘what are you going to do with an FPGA, blink a bunch of LEDs?’

Well… that saying is true.  Today I purchased a breakout board for the Zynberry and found an excellent guide on how to do just that:

But I am different and I am going to do more than just ‘blink a bunch of LEDs’.  I am going to do something useful.  <= It’s a joke… hahaha… Okay, not only am I going to blink a bunch of LEDs by using an FPGA, I am going to do it by using LabVIEW FPGA *and* by having that LabVIEW ‘code’ run on the Zynqberry, all at the same time!

For the first part of this demo, I had to re-learn a bunch of things that I learned in my High School electronics class (thank you Bronx Science – www.bxscience.edu).  What did I re-learn? How to power an LED without shorting the thing out… <= that was another joke hahaha. I hope you laughed.  Anyway, in the end, I used the breadboard provided by some electronics kit, along with three regular LEDs, one RGB LED, some push buttons and several 220 Ohm resistors.  For testing I brought power to this breakout board by using a regular battery pack and the Breadboard 5v/3v Power Supply Kit made by inland.  This is not important right now, so I will cover what I did in another post.

<TODO: Insert the link here…>

List of Parts:

I purchased everything from the Flushing Microcenter, which in my opinion has become a very suitable replacement for Radio Shack.

You don’t need to buy exactly what I did, but you will need the following components:

  • 2 x LEDS
  • 2 x220 Ohm Resistors
  • A couple of jumper cables
  • A Raspberry Pi 2 breakout board

I got these components from the following kits:

  • Inland Breadboard 5v/3v Power Supply Kit
  • Inland Electronic Parts Pack (KN3B)
  • MCM Electronics 40 Pin GPIO Breakout and Cable for Raspberry Pi

Pictures of the Boxes:

Why pictures? Well, because these parts seem so generic that I can’t even find them online for sale. 

Simple Example

The TL;DR for this one is – Connect the positive pin of the power bank to a 220 Ohm resistor, then the resistor to the positive end of the LED, then the negative end of the LED to ground.  Why? Because if you wire an LED directly to the +3.3V you will likely short it out.

The LabVIEW Part

Okay, so now that I gave myself a nice refresher on using electronics, while having fun, which is the most import part I then started to do something similar but with LabVIEW FPGA and the NI LabVIEW FPGA IP Export Utility.

I created a LabVIEW FPGA project using LabVIEW 2020 (32-bit version) and added a target that uses a Zynq family FPGA such as the Real-Time Compact RIO part cRio-9063.  The following screenshots should be sufficient if you have some LabVIEW FPGA experience.  If you do not, you will need to get some.  I would like to provide a more in-depth guide on that at some point.

 

LabVIEW FPGA IP Export Utility Section

So what does “Export VI to Netlist File” do? It creates two files.  A Xilinx dcp file, which I believe stands for “design checkpoint”, and  corresponding vhdl wrapper file for it.  Now these 2 files have the same name, but with a different extension, cand this file name is like a C++ function that has been mangled.  Which means that if you want to keep things simple, just call the VI something simple and short like “adder”, instead of “My NI LabVIEW to FPGA to Vivado Wrapper for blah blah blah”.  Anyway, the design above generates two files that get placed in to the C:\NIFPGA\compilation directory.  The name of the sub-directory will again follow some sort of name-mangling convention.  For me I have:

 

 

Vivado Section

Now create a Vivado project and make sure you are using the same version of Vivado as LabVIEW is using.  Since I am using LabVIEW 2020, the version of Vivado is 2019.  You can use the version that is packaged with LabVIEW, or you can download it yourself.  I chose to download it myself so I get whatever NI has decided or had to strip out as part of their agreement to distribute with LabVIEW.

Zynqberry Board Parts

You should install the Zynqberry board parts file.

From the Trenz Electronics homepage for the Zynqberry:

Download one of the Reference Designs for a version of Vivado close to 2019.1

Extract the zip file and look for the board_files directory, and it should contain two directories, in my case it is:

  • TE0726
  • TE0726_7S

You want to copy these directories to your Vivado installation to the C:\xilinx\Vivado\2019.1\data\boards\board_files directory. My directory looks like this:

 

Vivado Create Project

 

I hope you have some experience using Vivado, if not I will try to include enough information for you.  (Please comment below if anything is unclear, just reference the picture # and the title heading)

 

 

 

 

 

 

 

 

Vivado Block Design

I hope you have created a Block Design before.  It is cool. It reminds me somewhat of LabVIEW, but coming from a ‘text-based’ programming point of view. Follow these pictures and create a Block Design in your Vivado project which will map to what occurs on the Zynqberry board.  To the professional VHDL developers out there, yes, I am aware that I may not need to include the Zynq Processor.  I say this only now… as I am writing this post.


Add the LabVIEW Exported IP

Add the LabVIEW Exported IP to the top-level VHDL Module

Modify the my_top_level.vhd file to look like this picture:

paste the following:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
— Uncomment the following library declaration if using
— arithmetic functions with Signed or Unsigned values
–use IEEE.NUMERIC_STD.ALL;
 
— Uncomment the following library declaration if instantiating
— any Xilinx leaf cells in this code.
–library UNISIM;
–use UNISIM.VComponents.all;
 
entity my_top_level is
  Port (
    GPIO_0_tri_i : in STD_LOGIC_VECTOR ( 7 downto 0 );
    GPIO_1_tri_o : out STD_LOGIC_VECTOR ( 7 downto 0 )
);
end my_top_level;
 
architecture Behavioral of my_top_level is
  component NiFpgaIPWrapper_LabVIEW_Echo is
    port (
      reset : in std_logic;
      enable_in : in std_logic;
      enable_out : out std_logic;
      enable_clr : in std_logic;
      ctrlind_00_Data_in_U8 : in std_logic_vector(7 downto 0);
      ctrlind_01_Data_out_U8 : out std_logic_vector(7 downto 0);
      Clk40 : in std_logic
    );
  end component NiFpgaIPWrapper_LabVIEW_Echo;
 
  signal signal_clock: STD_LOGIC;
  signal echo_signal_enable_out: STD_LOGIC;
 
begin
 
ni_echo_i: component NiFpgaIPWrapper_LabVIEW_Echo
  port map(
    reset => ‘0’,
    enable_in => ‘1’,
    enable_out => echo_signal_enable_out,
    enable_clr => ‘0’,
—    ctrlind_00_Data_in_U8 => “00011100”,
    ctrlind_00_Data_in_U8 => GPIO_0_tri_i(7 downto 0),
    ctrlind_01_Data_out_U8 => GPIO_1_tri_o(7 downto 0),
    Clk40 => signal_clock
  );
 
end Behavioral;

Add Master Constraints File

 

Or cut and paste the following:

# LVCMOS33 because we are using 3.3V
set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_0_tri_i[*]}]
 
# PULLDOWN low makes sure all unwired inputs are 0 or false
set_property PULLDOWN TRUE [get_ports {GPIO_0_tri_i[*]}]
 
set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_0_tri_i[*]}]
set_property PACKAGE_PIN H14 [get_ports {GPIO_0_tri_i[7]}]
set_property PACKAGE_PIN J13 [get_ports {GPIO_0_tri_i[6]}]
set_property PACKAGE_PIN J15 [get_ports {GPIO_0_tri_i[5]}]
set_property PACKAGE_PIN N14 [get_ports {GPIO_0_tri_i[4]}]
set_property PACKAGE_PIN R15 [get_ports {GPIO_0_tri_i[3]}]
set_property PACKAGE_PIN R13 [get_ports {GPIO_0_tri_i[2]}]
set_property PACKAGE_PIN R12 [get_ports {GPIO_0_tri_i[1]}]
set_property PACKAGE_PIN L12 [get_ports {GPIO_0_tri_i[0]}]
 
set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_1_tri_o[*]}]
set_property PACKAGE_PIN K11 [get_ports {GPIO_1_tri_o[7]}]
set_property PACKAGE_PIN K13 [get_ports {GPIO_1_tri_o[6]}]
set_property PACKAGE_PIN L15 [get_ports {GPIO_1_tri_o[5]}]
set_property PACKAGE_PIN L14 [get_ports {GPIO_1_tri_o[4]}]
set_property PACKAGE_PIN M15 [get_ports {GPIO_1_tri_o[3]}]
set_property PACKAGE_PIN L13 [get_ports {GPIO_1_tri_o[2]}]
set_property PACKAGE_PIN M14 [get_ports {GPIO_1_tri_o[1]}]
set_property PACKAGE_PIN P15 [get_ports {GPIO_1_tri_o[0]}]

Generate Bitstream

 

Program and Run!

Pictures….

 

Zynqberry Update

So I followed the Zynqberry tutorial here:

https://www.knitronics.com/the-zynqberry-patch/getting-started-with-the-zynqberry-in-vivado-2018-2

And was able to get a basic Xilinx SDK application working on my Zynqberry, but with a twist… I used the NI LabVIEW IP Export tool to incorporate some LabVIEW code.  For now a simple adder that just adds 2 8-bit unsigned integers and outputs a 16-bit unsigned integer.

Anyway, the key takeaways are:

  • Follow the tutorial exactly and re-read it in case you have any confusion
  • Wrap up the default block design using my wrapper

Parse FIX Messages Part 1

For those unfamiliar with the FIX protocol, see:

The FIX Protocol transfers data uncompressed and in ASCII form.  The following data types are transferred like so:

Integer Value

To send the Integer 1,423, the TCP stream would look like this:

Index ASCII Hex
0 ‘1’ 0x31
1 ‘4’ 0x34
2 ‘2’ 0x32
3 ‘3’ 0x33

Date Time Value

To send the Date Time value pair “June 4th, 1998 2:58:48 PM”, the TCP stream would look like this:

Index ASCII Hex
0 ‘1’ 0x31
1 ‘9’ 0x39
2 ‘9’ 0x39
3 ‘8’ 0x38
4 ‘0’ 0x30
5 ‘6’ 0x36
6 ‘0’ 0x30
7 ‘4’ 0x34
8 ‘-‘ 0x2D
9 ‘1’ 0x31
10 ‘4’ 0x34
11 ‘:’ 0x3A
12 ‘5’ 0x35
13 ‘8’ 0x38
14 ‘:’ 0x3A
15 ‘4’ 0x34
16 ‘8’ 0x38
17 <SOH> 0x1

A very simple thing I can do is to read the incoming TCP stream and look for any integer and datetime values and replace them with a 32-bit Integer for Integer Values, and two 32-bit Integers for the Date Time Values.  So:

Incoming FIX stream looks like this:

( is how the SOH or ASCII character 1 appears in a text editor)

9=15452=19980604-14:58:48

Integer Value

Integer value does not really save much for a small number, but that is okay for now:

Integer field in ASCII format takes up 6 bytes:

(And the text based version in case you want to cut-and-paste)

39 3D 9A 01 

After converting this using an FPGA, it would take up only 4 bytes:

Date Time Value

Now the Date Time value however has a lot of space for saving… it can go from using 21 bytes to using 12 bytes.  Additionally, the real savings is in the time it takes to parse this on a regular processor and in the time it takes to convert it to an appropriate type in the user-mode application.

35 32 3D 01 30 E1 3C 00 02 39 B8 01

The FPGA-converted value only uses 11 bytes:

What does this mean? If we are using a programming language that stores Date Time values as 2 32-bit Integers, we can convert the ASCII stream directly into this format.  If on the other hand we are using a custom data type that stores it using the UNIX epcoh time, we can convert it directly to that.

Or, what if we don’t care about the Date and want to discard that part of the message altogether? We can do that all in the FPGA as the data is coming in.  No need for us to even read the entire message in to memory, we can just do this as it comes in.

So I created a LabVIEW FPGA project that reads a text file which contains the raw FIX message or messages, and passes them down to the FPGA where I parse the data and convert each field, value pair into an optimized key, value pair and to send it back up to the host.

Here is a screenshot of a sub-VI that parses data coming in and converts it into an Integer Value.  So let’s say we are reading a FIX message and want to get the Integer value of the field number:

(for reference)

8=FIX.<Version><SOH> … <FieldNum>=<FieldValue><SOH> … 

What does the above LabVIEW FPGA screenshot mean?

It means that on each clock cycle, Data_in has an unsigned 8-bit integer representing the data coming in from the data stream, and Reset_in is a boolean value telling us if we should reset the current value being stored/saved.

As for the output, the Valid boolean is set once and only once and that is when the SOH character is encountered, and the Integer Value is set to the appropriate value and is held that way until Reset_in is set to true again.

Now what would this look like in VHDL?  I don’t know, but it will take me some time to implement it, and some more time to create a test bench, and even more time to create test values and cases for this.  But with LabVIEW? I just drew it and used existing LabVIEW tools to pass data through it.  Go LabVIEW.

In upcoming articles, I will expand this code to handle entire FIX protocol messages, which include:

Heartbeat

8=FIX.4.19=11235=049=BRKR56=INVMGR34=23552=19980604-07:58:28112=19980604-07:58:2810=157

LogOn

8=FIX.4.29=6135=A34=149=EXEC52=20121105-23:24:0656=BANZAI98=0108=3010=003

Indicator of Interest (IOI)

8=FIX.4.29=15435=649=BRKR56=INVMGR34=23652=19980604-07:58:4823=11568528=N55=SPMI.MI54=227=20000044=10100.00000025=H10=159

For those that wish to follow, find me on github at:

https://github.com/fpganow/FIXParser