The SP701 is a Spartan-7 based FPGA development board. Spartan-7 FPGAs are one of the most ideal FPGAs available in Xilinx's lineup for its performance-per-watts efficiency. Utilizing the MicroBlaze soft processor versus a physically instantiated ARM-core as founds in a Zynq SoC counterpart, I've personally found that the power consumption can be cut down nearly 75%.
The SP701 development board is very handy for it's range on peripherals and available I/O which includes 2 RJ45 Ethernet connectors, USB to UART bridge, 6 PMODs, a VITA 57.1 FMC LPC, HDMI, MIPI-CSI and MIPI-DSI, as well as some push buttons and DIP switches. It's an ideal starting point for proof-of-concept type projects.
The hardware design I'm creating in this post is functionally equivalent to the IPI example design available on Xilinx's site here, but will be providing a detailed guide for how the design is laid out as it is for the SP701 so it can hopefully be clearer where to start adding any custom design.Generate License File for SP701
One of the IPs required by the SP701 (the 1G/2.5G Ethernet controller) requires a license to generate a bitstream with. This license is included with the purchase of an SP701 evaluation kit, so the digital license file just needs to be generated and installed in Vivado on the host PC.
Launch Xilinx License Manager from Vivado by selecting Help > Manage License...
Select the Obtain License tab and check the option to Get My Full or Purchased Certificated-Based License then click Connect Now which will open a window in your browser to Xilinx's website.
Log into Xilinx's website when prompted and provide the requested information (this information is required due to some sensitives with FPGAs and export control laws in the US).
After logging in, you'll see a box where you can enter a code under Have a Voucher to Redeem? Enter the voucher number found on the back of the Quick Start Guide that came in the box with the SP701 (it will be highlighted in red right above a barcode) and click Redeem Now.
A pop up window will confirm the voucher is for the SP701 evaluation kit, click Yes.
A new row will appear at the top of the Certificate Based Licenses table for the SP701 evaluation kit. Check the box next to it then click Generate Node-Locked License (the voucher is only for a node-locked license, so a floating license is not an option).
Enter your host PC info, which you can find displayed under View Host Information in the Xilinx License Manager. Click Next.
Confirm everything and click Next again, then you'll have to accept the License Agreement.
The license file will be emailed to you with instructions of where to place it in Windows and Linux.
Copy the Xilinx.lic received in your email to $HOME/.Xilinx or you can go back to Xilinx License Manager and select Load License where the Copy License button will let you point to where the downloaded Xilinx.lic file is and it will copy it to $HOME/.Xilinx for you.
Relaunch Vivado so it can detect and pick up the new license file.
Note: this license file will be picked up by all versions of Vivado installed on the same host machine so don't worry about installing the same license separately for each version of Vivado.Create New Vivado Project
Select Create Project from the main Vivado window and step through the project setup windows. Name the project and select the desired project directory.
Leave the option check to not specify sources at this time and do not select the option to make the project a Vitis extensible platform (that is a different topic for a different day).
Finally, the target FPGA chip or development board must be selected. Vivado 2021.2 no longer requires manually installation for a pretty wide selection of boards not only from Xilinx's own offerings, but also Avnet, Digilent, and Trenz Electronic. Vivado 2021.2 is connected to the Xilinx Board Store which is a backend repository on Github maintained by Xilinx. You'll need an internet connection initially to refresh and see the current version of the Xilinx Board Store and download the presets for your desired boards. After that, you'll be able to work with them offline.
Search for and select the SP701 as target board and click Next. The final page is a summary of the Vivado project that is to be created.
Click Finish to generate the project.
99% of new Vivado projects will start with the creation of a block design. The block design is a straightforward way to add preexisting IP blocks to a design with helper tools for automated settings configurations and interface connections between the IPs. Predominately, the block design is where the processor core for an FPGA design is instantiated also with its supporting IPs. Since the SP701's FPGA is a Spartan-7, a soft processor must be used (as compared to the Zynq processor in Xilinx's SoC family with is a physically instantiated ARM-core in the programmable logic of the FPGA). Thus I'll be using Xilinx's soft processor the MicroBlaze.
Note: I won't be covering how to add custom HDL to this particular project for the SP701, it will be in a future post. However I have covered it many times in the past for other boards.
Create a new block design by selecting Create Block Design under IP Integrator in the Flow Navigator window.
Once the blank block design has generated, you'll notice the Board tab appear. Switch from the Sources tab to the Board tab where you'll see that Vivado has detected the peripheral interfaces available on the SP701 board.
This tab is a perk of selecting a specific board as a target for a Vivado project versus just the FPGA part number itself. It helps expedite the design process as it will filter the IP catalog as you click on each peripheral to only show what IP blocks can be connected to the selected peripheral.
Usually I start by adding the Processor IP blocks in a block design (the MicroBlaze in this case) however the SP701 is a bit different. Since the external memory controller for the DDR3 SRAM is what takes the longest to get up and running and synced, it is best to have it be the first thing fed by the oscillator (system clock) then have the rest of the IP downstream from it. So the first thing I'm adding to the SP701's block design will instead be the Memory Interface Generator IP block.
Right-click on DDR3 SRAM in the Board tab and select Connect Board Component, then select the option mig_ddr_interface from the pop-up window.
Skip running the resultant Connection Automation that pops up in a green banner across the top of the Block Design window to connect the FPGA reset signal.
Double-click on the Memory Interface Generator IP block to open its customization window.
Under FPGA Options, change System Reset Polarity to Active High and XADC Instantiation to Disabled.
In the Pin Selection tab, click Read UCF/XDC and navigate to wherever you've saved the DDR pin-out file for the SP701 (mig_7series_0.xdc) to read it into the Memory Interface Generator (MIG) IP block.
After importing the DDR pin-out, click Validate. After the pin-out is validated, the Next button will no longer be greyed out.
In the System Signals Selection tab, set the sys_rst Bank Number to 13, and the sys_rst Pin Number to AE15.
Click through the rest of the tabs showing a summary of the configuration specified, then on the last page, click Generate.
Now run the resultant Connection Automation that pops up in a green banner across the top of the Block Design window to connect the FPGA reset signal.
Click the + button at the top of the block design window and type microblaze to search for the soft processor IP blocks. Of the three options, double-click MicroBlaze to add the core of the soft processor to the block design.
The options for Block Automation and Connection Automation will appear at the top of the block design window.
Run the Block Automation first and check the box to enable the interrupt controller. Also change the Clock Connection to be sourced from /mig_7series_0/ui_clk. Since this external memory controller is what takes the longest to get up and running and synced, it's best to have everything else such as the soft processor itself downstream of it. Thus the output clock of the MIG is being used as the source clock for the MicroBlaze and the rest of the IP that will be in the block design.
After running Block Automation for the MicroBlaze, run the Connection Automation. Of the available options to run Connection Automation for, only select the connection automation for the slave AXI (S_AXI) of the MIG (mig_7series_0).
Again, click the + button at the top of the block design window and add an AXI BRAM Controller to the block design. Run all the Connection Automation for the AXI BRAM Controller, making sure that the S_AXI master interface is set to /microblaze_0 (cached).
Return to the Board tab and right-click on Onboard PHY1 and select Connect Board Component, then select the option AXI1G/2.5GEthernetSubsystem from the pop-up window.
Run the resultant Block Automation, selecting RGMII for the Physical Interface Selection and DMA for the AXI Streaming Interface.
For the Connection Automation fro the AXI1G/2.5GEthernetSubsystem, don't select axis_clk (this will be manually connected in the next step). For the reset of the Connection Automation, make the following selections:
- Select S_AXI with a clock source of /mig_7series_0/ui_clk
- Select M_AXI_MM2S, M_AXI_S2MM, and M_AXI_SG with a source of /mig_7series_0/S_AXI.
- Select S_AXI_LITE with a source of /microblaze_0 (Periph)
- Select clk_in1 with a source of /mig_7series_0/ui_clk
After running this Connection Automation, go back and manually connect axis_clk of axi_ethernet_0 to clk_ou1 of axi_ethernet_0_refclk
Next, click the + button at the top of the block design window and add an XADCWizard to the block design. Run the resultant Connection Automation setting its source to /microblaze_0 (Periph)
Double-click on the XADCWizard IP to open its customization window and make the following changes under the specified tabs:
- Basic: change Startup Channel Selection to Simultaneous Selection and enable Temp Bus under Control/Status Ports
- Channel Sequencer: enable vauxp0/vauxn0 Channel Enable
Click OK to apply and close the customization window. Right-click on the Vp_Vn port of the XADC Wizard IP block and select the option to Make External. Do the same for Vaux0 and Vaux8. This Make External option is what pulls a signal top to the top level of the design so it can be connected to a package pin of the FPGA chip.
Finally manually connect temp_out[11:0] of the XADC Wizard to the device_temp_i[11:0] of the Memory Interface Generator.
At this point, the most complex parts of the design are complete. Now the rest of the peripherals can be added. Returning to the Board tab, right-click on each of the following peripherals, select Connect Board Component, then select the following for each respective IP:
- SPI Flash: select SPI_0 and run the resultant Connection Automation with the clock source being /mig_7series_0/ui_clk.
- UART: select AXI UART16550 and run the resultant Connection Automation with the clock source being /mig_7series_0/ui_clk.
- IIC: select IIC and run the resultant Connection Automation with the clock source being /mig_7series_0/ui_clk.
- DIP Switches, Push Buttons, and LEDs: select GPIO and run the resultant Connection Automation with the clock source being /mig_7series_0/ui_clk.
Resulting in the following block design:
Click the + button at the top of the block design window and add an AXI Timer IP to the block design, again run the resultant Connection Automation with the clock source being /mig_7series_0/ui_clk.
There is a concat IP block feeding the interrupt input port of the AXI Interrupt Controller IP. By default, this concat is only configured to take in two inputs, but there are 8 total interrupt signals that need to be fed into the MicroBlaze soft processor via the AXI interrupt controller. Double-click the concat IP to open its configuration window and change its Number of Ports from 2 to 8 then click OK.
Connect the interrupt outputs in the following order:
- In0: AXI UART16550 ip2intc_irpt
- In1: AXI IIC ip2intc_irpt
- In2: AXI Quad SPI ip2intc_irpt
- In3: AXI 1G/2.5G Ethernet Subsystem interrupt
- In4: AXI Direct Memory Access mm2s_introut
- In5: AXI Direct Memory Access s2mm_introut
- In6: AXI Timer interrupt
- In7: XADC Wizard ip2intc_irpt
There are some custom frequency counter IPs that can be useful for various applications. I've attached them below and you'll need to place them in a directory locally then specify that directory as a repository in the Vivado project.
After copying the IP folder to your desired local directory, select Settings from the Flow Navigator window. Select IP > Repository then click the + button and point to the local directory the IP folder is located in. Vivado will pop up a window showing the IPs it detects in the directory. Click OK.
Click Apply, then OK.
In the block design window, click the + button and add one freq_counter_v1 IP block and two diff_freq_counter_v1 IP blocks. Connect the RST_I of each to the peripheral_reset of rst_mig_7series_0_100M and the REF_CLK_I of each to the ui_clk of mig_7series_0.
Connect CLKIN of freq_counter_v1_0 to ui_addn_clk_0 of mig_7series_0.
Right-click DIFF_CLKIN_P and DIFF_CLKIN_N of diff_freq_counter_v1_0 and select Make External. Then rename the ports FMC_CLK0_M2C_P and FMC_CLK0_M2C_N respectively.
Do the same for diff_freq_counter_v1_1 except rename its ports to FMC_CLK1_M2C_P and FMC_CLK1_M2C_N respectively.
Then add 3 AXI GPIO IP blocks with one channel being 16 bits all inputs. Run the resultant Connection Automation only for the S_AXI interface with the clock source being /mig_7series_0/ui_clk. Do not select the GPIO option for the AXI GPIO IPs in the Connection Automation.
Connect FREQ_CNT_O[15:0] of freq_counter_v1_0 to gpio_io_i[15:0] of one of the 3 AXI GPIO block just created.
Then connect FREQ_CNT_O[15:0] from diff_freq_counter_v1_0 and diff_freq_counter_v1_1 and connect them to gpio_io_i[15:0] of the other two AXI GPIO blocks.
At this point, this mostly all-encompassing block design for the SP701 is complete. Once I get to this point (and I usually am doing this after each instance that I add an IP block) is to use the Regenerate Layout tool to make the block design a little easier to look at. Click on the circle arrow icon at the top of the block design window to regenerate the layout in the block design.
The final design:
The final step in the creation of any block design is to validate it to verify that it is free of any critical warnings or errors. Click the checkbox icon at the top of the block design window and wait until the validation pop-up window appears with the results:
Click OK and save the block design.
Then return to the Sources tab. At this point, the block design needs to be instantiated in the overall project via a top level HDL file, which you can tell Vivado to auto-generate.HDL Wrapper
Right-click on the block design (.bd) file in the Sources tab and select Create HDL Wrapper... to have Vivado auto-generate it.
In the pop-up window, select the default option to allow Vivado to auto-manage the HDL wrapper file.
With the block design and top level wrapper file complete, the last item to be added is the constraints file specifying the signal routing to the Spartan-7 FPGA's package pins.
Select Add Sources from the Flow Navigator window. Select the option to Add or create constraints, and create a new constraints file local to the project.
Add the following constraints for the SP701 evaluation board:
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 3 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.UNUSEDPIN Pulldown [current_design]
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property PACKAGE_PIN H21 [get_ports Vaux0_0_v_n]
set_property IOSTANDARD LVCMOS33 [get_ports Vaux0_0_v_n]
set_property IOSTANDARD LVCMOS33 [get_ports Vaux0_0_v_p]
set_property IOSTANDARD LVCMOS33 [get_ports Vaux8_0_v_n]
set_property IOSTANDARD LVCMOS33 [get_ports Vaux8_0_v_p]
set_property PACKAGE_PIN D9 [get_ports FMC_CLK0_M2C_P]
set_property IOSTANDARD LVDS_25 [get_ports FMC_CLK0_M2C_P]
set_property IOSTANDARD LVDS_25 [get_ports FMC_CLK0_M2C_N]
set_property PACKAGE_PIN J4 [get_ports FMC_CLK1_M2C_P]
set_property IOSTANDARD LVDS_25 [get_ports FMC_CLK1_M2C_P]
set_property IOSTANDARD LVDS_25 [get_ports FMC_CLK1_M2C_N]
set_property IOSTANDARD LVCMOS18 [get_ports reset]
These constraints also include the circuit configuration of the QSPI flash memory chip.
Vivado follows the standard FPGA development flow of synthesis, followed by place & route (referred to as implementation in Vivado), and finally bitstream generation. Each step appears in the Flow Navigator window to be run manually. It is worth noting that if you try to run implementation before synthesis, Vivado will automatically perform a synthesis run before launching the implementation run.
I've found an interesting quirk in Vivado 2021.x versions that sometimes (but not always) if you run each step individually (ie you manually click "Run Synthesis", "Run Implementation", and "Generate Bitstream" a critical warning will pop up saying the board definition files for the target FPGA cannot be found.
It's a completely "fluff" warning and has no functional impact on the project (there is no actual issue with the board definition files), but I find it extremely annoying. Fortunately there is a super easy work around, if you always select "Generate Bitstream" and let Vivado automatically rerun synthesis and implementation, this critical warning never pops up. I've only found this to potentially happen in Vivado 2021.x versions on Linux, so ignore this little ramble if it doesn't appear for you.
Anyways, since I select "Generate Bitstream" without having done a synthesis or implementation run prior, Vivado will let me know and ask to proceed:
After clicking yes, Vivado will give me some options as to how to utilize the resources of the host PC. I usually always leave these options set to default.
I have an Intel i9 processor with 32GB of RAM and from the start of synthesis to the completion of bitstream generation for this design took about ~10 minutes.Export Hardware
After the bitstream has been successfully generated, the hardware platform needs to be exported for use in Vitis and/or PetaLinux for the software development of the code to run on the MicroBlaze soft processor.
Select File > Export > Export Hardware...
Select to include the bitstream in the exported hardware platform and select the desired output directory.
I personally like to export it to the top level of the Vivado project directory to keep everything together in one place.
And that's all for the SP701 hardware design in Vivado. I will be following this post up with a guide for creating an lwIP echo server in Vitis based on this hardware design.