{"id":1354,"date":"2021-03-22T02:42:17","date_gmt":"2021-03-22T02:42:17","guid":{"rendered":"https:\/\/fpganow.com\/?page_id=1354"},"modified":"2021-05-15T19:34:36","modified_gmt":"2021-05-15T19:34:36","slug":"parse-bats-messages-in-an-fpga","status":"publish","type":"page","link":"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/","title":{"rendered":"Part 2: Parse BATS (PITCH) Market Data in an FPGA"},"content":{"rendered":"\n<p><em>Last Edit: Sunday, March 21st, 2021<\/em><\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_79_2 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a140d3f27a00\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a140d3f27a00\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#High_Level_View\" >High Level View<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#References\" >References<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#My_Hardware_and_Software\" >My Hardware and Software<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Interface\" >Interface<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Input\" >Input<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Data_Types\" >Data Types<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#LabVIEW\" >LabVIEW<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#VHDL\" >VHDL<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Output\" >Output<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Data_Types-2\" >Data Types<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#LabVIEW-2\" >LabVIEW<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#VHDL-2\" >VHDL<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Top-Level_Implementation\" >Top-Level Implementation<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#State_Machine\" >State Machine<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#LabVIEW_State_Machine\" >LabVIEW State Machine<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Close_up_for_Add_Order_States\" >Close up for Add Order States<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Read_Message_Type_and_Length_State\" >Read Message Type and Length State<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Simulation_with_Vivado_Simulator\" >Simulation with Vivado Simulator<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Simulation_with_LabVIEW_Simulator\" >Simulation with LabVIEW Simulator<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/#Instructions_for_Running\" >Instructions for Running<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"High_Level_View\"><\/span>High Level View<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>In today&#8217;s post, I will go over how I used <a href=\"https:\/\/www.ni.com\/en-us\/support\/downloads\/software-products\/download.labview-fpga-ip-export-utility.html#345666\" target=\"_blank\" rel=\"noopener\"><strong>LabVIEW FPGA<\/strong><\/a>, along with the <a href=\"https:\/\/www.ni.com\/en-us\/support\/downloads\/software-products\/download.labview-fpga-ip-export-utility.html#345666\" target=\"_blank\" rel=\"noopener\"><strong>LabVIEW FPGA IP Export Utility<\/strong><\/a> to generate a netlist that parses and normalized <a href=\"https:\/\/cdn.cboe.com\/resources\/membership\/US_EQUITIES_OPTIONS_MULTICAST_PITCH_SPECIFICATION.pdf\" target=\"_blank\" rel=\"noopener\">BATS Multicast PITCH<\/a> Market Data messages.<\/p>\n<p>You can use this netlist on non-NI hardware, as long as I export the netlist for the appropriate Xilinx Family\/Series.<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/High_Level.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1313 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/High_Level.png\" alt=\"\" width=\"857\" height=\"125\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/High_Level.png 857w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/High_Level-300x44.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/High_Level-768x112.png 768w\" sizes=\"auto, (max-width: 857px) 100vw, 857px\" \/><\/a><\/p>\n<p>This assumes that you already are using an FPGA &#8220;Smart-NIC&#8221;, sometimes known as a FPGA Accelerated Network Card that has a valid BATS Multicast PITCH feed.&nbsp; This is a Proof-of-Concept where you can connect a UDP payload to this IP and get a normalized version of each Market Data message that can be used for building an Order Book in the FPGA in the style of your choosing.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"References\"><\/span>References<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ul>\n<li><a href=\"https:\/\/www.ni.com\/en-us\/shop\/software\/products\/labview-fpga-module.html#:~:text=LabVIEW%20FPGA%20is%20a%20software,fidelity%20simulator%2C%20and%20debugging%20features.\" target=\"_blank\" rel=\"noopener\">LabVIEW FPGA (on ni.com)<\/a><\/li>\n<li><a href=\"https:\/\/www.ni.com\/en-us\/support\/downloads\/software-products\/download.labview-fpga-ip-export-utility.html#345666\" target=\"_blank\" rel=\"noopener\">LabVIEW FPGA IP Export Utility<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/fpganow\/arty_bats\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/fpganow\/arty_bats<\/a><\/li>\n<li><a href=\"https:\/\/cdn.cboe.com\/resources\/membership\/US_EQUITIES_OPTIONS_MULTICAST_PITCH_SPECIFICATION.pdf\" target=\"_blank\" rel=\"noopener\">BATS Multicast PITCH Specification<\/a><\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"My_Hardware_and_Software\"><\/span>My Hardware and Software<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>I am using a cheap Arty A100T ($250 USD) development board along with LabVIEW FPGA 2020 (non-SP1 version)<\/p>\n<ul>\n<li><a href=\"https:\/\/store.digilentinc.com\/arty-a7-artix-7-fpga-development-board\/\" target=\"_blank\" rel=\"noopener\">Arty A7: Artix-7 FPGA Development Board<\/a><\/li>\n<li><a href=\"https:\/\/www.ni.com\/en-us\/support\/downloads\/software-products\/download.labview-fpga-module.html#346249\" target=\"_blank\" rel=\"noopener\">LabVIEW FPGA Module<\/a><\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Interface\"><\/span>Interface<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Like all FPGA IP, the inputs and outputs are based on connecting wires to input and output signals.&nbsp; On each clock cycle, you usually wire an &#8216;input valid&#8217; signal along with several signals indicating the values, while on the output side, you read the same &#8211; a signal indicating that the output is valid along with a few more signals for the respective values.&nbsp; This is a very simple interface, as opposed to a FIFO where a packet of data is sent with 1 or more elements.&nbsp; In summary &#8211; one input per clock cycle, and one output per clock cycle.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Input\"><\/span>Input<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The input to the IP is an AXI-like interface that is suitable for both LabVIEW FPGA and Verilog\/VHDL designs:<\/p>\n<ol>\n<li><strong>Data (u8)<\/strong> &#8211; A single byte of data.&nbsp; With some modifications, this can be converted to an array of 8 bytes, or a 64-bit unsigned integer, which is what 10 Gigabit data comes in as.&nbsp; (If you know enough LabVIEW FPGA, you will understand the distinction between a 64-bit unsigned integer and a fixed-size array of 8 bytes)<\/li>\n<li><strong>Data_Valid<\/strong>&nbsp;<strong> (Boolean)<\/strong> &#8211; Just a signal that indicates whether data is valid for the current clock cycle.<\/li>\n<li><strong>Reset (Boolean)<\/strong> &#8211; Resets the internal state of the IP.&nbsp; Takes 1 clock cycle for the IP to reset.<\/li>\n<li><strong>Ready_for_Udp_Input (Boolean)<\/strong> &#8211; Specifies that the IP is ready for new data.<\/li>\n<\/ol>\n<h4><span class=\"ez-toc-section\" id=\"Data_Types\"><\/span>Data Types<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Input.Interface-1.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1336 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Input.Interface-1.png\" alt=\"\" width=\"442\" height=\"143\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Input.Interface-1.png 442w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Input.Interface-1-300x97.png 300w\" sizes=\"auto, (max-width: 442px) 100vw, 442px\" \/><\/a><\/p>\n<h4><span class=\"ez-toc-section\" id=\"LabVIEW\"><\/span>LabVIEW<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>If you are using this IP from a LabVIEW design, you would have to wire in the following 4 signals:<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.labview.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1316 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.labview.png\" alt=\"\" width=\"965\" height=\"376\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.labview.png 965w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.labview-300x117.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.labview-768x299.png 768w\" sizes=\"auto, (max-width: 965px) 100vw, 965px\" \/><\/a><\/p>\n<h4><span class=\"ez-toc-section\" id=\"VHDL\"><\/span>VHDL<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>If you are using this IP from Vivado, you will have to import the following VHDL &#8216;entity&#8217;.&nbsp; I have highlighted the entity name and the input signals.<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.vhdl_.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1319 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.vhdl_.png\" alt=\"\" width=\"1374\" height=\"795\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.vhdl_.png 1374w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.vhdl_-300x174.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.vhdl_-1024x592.png 1024w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/input.interface.vhdl_-768x444.png 768w\" sizes=\"auto, (max-width: 1374px) 100vw, 1374px\" \/><\/a><\/p>\n<h3><span class=\"ez-toc-section\" id=\"Output\"><\/span>Output<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The output interface follows the same paradigm as the input interface and has all of the elements of an OrderBook command available in 1 clock cycle.<\/p>\n<ol>\n<li><strong>Ready_for_OrderBook_Command<\/strong> &#8211; Tells the IP that is going to be reading the output signals that it is ready to receive a new OrderBook Command.<\/li>\n<li><strong>OrderBook_Command_Valid <\/strong>&#8211; Indicates whether a valid OrderBook command is present.<\/li>\n<li><strong>OrderBook_Command<\/strong> &#8211; This is the actual Command, which is the integer value of the LabVIEW Enum variable type.<\/li>\n<li><strong>Side<\/strong> &#8211; The ASCII value of the side (Buy &#8211; 0x42, Sell &#8211; 0x53)<\/li>\n<li><strong>Quantity<\/strong> &#8211; Number of shares<\/li>\n<li><strong>Executed_Quantity<\/strong> &#8211; Number of executed shares<\/li>\n<li><strong>Cancelled_Quantity<\/strong> &#8211; Number of cancelled shares<\/li>\n<li><strong>Price<\/strong> &#8211; Price<\/li>\n<li><strong>Symbol<\/strong> &#8211; Symbol represented as right-justified ASCII padded on the right with spaces<\/li>\n<li><strong>Order_Id<\/strong> &#8211; Order Id.<\/li>\n<\/ol>\n<h4><span class=\"ez-toc-section\" id=\"Data_Types-2\"><\/span>Data Types<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Output.Interface-1.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1337 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Output.Interface-1.png\" alt=\"\" width=\"510\" height=\"279\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Output.Interface-1.png 510w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Output.Interface-1-300x164.png 300w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/a><\/p>\n<h4><span class=\"ez-toc-section\" id=\"LabVIEW-2\"><\/span>LabVIEW<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>I have placed a comment box for each output-interface signal that corresponds to the name which is generated by the IP Export Utlity.<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.labview.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1324 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.labview.png\" alt=\"\" width=\"1438\" height=\"569\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.labview.png 1438w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.labview-300x119.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.labview-1024x405.png 1024w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.labview-768x304.png 768w\" sizes=\"auto, (max-width: 1438px) 100vw, 1438px\" \/><\/a><\/p>\n<h4><span class=\"ez-toc-section\" id=\"VHDL-2\"><\/span>VHDL<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>In order to import this IP in to your existing Vivado project, you will have to import the following entity using VHDL or Verilog.&nbsp; I have highlighted the output signals.&nbsp; (Note: by &#8216;output&#8217; signal, I mean signals related to getting the output from the IP, and not signals with a direction of &#8216;output&#8217;)<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.vhdl_.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1326 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.vhdl_.png\" alt=\"\" width=\"1397\" height=\"795\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.vhdl_.png 1397w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.vhdl_-300x171.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.vhdl_-1024x583.png 1024w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/output.interface.vhdl_-768x437.png 768w\" sizes=\"auto, (max-width: 1397px) 100vw, 1397px\" \/><\/a><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Top-Level_Implementation\"><\/span>Top-Level Implementation<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>So when looking at this IP in LabVIEW, you have to open the &#8216;bats.parser.ip.vi&#8217; VI and this is what you see.&nbsp; The 2 large boxes are single-cycle timed loops, and the wires connecting them are a VI-Scoped FIFO.&nbsp; A lot of the implementation details that would normally exist in a Vivado implementation have been abstracted by LabVIEW, and what you see below is the equivalent of at least 50 VHDL files.<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.Top_.Level_.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1328 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.Top_.Level_.png\" alt=\"\" width=\"1716\" height=\"1040\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.Top_.Level_.png 1716w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.Top_.Level_-300x182.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.Top_.Level_-1024x621.png 1024w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.Top_.Level_-768x465.png 768w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.Top_.Level_-1536x931.png 1536w\" sizes=\"auto, (max-width: 1716px) 100vw, 1716px\" \/><\/a><\/p>\n<h3><span class=\"ez-toc-section\" id=\"State_Machine\"><\/span>State Machine<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Everything inside the small box labeled <strong>&#8216;bats.parser.vi&#8217;<\/strong> from the screenshot above can be represented by the following state machine:<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/BATS_Pitch_Parser.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1322 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/BATS_Pitch_Parser.png\" alt=\"\" width=\"1286\" height=\"703\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/BATS_Pitch_Parser.png 1286w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/BATS_Pitch_Parser-300x164.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/BATS_Pitch_Parser-1024x560.png 1024w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/BATS_Pitch_Parser-768x420.png 768w\" sizes=\"auto, (max-width: 1286px) 100vw, 1286px\" \/><\/a><\/p>\n<h3><span class=\"ez-toc-section\" id=\"LabVIEW_State_Machine\"><\/span>LabVIEW State Machine<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The <strong>&#8220;Read Add Order&#8221;<\/strong> State from the state machine diagram above is represented in LabVIEW code with the following below:<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.State_.Machine.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1331 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.State_.Machine.png\" alt=\"\" width=\"1249\" height=\"863\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.State_.Machine.png 1249w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.State_.Machine-300x207.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.State_.Machine-1024x708.png 1024w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/LabVIEW.State_.Machine-768x531.png 768w\" sizes=\"auto, (max-width: 1249px) 100vw, 1249px\" \/><\/a><\/p>\n<h4><span class=\"ez-toc-section\" id=\"Close_up_for_Add_Order_States\"><\/span>Close up for Add Order States<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>In the &#8220;LabVIEW State Machine&#8221; diagram above, there is a box or <strong>Case-Structure<\/strong> inside the outer Case-Structure which has the <strong>MessageType<\/strong> wire plugged in to the Case Selector input.&nbsp; If the message type is <strong>ADD ORDER Long<\/strong>, it will execute the following code which parses the Quantity starting at index 15 and ending at index 19.<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.add_.order_.long_.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1332 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.add_.order_.long_.png\" alt=\"\" width=\"495\" height=\"384\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.add_.order_.long_.png 495w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.add_.order_.long_-300x233.png 300w\" sizes=\"auto, (max-width: 495px) 100vw, 495px\" \/><\/a><\/p>\n<p>If the Message Type is 0x22, the same variable &#8211; Quantity &#8211; will be read starting at index 15 and ending at index 17.&nbsp; The Quantity only takes up 16 bits in the specification, but since we are normalizing each message format, we are storing it in a 32-bit number.<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.add_.order_.short_.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1333 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.add_.order_.short_.png\" alt=\"\" width=\"485\" height=\"381\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.add_.order_.short_.png 485w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.add_.order_.short_-300x236.png 300w\" sizes=\"auto, (max-width: 485px) 100vw, 485px\" \/><\/a><\/p>\n<h4><span class=\"ez-toc-section\" id=\"Read_Message_Type_and_Length_State\"><\/span>Read Message Type and Length State<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>There are 3 wires coming in to this Case Structure, the top wire is a cluster &#8211; which is similar to a structure in C &#8211; contains all the values to be read in on each iteration, and to the right &#8211; the corresponding output values.<\/p>\n<p>On each loop iteration &#8211; or clock cycle &#8211; we read the input values, make some changes such as store the Message Type and modify the output values.&nbsp; As an example, on the first clock cycle, the &#8216;Message Counter (U8)&#8217; variable (or wire) has a value of 0, the Case Selector runs the loop for &#8216;0&#8217;, which causes it to store the length in the Message Length variable (or wire), then the Message Counter variable is incremented by one and the loop runs again.<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.ReadMsgTypeAndLength.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1334 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.ReadMsgTypeAndLength.png\" alt=\"\" width=\"1265\" height=\"859\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.ReadMsgTypeAndLength.png 1265w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.ReadMsgTypeAndLength-300x204.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.ReadMsgTypeAndLength-1024x695.png 1024w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/State.ReadMsgTypeAndLength-768x522.png 768w\" sizes=\"auto, (max-width: 1265px) 100vw, 1265px\" \/><\/a><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Simulation_with_Vivado_Simulator\"><\/span>Simulation with Vivado Simulator<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>You can take the netlist &#8211; <strong>NiFpgaAG_bats_parser_ip.vhd<\/strong> &#8211; and run a <strong>Vivado Testbench<\/strong> around it:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/fpganow\/arty_bats\/blob\/main\/vivado\/src\/ip\/NiFpgaAG_bats_parser_ip.vhd\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/fpganow\/arty_bats\/blob\/main\/vivado\/src\/ip\/NiFpgaAG_bats_parser_ip.vhd<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/fpganow\/arty_bats\/blob\/main\/vivado\/src\/hdl\/test\/bats_parser_tb.v\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/fpganow\/arty_bats\/blob\/main\/vivado\/src\/hdl\/test\/bats_parser_tb.v<\/a><\/li>\n<\/ul>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.one_.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1339 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.one_.png\" alt=\"\" width=\"1016\" height=\"1044\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.one_.png 1016w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.one_-292x300.png 292w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.one_-997x1024.png 997w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.one_-768x789.png 768w\" sizes=\"auto, (max-width: 1016px) 100vw, 1016px\" \/><\/a><\/p>\n<p>On my computer, I run it for 1 microsecond and I get my first &#8216;orderbook_command_valid&#8217; result.&nbsp; The test data is also included in the github repository.&nbsp; The test data is actually based on something I found in an old repository on github (<a href=\"https:\/\/github.com\/klon\/bats-pitch-parser\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/klon\/bats-pitch-parser<\/a>)<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/fpganow\/arty_bats\/blob\/main\/vivado\/src\/hdl\/test\/raw.pitch.dat\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/fpganow\/arty_bats\/blob\/main\/vivado\/src\/hdl\/test\/raw.pitch.dat<\/a><\/li>\n<\/ul>\n<p>Notice how the orderbook_command_valid value is true for only one clock cycle, and during that cycle all the values for an entire OrderBook command are also set.&nbsp; (I did not reset them to 0 after that, but this is a Proof-of-Concept&#8230;)<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.two_.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1340 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.two_.png\" alt=\"\" width=\"996\" height=\"676\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.two_.png 996w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.two_-300x204.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.Verilog.two_-768x521.png 768w\" sizes=\"auto, (max-width: 996px) 100vw, 996px\" \/><\/a><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Simulation_with_LabVIEW_Simulator\"><\/span>Simulation with LabVIEW Simulator<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Now running simulation from LabVIEW FPGA is a bit different.&nbsp; You are still writing an application using LabVIEW, but you start on the host, read a data file and pump the data in to the FPGA over a FIFO in much the same way that the FPGA would receive data from another source, which in our case would be a FIFO that replaces the Ethernet stream and UDP\/IP Parser.<\/p>\n<p>I clean things up by taking the results &#8211; which are the OrderBook Commands and display them in a easy-to-read processed format.<\/p>\n<p><a href=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.LabVIEW.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1342 size-full\" src=\"http:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.LabVIEW.png\" alt=\"\" width=\"1327\" height=\"649\" srcset=\"https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.LabVIEW.png 1327w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.LabVIEW-300x147.png 300w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.LabVIEW-1024x501.png 1024w, https:\/\/fpganow.com\/wp-content\/uploads\/2021\/03\/Simulation.LabVIEW-768x376.png 768w\" sizes=\"auto, (max-width: 1327px) 100vw, 1327px\" \/><\/a><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Instructions_for_Running\"><\/span>Instructions for Running<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Clone the source code repository,from Vivado source the arty_bats.tcl script:<\/p>\n<table style=\"border-collapse: collapse; width: 100%;\">\n<tbody>\n<tr>\n<td style=\"width: 100%;\">\n<p>git clone git@github.com\/FpgaNow\/arty_bats<\/p>\n<p>cd {x:\/arty_bats\/vivado}<\/p>\n<p>source .\/arty_bats.tcl<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last Edit: Sunday, March 21st, 2021 High Level View In today&#8217;s post, I will go over how I used LabVIEW FPGA, along with the LabVIEW FPGA IP Export Utility to generate a netlist that parses and normalized BATS Multicast PITCH Market Data messages. You can use this netlist on non-NI hardware, as long as I &#8230; <a title=\"Part 2: Parse BATS (PITCH) Market Data in an FPGA\" class=\"read-more\" href=\"https:\/\/fpganow.com\/index.php\/parse-bats-messages-in-an-fpga\/\" aria-label=\"Read more about Part 2: Parse BATS (PITCH) Market Data in an FPGA\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","footnotes":""},"class_list":["post-1354","page","type-page","status-publish"],"_links":{"self":[{"href":"https:\/\/fpganow.com\/index.php\/wp-json\/wp\/v2\/pages\/1354","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fpganow.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/fpganow.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/fpganow.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fpganow.com\/index.php\/wp-json\/wp\/v2\/comments?post=1354"}],"version-history":[{"count":12,"href":"https:\/\/fpganow.com\/index.php\/wp-json\/wp\/v2\/pages\/1354\/revisions"}],"predecessor-version":[{"id":1415,"href":"https:\/\/fpganow.com\/index.php\/wp-json\/wp\/v2\/pages\/1354\/revisions\/1415"}],"wp:attachment":[{"href":"https:\/\/fpganow.com\/index.php\/wp-json\/wp\/v2\/media?parent=1354"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}