Skip to content
Adam edited this page Feb 26, 2013 · 14 revisions

Table of Contents

Developers Guide

Attention: This guide applies to the 3.0.0 and above releases.

This guide explains the process of developing for the NetFPGA platform. The primary focus is on developing projects, although the lessons also apply to module development.

Overview

The NetFPGA platform consists of many elements including the physical hardware, hardware designs that are downloaded to the FPGA, software associated with a particular hardware design, general software tools for interacting with the hardware, and the simulation and synthesis environment for building new designs. Developers will most frequently develop new hardware designs to run on the FPGA and software for use with particular hardware projects.

Developers work with projects and modules. Projects are complete designs, consisting of a hardware component, tests (simulations and hardware regression tests), and associated software components. Modules are small reusable hardware units that are incorporated into projects.

The hardware component for a project is typically built by interconnecting a number of reusable modules and some project-specific HDL code. Some projects, notably some of the reference designs, are built entirely by assembling the reusable modules. The simulation and regression tests associated with a project are used to specify the features of the design and demonstrate the correctness of that design (as explained in Regression Tests). The software associated with a project allows the user to interact with the hardware in a meaningful way; for example in the Reference Router project, the software provides a command-line interface for manipulating the ARP and routing tables inside the hardware.

Modules consists of HDL code, specification of IP blocks built using the Xilinx Core Generator, and a specification of any registers that the module exposes. Registers and associated information are specified using an XML-based system; this system takes care of allocating memory for the registers within each module when the modules are integrated into projects.

The process below explains how to develop for NetFPGA platform using the new python based unified infrastructure for simulation and hardware testing. For information on using the previous Perl based testing infrastructure visit here.

NetFPGA Directory Structure

The directory structure of the NetFPGA source tree is as follows:

   netfpga                {Base directory}
      bin                 {Scripts for simulation/synthesis/register gen}
      bitfiles            {Compiled hardware bitfiles}
      lib                 {Libraries and software tools}
         C                {C libraries/programs}
         java             {Java libraries}
         Makefiles        {Makefile templates used for sim/synth}
         Perl5            {Perl libraries}
         python           {Python libraries}
         release          {XML files for packaging}
         scripts          {Utility scripts}
         verilog
            contributed   {Contributed Verilog modules}
            core          {Official Verilog modules}
         xml              {XML schemas}
      projects            {project directory}
         <project>        {contributed project}
            doc           {documentation}
            include       {project.xml, project specific module XML}
            lib           {Perl and C headers}
            src           {non-library verilog}
            sw            {Project-specific software}
            synth         {Synthesis directory (contains all .xco files)}
            test          {Unified (Hw/Sw) tests}

Creating a new project

A new project is created by following these steps:

  1. Create a new project directory inside netfpga/projects
  2. Update the NF_DESIGN_DIR directory to point to the new project directory. Example (Bourne shell syntax): export NF_DESIGN_DIR=$(HOME)/netfpga/projects/my_first_project (See the guide for more information.)
  3. Create the following directories inside the project directory: include, src, synth, and test. Optionally create doc, lib, and sw. (Note: lib will be automatically created when the register generation tool is run.)
  4. Create a project.xml file inside the include directory. See the Register System section below for more information.
  5. Add any library modules to the project.xml file.
  6. Write any project-specific Verilog and place inside the src directory.
  7. Write module-specific XML files for any new modules you have written and place in the include directory.
  8. In the new python testing infrastructure, simulation and hardware (previously regression) tests have been unified, so a test can be written once and run as either a simulation or hardware test, unless hardware specific functions are needed. Tests should be placed in a project's test directory. Test directories should be named both_&lt;major&gt;_&lt;minor&gt; if they can be run in both simulation and hardware, hw_&lt;major&gt;_&lt;minor&gt; if the test can only be run as a hardware test, and sim_&lt;major&gt;_&lt;minor&gt;; if the test can only be run as a simulation test. Neither major or minor can have underscores in the name, nor can they be blank.
  9. Copy the Makefile from the reference router synth directory into your synth directory.
  10. Synthesize the design by running make inside the synth directory.
  11. Write hardware tests and place them in the test directory. Run with nf_test.py (See Verification for more information.)
  12. Write any software and place inside the sw directory.
  13. Add documentation to the doc directory.
  14. Contribute your project if you think your project may be useful to others. See the Develop page for more information.
Note: The act of running simulations or synthesizing the project causes the registers to be regenerated. Use the nf_register_gen.pl tool if you want to regenerate registers without running simulation/synthesis.

Build system

The build system manages the process of compiling projects for simulation and synthesizing projects for download to the FPGA.

Build process

The following steps are undertaken during a build:

  1. Query the register system for a list of all modules used by the project.
  2. Instruct the register system to generate the registers. This involves reading the register descriptions for each module, allocating memory for all registers, and outputting that resultant allocation for use in Verilog, C, and Perl.
  3. Generate cores associated with each module and the project.
  4. Compile/synthesize the code associated with each module and the project.

Projects and reusable modules

As previously mentioned, the NetFPGA platform supports reusable hardware modules that can be incorporated into projects. The build system makes using modules extremely simple: a developer simply specifies which modules that they'd like included in their project and the build system allocates addresses for registers within each module, generates any necessary IP blocks, and includes the necessary source files during compilation.

Many new developers do not realize that modules are included as part of the compilation process; this causes confusion to many new developers when they look at the src directory of a project and see very few files, or even none at all. For example, reference router's src directory is completely empty; all of the functionality of the reference router is provided by the reusable modules.

The set of modules that a project uses is specified in the project's project.xml file (see Register System for more information). The nf:use_modules section of the XML files specifies which modules to include. Part of the use_modules section from the reference router is shown below:

<nf:use_modules>
	core/io_queues/cpu_dma_queue 
	core/io_queues/ethernet_mac 
	core/input_arbiter/rr_input_arbiter 
	core/nf2/generic_top 
	core/nf2/reference_core 
	... 
</nf:use_modules>

This section of code instructs the build system to use these modules: CPU DMA queues, Ethernet MAC, the generic top-level Verilog file ( generic_top), and the reference core. The reusable modules are located in the netfpga/lib/verilog directory. For example, the CPU DMA queues (specified as core/io_queues/cpu_dma_queue in the above code snippet), is located in netfpga/lib/verilog/core/io_queues/cpu_dma_queue.

Shared Makefiles

TBD. This section should discuss the shared makefiles.

Register system

This section provides an overview of the register system. Detailed information about the register system can be found on the Register System page.

The register system provides a mechanism for:

  • specifying the registers provided by each module
  • specifying the modules used by each project
  • generating a register map/memory allocation for each project
Information for each project (eg. name, list of modules, location of modules in memory space) and each module (eg. name, list of registers) is specified in an XML file. The register generation tool (=nf2_register_gen.pl) reads the XML file of the project and the XML files of the included modules, performs memory allocation, and then outputs a set of files with the memory allocation/register map to files for use in Verilog, C, and Perl.

project.xml

The project.xml file provides information about the project and specifies the list of shared modules used by the project. A sample XML file is shown below:

< ?xml version="1.0" encoding="UTF-8"? >
<nf:project xmlns:nf="http://www.NetFPGA.org/NF2_register_system" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.NetFPGA.org/NF2_register_system NF2_register_system.xsd ">
  <nf:name>Reference router</nf:name>
  <nf:description>Reference IPv4 router</nf:description>
  <nf:version_major>1</nf:version_major>
  <nf:version_minor>0</nf:version_minor>
  <nf:version_revision>0</nf:version_revision>
  <nf:dev_id>0</nf:dev_id>
  <nf:use_modules>
    core/io_queues/cpu_dma_queue
    core/io_queues/ethernet_queue
    contrib/ucsd/gig_eth_mac
    core/input_arbiter/rr_input_arbiter
    ...
  </nf:use_modules>
  <nf:memalloc layout="reference">
    <nf:group name="core1">
      <nf:instance name="device_id" />
      <nf:instance name="dma" base="0x0500000"/>
      <nf:instance name="mdio" />
      <nf:instance name="nf2_mac_grp" count="4" />
      <nf:instance name="cpu_dma_queue" count="4" />
    </nf:group>
    <nf:group name="udp">
      <nf:instance name="in_arb" />
      <nf:instance name="router_op_lut" />
      <nf:instance name="strip_headers" />
      <nf:instance name="output_queues" />
    </nf:group>
  </nf:memalloc>
</nf:project>

Line 1 specifies that this is an XML file.

Line 2 declares that we're working with a project and specifies the XML schema that this file is based on.

Lines 3 -- 8 provide information about the project. Name is a short textual description of the project. Description is a slightly longer description of what the project does. The version major, minor, and revision are used to tag the resultant bitfile; the information is placed in the Device ID module that is instantiated by default in each design. (This module can be queried to identify the currently active bitfile.) The device ID is also incorporated into the Device ID module; currently it serves no purpose other than acting as an opaque identifier.

Lines 9 -- 14 specify the shared modules to use. The modules are listed one per line between nf:use_module tags. Each module is located in the NF2/lib/verilog directory.

Lines 15 -- 29 specify the memory layout of the design, maps modules to particular regions of the address space, and specifies the number of instances for each module.

Lines 16 and 23 begin groups for memory regions (core1 and udp respectively). udp is the region allocated to the User Data Path; many of the modules written by developers would be instantiated inside the User Data Path. Core1 is a region located outside of the user data path. More information about memory regions can be found in the Register Layout section of the Register System guide.

Line 17 specifies that the device_id module should be instantiated inside the core1 region. The addresses allocated the module will be left entirely to the register system. Note: The name "=device_id=" is the name specified in the module's XML file.

Line 18 specifies that the dma module should be instantiated inside the core1 region. The base attribute specifies that the module should be allocated addresses starting at 0x0500000. Generally developers should leave the address allocation to the register system (it gives the register system more flexibility in it's allocation).

Line 20 specifies that the nf2_mac_grp module should be instantiated inside the core1 region. The count attribute specifies the number of instances of this module to allocate memory for; in this example there are four instances. Each instance requires it's own memory allocation so that the registers for one instance can be uniquely identified from the registers for another instance.

Not shown in the example above is the ability to specify types and constants within the project.xml. These features and more are documented in more detail on the Register System page.

Module XML files

An XML file is provided for each module and specifies the registers, constants, and types used by each module. The XML file should be located in the module's xml directory for shared modules, or the project's include directory for project-specific modules. A sample module XML file is shown below:

< ?xml version="1.0" encoding="UTF-8"? >
<nf:module xmlns:nf="http://www.NetFPGA.org/NF2_register_system" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.NetFPGA.org/NF2_register_system NF2_register_system.xsd ">
	<nf:name>phy_test</nf:name>
	<nf:prefix>phy_test</nf:prefix>
	<nf:location>core</nf:location>
	<nf:description>Ethernet PHY test</nf:description>
	<nf:blocksize>256k</nf:blocksize>
	<nf:registers>
		<nf:register>
			<nf:name>status</nf:name>
			<nf:description>Status of the test</nf:description>
			<nf:type>phy_test_status</nf:type>
		</nf:register>
		<nf:register_group>
			<nf:name>phy</nf:name>
			<nf:description>Individual PHY registers</nf:description>
			<nf:instances>4</nf:instances>
			<nf:register>
				<nf:name>tx_status</nf:name>
				<nf:description>Transmit status</nf:description>
				<nf:type>phy_test_phy_tx_status</nf:type>
			</nf:register>
		</nf:register_group>
	</nf:registers>
	<nf:constants>
		<nf:constant>
			<nf:name>num_patterns</nf:name>
			<nf:description>Number of different test patterns</nf:description>
			<nf:value>5</nf:value>
		</nf:constant>
	</nf:constants>
	<nf:types>		
		<nf:type xsi:type="nf:SimpleType">
			<nf:name>phy_test_status</nf:name>
			<nf:description>Ethernet PHY test status</nf:description>
			<nf:width>32</nf:width>
			<nf:bitmask>
				<nf:name>busy</nf:name>
				<nf:description>Test in progress</nf:description>
				<nf:pos>0</nf:pos>
			</nf:bitmask>
			<nf:bitmask>
				<nf:name>done</nf:name>
				<nf:description>Test completed</nf:description>
				<nf:pos>4</nf:pos>
			</nf:bitmask>
			<nf:bitmask>
				<nf:name>good</nf:name>
				<nf:description>Test successful</nf:description>
				<nf:pos>8</nf:pos>
			</nf:bitmask>
		</nf:type>
	</nf:types>
</nf:module>

Line 1 specifies that this is an XML file.

Line 2 declares that we're working with a project and specifies the XML schema that this file is based on.

Lines 3 and 6 specify the name of the module and a description. The name is used in the project.xml file when specifying the module instances in each memory region.

Line 4 specifies the prefix to attach to register names in the Verilog, C and Perl files. In this example, the name and prefix are identical but they do not need to be.

Line 5 specifies which memory region the module can be instantiated in. Valid locations are "core", "udp", and "cpci". The location is checked when a module is instantiated in the project.xml file to ensure that the module is being instantiated in the correct memory region.

Line 7 specifies the block size of the module; this is the size of the address space allocated to that module, the maximum number of registers that can be instantiated is the block size divided by four (each register is 32 bits/4 bytes wide). Common sizes for udp blocks are 64, 256, and 1024; the only size supported for core blocks is 256k. See Register System for more informaiton.

Lines 8 -- 24 specify the registers in the module.

Lines 9 -- 13 specify the first register in the module. In this case, the module is named "status", the description is "Status of the test", and it's declared to be of type phy_test_status. The type is defined later in the XML file, although it is also possible to specify a width instead of a type. The register name generated in Verilog, C, and Perl files is the concatenation of the module prefix and the register name; in this instance the name would be PHY_TEST_STATUS.

Lines 14 -- 23 specify a register group containing a single register. Register Groups provide a mechanism to generate a repeated set of registers; in this case the register group is used to generate one set of registers per physical port.

In this example, the register group is named phy, there are four instances, and each instance contains a single register named tx_status. The register names for register groups differ slightly between the Verilog code and the C/Perl code, largely due to the use cases. The register names produced by this register group are: PHY_TEST_PHY_0_TX_STATUS_REG through PHY_TEST_PHY_3_TX_STATUS_REG. The name is a concatenation of the module's prefix, the register group name, the instance number, and the register name.

Lines 25 -- 31 specify constants.

Lines 26 -- 30 specify a single constant named num_patterns that represents the number of different test patterns. The value of this constant is specified as 5. Constants can be used anywhere that numerical values can used.

Lines 32 -- 53 specify types.

Lines 33 -- 52 specify a single type named phy_test_status. This type represents the status for the Ethernet PHY tests (as explained in description). The width attribute specifies the width of the type in bits. The bitmasks (lines 37 -- 51) specify the purpose of individual bits within the type; as an example bit 0 is named busy and represents whether a test is in progress. You can also experiment with multi-bit fields using the nf:pos_lo and nf:pos_hi xml tags.

Specifying types is not necessary but aids developers working with projects. The type information is incorporated in the Verilog, C, and Perl output to simplify the developers job; for example, the following constants are provided in the C header file produced by the register system:

// Type: phy_test_status
// Description: Ethernet PHY test status
// File: projects/selftest/include/phy_test.xml

// Part 1: bit positions
#define PHY_TEST_STATUS_BUSY_POS   0
#define PHY_TEST_STATUS_DONE_POS   4
#define PHY_TEST_STATUS_GOOD_POS   8

// Part 2: masks/values
#define PHY_TEST_STATUS_BUSY       0x00000001
#define PHY_TEST_STATUS_DONE       0x00000010
#define PHY_TEST_STATUS_GOOD       0x00000100

The above example provides an overview module XML files. More detailed information is found on the Register System page.

Performing register memory allocation

The register system tool to perform register memory allocation is invoked automatically as part of every simulation and synthesis run. The tool can be invoked manually at any time with the nf_register_gen.pl command. Common command line options include:

  • --project &lt;project&gt; -- specify a particular project (instead of using the current project specified via the NF_DESIGN_DIR variable).

Verification Tests (Simulation and Hardware)

Verification

Backend utilities

Common backend utilities that a developer is likely to invoke include:

nf_register_gen.pl :
Performs register memory allocation for a particular project. See Performing register memory allocation.
nf_run_tests.pl :
Run the simulation tests for the project. See Running simulations.
nf_regress_tests.pl :
Run the regression tests for a project. See Running regression tests.
nf_download :
Download a bitfile to the NetFPGA
nf_info :
Read the device ID info from the active design in the Virtex. Note: This is not installed by default prior to the 2.0.1 release. The source is located in netfpga/lib/C/tools/nf_info
cpci_reprogram.pl :
Download the latest CPCI design to the Spartan

DDR2 DRAM Interface

DDR2 DRAM Interface page

DDR2 Block Read Write

DDR2 Block Read Write page

DMA

DMA support information

Verilog Coding Guidlines

Verilog Coding Guidelines

Clone this wiki locally