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.
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.
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.
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.
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:
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:
Extract the zip file and look for the board_files directory, and it should contain two directories, in my case it is:
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:
— Uncomment the following library declaration if using
— arithmetic functions with Signed or Unsigned values
— Uncomment the following library declaration if instantiating
— any Xilinx leaf cells in this code.
entity my_top_level is
GPIO_0_tri_i : in STD_LOGIC_VECTOR ( 7 downto 0 );
GPIO_1_tri_o : out STD_LOGIC_VECTOR ( 7 downto 0 )
architecture Behavioral of my_top_level is
component NiFpgaIPWrapper_LabVIEW_Echo is
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);
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
The FIX Protocol transfers data uncompressed and in ASCII form. The following data types are transferred like so:
To send the Integer 1,423, the TCP stream would look like this:
Date Time Value
To send the Date Time value pair “June 4th, 1998 2:58:48 PM”, the TCP stream would look like this:
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)
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:
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:
[Updated]: It turns out there are 2 editions of this board, and it looks like the premium one with a 10 Gigabit SFP+ connector is not yet available in the USA. However, I did some research and the lesser version of this board – the 3EV – has a SYZYGY connector, which supports SFP+ peripherals.
So I ordered these 2 accessories and am awaiting a response from the manufacturer in case they actually do have one of the premium boards available:
If you have a bigger budget than that of a hobbyist, or are a hobbyist that is willing to spend more to create your own FPGA accelerated Network card, then read on.
So the Zynqberry board may look cool and all, but it is limited to a 100Mbit network connection. Now from all the 10 gigabit boards, I wanted to pick one that has that ‘hobbyist’ feel to it. Something I can put on my desk and connect it with USB to my desktop in order to program it. And if on the road, do the same with my laptop.
This board will allow me to test out with an actual 10 gigabit connection. I also have some code written somewhere that will do some basic parsing. So while I wait for this board and the Zynqberry to arrive, I will start doing some digging.
And how does “The Good, The Bad, and The Ugly” end?
“There are two kinds of people in the world, those with guns and those that dig. You dig.”
Well, I want to expand on this knowledge and say that:
“There are two kinds of developers in this world, those with LabVIEW FPGA and those that debug. You debug all day?”
So I just ordered this Zynq UltraScale board from Digilent. It cost $1,149.00.
I did some research looking for existing TCP/IP FPGA Cores. There are two basic types – 10 Gigabit and non-10 Gigabit. There is also a range of free and commercial solutions out there, and I’m sure the usual caveats apply. Free = no documentation or support, Commercial = super expensive. Anyway, here is what I discovered:
The most important thing is that data comes in using an AXI4-Lite or similar interface. What is an AXI4-Lite interface? Here is the official Xilinx documentation:
You can also simply think of it like this, on each clock cycle your FPGA reads the following signals:
For receiving data:
New Data is Available
New Data in the form of 64 bits or 8 bits
For sending data, the opposite:
I have new data
Here is the new data
No packet sizes, no lengths, nothing else. You have 8 bytes of new data on each cycle for 10 Gigabit connections, or 1 byte of new data on each cycle for the rest.
Here is a picture to make things easier to understand:
Of course, what if you are trying to send data and the TCP Core is not ready to send data for whatever reason? Be it busy, has no space in its send buffer or does not have a valid connection/place to send the data? Well, there is a ‘Ready’ signal that you have to read before sending data as described above.
As for reading data, you have to do the complementary operation by telling the TCP Core that you are ready to read data, and then the TCP Core sends you the data.
Anyway, here is a closed-source TCP FPGA core that is non-10 Gigabit:
If you want multiple sessions you have to instantiate multiple copies of the core
You set the parameters of your TCP connection by using registers
You send and receive data through a FIFO / AXI4-Lite interface
so this looks quite simple. I can take some data like a FIX or ITCH message, convert the date string, which in the FIX protocol is 20-something ASCII characters, convert them into a binary representation, and send out this data using a similar FIFO / AXI4-Lite interface. Where this outgoing FIFO goes is not of concern right now, however, keep in mind that it can be any of the following:
Operating System/kernel TCP/IP
Another portion of the FPGA
A user-mode application running on an embedded processor which is housing the FPGA.
I stumbled upon a board called the “Zynqberry” which is supposed to mimic a Raspberry Pi but with a Xilinx Zyn-7000 FPGA board present.
This board aims to be an FPGA-enabled version of the Raspberry Pi and comes with a 100MBit connector. Unfortunately it does not support 10 Gigabit. I mean, how could it with such a small footprint?
Anyway, this board will be perfect for me to demonstrate certain things that will make FPGA programming accessible to a hobbyist not willing to shell out thousands of dollars and to a student on a limited budget.
Here is a link to a detailed getting started guide:
Genesis ZU: Zynq Ultrascale+ MPSoC Development Board
Has 1 SFP+ Connector suitable for a 10 Gigabit connection.
FPGA: Zynq Ultrascale+ (XCZU3EG-SFVC784-1-E)
Pros: You can put the board on your desk and play around with other components.
Cons: You can’t plug it in to your system in a regular port. Has only 1 10 Gigabit port. However, there is a FMC connector which you can use to add other peripherals, including a board with an SFP+ connector.
Now you can run LabVIEW FPGA on the hardware of your choice with the new “LabVIEW FPGA IP Export Utility”.
That sounds great, but what’s that got to do with me? (quoting Rambo 3)
Step 1 – Pick a non-National Instruments FPGA Board
You will have to pick a non-National Instruments FPGA board that has an FPGA that uses Vivado (7 Series devices and above) and has a corresponding LabVIEW FPGA board that uses a device of the same family. What does same family mean? Well, a Virtex-7 chip such as the VX485T has the same family as the VX690T.
If you want to run LabVIEW on other hardware, you will have to pay for and upgrade to the premium version of this tool which exports to VHDL source code. (This does not appear to be available yet, as per the documentation they request that you email them. As for me? I am happy with the encrypted netlist for now, because it keeps things simpler and will allow for easier licensing.)
For this post, I am going to select the NetFPGA-1G-CML Kinex-7 FPGA Development Board, which has a Xilinx Kintex-7 XC7K325T FPGA. See:
Step 3 – Create a LabVIEW Project using this board
Create a project with the PXIe-7858R board as one of its targets, and make a very simple top-level vi. Here is a very simple VI Snippet:
Step 4 – Create a Build Specification
Right-click on the top-level vi and select ‘Create Build Specification’
And after you should see:
Step 5 – Create a Netlist Export
A new option is available under the right-click menu of the build specification called “Export to Netlist”
It runs the first steps that it normally does when you synthesize an FPGA project:
Be careful, the window just disappears and expects you to know where the netlist will be saved. (Hey, that’s much better than them sitting on it internally and not releasing it. And, this is one of those RTFM issues anyway…)
In my case, there is a Vivado Checkpoint file and a wrapper VHD file.
The code looks pretty cool. And remember the most important thing – ACTIVE HIGH!
-- VHDL wrapper for NiFpgaAG_pxie7868_dash_Top_dash_Level -- Generated by LabVIEW FPGA IP Export Utility -- -- Ports: -- reset : Reset port. Minimum assertion length: 1 base clock cycles. -- Minimum de-assertion length: 40 base clock cycles. -- enable_in : Enable in port. Minimum re-initialization length: 7 base clock cycles. -- enable_out : Enable out port. -- enable_clr : Enable clear port. -- ctrlind_00_B : Top level control "B", sync to Clk40, u32 -- ctrlind_01_A : Top level control "A", sync to Clk40, u32 -- ctrlind_02_SUM : Top level indicator "SUM", sync to Clk40, u32 -- Clk40 : Clock "40 MHz Onboard Clock", nominal frequency 40.00 MHz, base clock
library ieee; use ieee.std_logic_1164.all;
entity NiFpgaIPWrapper_pxie7868_dash_Top_dash_Level is port ( reset : in std_logic; enable_in : in std_logic; enable_out : out std_logic; enable_clr : in std_logic; ctrlind_00_B : in std_logic_vector(31 downto 0); ctrlind_01_A : in std_logic_vector(31 downto 0); ctrlind_02_SUM : out std_logic_vector(31 downto 0); Clk40 : in std_logic ); end NiFpgaIPWrapper_pxie7868_dash_Top_dash_Level;
architecture vhdl_labview of NiFpgaIPWrapper_pxie7868_dash_Top_dash_Level is
component NiFpgaAG_pxie7868_dash_Top_dash_Level port ( reset : in std_logic; enable_in : in std_logic; enable_out : out std_logic; enable_clr : in std_logic; ctrlind_00_B : in std_logic_vector(31 downto 0); ctrlind_01_A : in std_logic_vector(31 downto 0); ctrlind_02_SUM : out std_logic_vector(31 downto 0); Clk40 : in std_logic; tDiagramEnableOut : in std_logic ); end component;