For some reason, the Base System Builder in EDK doesn’t support the XUPV5 board so when making an EDK project for the XUPV5 we have to select the ML505 board and modify the project settings later. If you have not yet created an EDK project, you should read the previous post Creating a project using the Base System Builder, and then continue from these instructions.
Change the target FPGA
The ML505 is based on the Virtex-5 XC5VLX50T whereas the XUPV5 is based on the Virtex-5 XC5VLX110T, so the first thing we must do is change the target FPGA of the project.
- Open XPS and open your base project which should have been setup for the ML505 board.
- Select “Project->Project Options”.

- Change the target FPGA setting to “XC5VLX110T”, package “FFG1136″ and speed grade “-1″.
- Click “OK” to save the changes.
We’re not finished yet so don’t get too excited and try building the bitstream. If you were to try to build the bitstream, you would come up with this error:
ERROR: Place:713 - IOB component "fpga_0_DDR2_SDRAM_DDR2_DQ_pin<13>" and IODELAY component "DDR2_SDRAM/DDR2_SDRAM/mpmc_core_0/gen_v5_ddr2_phy.mpmc_phy_if_0/u_phy_io_0/g en_dq[13].u_iob_dq/u_idelay_dq" must be placed adjacent to each other into the same I/O tile in order to route net "DDR2_SDRAM/DDR2_SDRAM/mpmc_core_0/gen_v5_ddr2_phy.mpmc_phy_if_0/u_phy_io_0/g en_dq[13].u_iob_dq/dq_in". The following issue has been detected: Some of the logic associated with this structure is locked. This should cause the rest of the logic to be locked.A problem was found at site IODELAY_X0Y56 where we must place IODELAY DDR2_SDRAM/DDR2_SDRAM/mpmc_core_0/gen_v5_ddr2_phy.mpmc_phy_if_0/u_phy_io_0/ge n_dq[13].u_iob_dq/u_idelay_dq in order to satisfy the relative placement requirements of this logic. IODELAY DDR2_SDRAM/DDR2_SDRAM/mpmc_core_0/gen_v5_ddr2_phy.mpmc_phy_if_0/u_phy_io_0/ge n_dqs[0].u_iob_dqs/u_iodelay_dq_ce appears to already be placed there which makes this design unplaceable. ERROR: Pack:1654 - The timing-driven placement phase encountered an error. ERROR: Xflow - Program map returned error code 2. Aborting flow execution... make: *** [__xps/system_routed] Error 1
The reason for this error is that the design contains certain location constraints that are optimal for the Virtex-5 XC5VLX50T but not for the XC5VLX110T. We will have to modify the UCF file to use location constraints that are optimal for our FPGA.
Add the PCIe Bridge Constraints
The PCIe bridge peripheral that we included in the project has timing constraints in the project UCF file (system.ucf) but it also has some location constraints in its core specific UCF file (implementation/pcie_bridge_wrapper/pcie_bridge_wrapper.ucf). If you are curious, open this file and read the constraints inside.
The core specific UCF file is generated when you build the project and it is usually generated with constraints that are optimal for the target platform (ie. ML505 in our case). As the ML505 contains a smaller FPGA, the constraints are not optimal for the XUPV5 and we will have to override them by placing the same constraints (with different locations) into the project UCF file (system.ucf).
- Copy and paste the following lines to the bottom of your system.ucf file. Notice that they are the same constraints you would have found in the pcie_bridge_wrapper.ucf file, but I have changed the LOCs. All constraints placed in the system.ucf file will override the core specific constraints.
############################################################################### # PCIe Bridge Constraints for XUPV5 ############################################################################### # BlockRAM placement INST "pcie_bridge/*pcie_mim_wrapper_i/bram_tl_tx/generate_tdp2[1].ram_tdp2_inst" LOC = RAMB36_X3Y11; INST "pcie_bridge/*pcie_mim_wrapper_i/bram_tl_rx/generate_tdp2[1].ram_tdp2_inst" LOC = RAMB36_X3Y9; INST "pcie_bridge/*pcie_mim_wrapper_i/bram_tl_tx/generate_tdp2[0].ram_tdp2_inst" LOC = RAMB36_X3Y10; INST "pcie_bridge/*pcie_mim_wrapper_i/bram_tl_rx/generate_tdp2[0].ram_tdp2_inst" LOC = RAMB36_X3Y8; INST "pcie_bridge/*pcie_mim_wrapper_i/bram_retry/generate_sdp.ram_sdp_inst" LOC = RAMB36_X3Y7; # Timing critical placements INST "pcie_bridge/*tx_bridge/shift_pipe1" LOC = "SLICE_X59Y56"; INST "pcie_bridge/*arb_inst/completion_available" LOC = "SLICE_X58Y46"; INST "pcie_bridge/*management_interface/mgmt_rdata_d1_3" LOC = "SLICE_X59Y45";
Remove the DDR2 constraints
The DDR2 memory controller peripheral is the other device with some critical location constraints that we will have to optimize for the XUPV5.
- Find and remove the following lines in the system.ucf file.
############################################################################### # LOC placement of DQS-squelch related IDDR and IDELAY elements # Each circuit can be located at any of the following locations: # 1. Ununsed "N"-side of DQS diff pair I/O # 2. DM data mask (output only, input side is free for use) # 3. Any output-only site ############################################################################### INST "*/gen_dqs[0].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y56"; INST "*/gen_dqs[0].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y56"; INST "*/gen_dqs[1].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y18"; INST "*/gen_dqs[1].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y18"; INST "*/gen_dqs[2].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y22"; INST "*/gen_dqs[2].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y22"; INST "*/gen_dqs[3].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y60"; INST "*/gen_dqs[3].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y60"; INST "*/gen_dqs[4].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y62"; INST "*/gen_dqs[4].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y62"; INST "*/gen_dqs[5].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y216"; INST "*/gen_dqs[5].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y216"; INST "*/gen_dqs[6].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y220"; INST "*/gen_dqs[6].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y220"; INST "*/gen_dqs[7].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y222"; INST "*/gen_dqs[7].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y222"; ############################################################################### # LOC and timing constraints for flop driving DQS CE enable signal # from fabric logic. Even though the absolute delay on this path is # calibrated out (when synchronizing this output to DQS), the delay # should still be kept as low as possible to reduce post-calibration # voltage/temp variations - these are roughly proportional to the # absolute delay of the path ############################################################################### INST "*/u_phy_calib_0/gen_gate[0].u_en_dqs_ff" LOC = SLICE_X0Y28; INST "*/u_phy_calib_0/gen_gate[1].u_en_dqs_ff" LOC = SLICE_X0Y9; INST "*/u_phy_calib_0/gen_gate[2].u_en_dqs_ff" LOC = SLICE_X0Y11; INST "*/u_phy_calib_0/gen_gate[3].u_en_dqs_ff" LOC = SLICE_X0Y30; INST "*/u_phy_calib_0/gen_gate[4].u_en_dqs_ff" LOC = SLICE_X0Y31; INST "*/u_phy_calib_0/gen_gate[5].u_en_dqs_ff" LOC = SLICE_X0Y108; INST "*/u_phy_calib_0/gen_gate[6].u_en_dqs_ff" LOC = SLICE_X0Y110; INST "*/u_phy_calib_0/gen_gate[7].u_en_dqs_ff" LOC = SLICE_X0Y111;
Add the new DDR2 constraints
- Add the following constraints to the system.ucf file. You will notice that they are similar to the constraints that we just removed, yes we are replacing the old constraints with these ones!
############################################################################### # LOC placement of DQS-squelch related IDDR and IDELAY elements # Each circuit can be located at any of the following locations: # 1. Ununsed "N"-side of DQS diff pair I/O # 2. DM data mask (output only, input side is free for use) # 3. Any output-only site ############################################################################### INST "*/gen_dqs[0].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y96"; INST "*/gen_dqs[0].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y96"; INST "*/gen_dqs[1].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y58"; INST "*/gen_dqs[1].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y58"; INST "*/gen_dqs[2].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y62"; INST "*/gen_dqs[2].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y62"; INST "*/gen_dqs[3].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y100"; INST "*/gen_dqs[3].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y100"; INST "*/gen_dqs[4].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y102"; INST "*/gen_dqs[4].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y102"; INST "*/gen_dqs[5].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y256"; INST "*/gen_dqs[5].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y256"; INST "*/gen_dqs[6].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y260"; INST "*/gen_dqs[6].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y260"; INST "*/gen_dqs[7].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y262"; INST "*/gen_dqs[7].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y262"; INST "DDR2_SDRAM/DDR2_SDRAM/gen_no_iodelay_grp.gen_instantiate_idelayctrls[1].idelayctrl0" LOC = IDELAYCTRL_X0Y2; INST "DDR2_SDRAM/DDR2_SDRAM/gen_no_iodelay_grp.gen_instantiate_idelayctrls[0].idelayctrl0" LOC = IDELAYCTRL_X0Y6; INST "DDR2_SDRAM/DDR2_SDRAM/gen_no_iodelay_grp.gen_instantiate_idelayctrls[2].idelayctrl0" LOC = IDELAYCTRL_X0Y1; ############################################################################### # LOC and timing constraints for flop driving DQS CE enable signal # from fabric logic. Even though the absolute delay on this path is # calibrated out (when synchronizing this output to DQS), the delay # should still be kept as low as possible to reduce post-calibration # voltage/temp variations - these are roughly proportional to the # absolute delay of the path ############################################################################### INST "*/u_phy_calib_0/gen_gate[0].u_en_dqs_ff" LOC = SLICE_X0Y48; INST "*/u_phy_calib_0/gen_gate[1].u_en_dqs_ff" LOC = SLICE_X0Y29; INST "*/u_phy_calib_0/gen_gate[2].u_en_dqs_ff" LOC = SLICE_X0Y31; INST "*/u_phy_calib_0/gen_gate[3].u_en_dqs_ff" LOC = SLICE_X0Y50; INST "*/u_phy_calib_0/gen_gate[4].u_en_dqs_ff" LOC = SLICE_X0Y51; INST "*/u_phy_calib_0/gen_gate[5].u_en_dqs_ff" LOC = SLICE_X0Y128; INST "*/u_phy_calib_0/gen_gate[6].u_en_dqs_ff" LOC = SLICE_X0Y130; INST "*/u_phy_calib_0/gen_gate[7].u_en_dqs_ff" LOC = SLICE_X0Y131;
Build the project
Now you are ready to build the project and if you have done everything right, you should not have any errors.
- Select “Device Configuration->Update Bitstream”. It should take about a half an hour to build depending on your machine.
- You should see the message below if you are successful.
Checking platform address map ... Initializing Memory... Running Data2Mem with the following command: data2mem -bm "implementation/system_bd" -p xc5vlx110tff1136-1 -bt "implementation/system.bit" -bd "bootloops/microblaze_0.elf" tag microblaze_0 -o b implementation/download.bit Memory Initialization completed successfully. Done!
You can download the project files as a compressed zip file here: base-system-xupv5-edk13-1.zip
What am I learning here?
In this post we’ll look at using the Base System Builder in EDK version 13.1. Specifically you’ll learn:
- How to create an EDK project with the Base System Builder
- How to add a software application to an EDK project
- How to implement and test your design
Requirements
You will need the following :
- One ML505/ML506/ML507 or XUPV5 board (or actually any board supported by Xilinx).
- Xilinx ISE Design Suite 13.1 (including EDK)
Create the Basic Project
Follow these steps to create the basic project:
- Open XPS by selecting “Start->Xilinx ISE Design Suite 13.1->EDK->Xilinx Platform Studio”.
- From the dialog box, select “Base System Builder wizard” and OK.
- You will be asked to specify which folder to place the project. Click “Browse” and create a new folder for the project. Click “OK”.

- The first page of the wizard will ask us to choose between using a Processor Local Bus (PLB) or an Advanced Extensible Interface (AXI). As we are using the Virtex-5, we have to select a PLB system, but if you are working with a Virtex-6 or a Spartan-6 you are better to go with the AXI system.

- We are given the choice to create a new project or to create one using the template of another project. Tick “I would like to create a new design” and click “Next”.

- On the “Select Board” page, select “Xilinx” as the board vendor. Then select the board you are using (eg. “Virtex 5 ML505 Evaluation Platform”). Select “1″ as the board revision. Click “Next”. (Note: If you are using the XUPV5 (ML509) board, select “Virtex 5 ML505 Evaluation Platform” instead.)

- Now we have the choice to build a single-processor or dual-processor system. The Virtex-5 doesn’t have any hard processors, so the Base System Builder will setup a Microblaze soft processor for us. Select “Single-Processor System” and click “Next”.

- On the “Configure Microblaze” page, we can specify the clock frequency of our processor and the amount of memory it will use. Select the clock frequency to 125MHz. Click “Next”.

- Now we can select the peripherals to put in the design. The peripherals will all be connected to the Microblaze processor via the PLB and they allow us to control and access features of the FPGA and external hardware such as the DDR2 memory and the Ethernet MAC. We will leave the default setting which is to include ALL the standard peripherals. You might ask “Why include all the peripherals?“, well most of the time you would only include the peripherals that you need so that you don’t waste time building peripherals you wont use. In this case, I want you to include all the peripherals because a lot of the following EDK tutorials will be based on this “base system”. This way, we wont have to go through the Base System Builder for every tutorial and we’ll save time. The fact is, in a professional environment, you would never go through the Base System Builder when starting a new project, instead you would take an existing project and develop from that.

- In the next page we can configure cache memory for the Microblaze. In our case we wont use cache memory so leave the default and click “Next”.

- The Base System Builder then gives us a summary of the design that it will create for us, showing the PLB memory map, the peripherals and the files that it will create.

- Click “Finish”.
If you are using the XUPV5 (ML509) board
If you are using the XUPV5 (ML509) board and you selected “Virtex 5 ML505 Evaluation Platform” in step 6 above, you will have to change the target FPGA setting to “XC5VLX110T”, package “FFG1136″ and speed grade “-1″ in the “Project->Project Options” menu. There are more changes to make that will be discussed in the next post: Convert an ML505 project for the XUPV5. If you don’t make these changes, you’ll find this error message when you try to build the bitstream:
ERROR:Place:713 - IOB component "fpga_0_DDR2_SDRAM_DDR2_DQ_pin<13>" and IODELAY component "DDR2_SDRAM/DDR2_SDRAM/mpmc_core_0/gen_v5_ddr2_phy.mpmc_phy_if_0/u_phy_io_0/g en_dq[13].u_iob_dq/u_idelay_dq" must be placed adjacent to each other into the same I/O tile in order to route net "DDR2_SDRAM/DDR2_SDRAM/mpmc_core_0/gen_v5_ddr2_phy.mpmc_phy_if_0/u_phy_io_0/g en_dq[13].u_iob_dq/dq_in". The following issue has been detected: Some of the logic associated with this structure is locked. This should cause the rest of the logic to be locked.A problem was found at site IODELAY_X0Y56 where we must place IODELAY DDR2_SDRAM/DDR2_SDRAM/mpmc_core_0/gen_v5_ddr2_phy.mpmc_phy_if_0/u_phy_io_0/ge n_dq[13].u_iob_dq/u_idelay_dq in order to satisfy the relative placement requirements of this logic. IODELAY DDR2_SDRAM/DDR2_SDRAM/mpmc_core_0/gen_v5_ddr2_phy.mpmc_phy_if_0/u_phy_io_0/ge n_dqs[0].u_iob_dqs/u_iodelay_dq_ce appears to already be placed there which makes this design unplaceable. ERROR:Pack:1654 - The timing-driven placement phase encountered an error. ERROR:Xflow - Program map returned error code 2. Aborting flow execution... make: *** [__xps/system_routed] Error 1
Build the bitstream
The project is now ready to build.
- To build the bitstream of the project, select “Device Configuration->Update Bitstream”. This will take some time (around half an hour) depending on your machine.
You should end up seeing this message when the build is complete:
Checking platform address map ... Initializing Memory... Running Data2Mem with the following command: data2mem -bm "implementation/system_bd" -p xc5vlx110tff1136-1 -bt "implementation/system.bit" -bd "bootloops/microblaze_0.elf" tag microblaze_0 -o b implementation/download.bit Memory Initialization completed successfully. Done!
What about the software application?
If you’re used to older versions of EDK, you would notice that we didn’t put any software into the project – software to run on the Microblaze processor. The reason for this is that Xilinx has removed this functionality from EDK in version 13.1. They gave us plenty of notice actually, but now all the software development for your FPGA projects must be done in SDK (Software Development Kit), logical isn’t it?
The project folder for this tutorial can be downloaded in a compressed ZIP file. Remember that if you want to understand the modifications made to the project for the XUPV5, you should read the next post.
| Board | Virtex-5 Version | Project files |
| ML505 | XC5VLX50T | base-system-ml505-edk13-1.zip |
| ML506 | XC5VSX50T | base-system-ml506-edk13-1.zip |
| ML507 | XC5VFX70T | base-system-ml507-edk13-1.zip |
| XUPV5 | XC5VLX110T | base-system-xupv5-edk13-1.zip |
Overview
Your FPGA designs can be copied onto a compact flash card and loaded automatically when your ML50x/XUPV5 board is turned ON. The configuration DIP switch (SW3), located in the top left hand corner of the board, determines which design the FPGA is loaded with when the board is turned ON.
Before understanding how to use these switches, we must first take a look at how the flash disk contents are structured.
Flash Disk Contents
The folder structure of the flash disk contents is shown in the screenshots below. The root folder can contain different files that are not necessarily used for configuration. We are interested in the folder for placing our FPGA designs which is called “ML50x”.
As can be seen in the screenshots, the “ML50x” folder contains eight configuration folders (cfg0 to cfg7). These configuration folders are used to store eight separate FPGA designs. There must only be ONE design per folder, and it must be in SystemACE (.ACE) format. To learn how to convert your bit files into SystemACE files, refer to this tutorial: Convert Bit Files to System ACE Files.
How to load a design from Compact Flash
To load a design from compact flash, follow these instructions:
- Copy a design in SystemACE format (.ace) into one of the “cfg0-7″ folders on the flash disk. Ensure that the .ace file that was previously in that folder has been either deleted or renamed to another extension (ie. “previous.bak”).
- Set the configuration DIP (SW3) switches 4 to 8 to “10101″. This sets the hardware to load the FPGA using the compact flash.
- Set the configuration DIP (SW3) switches 1 to 3 to the design you want to use. For example, if you want to load the design in folder “cfg0″, you would set “000″, alternatively if you want to load “cfg4″ you would set “100″.
- Ensure that the flash disk is properly inserted into your board and then turn the board ON.
As a final example, if I had copied my “project.ace” file into the “cfg3″ folder, I would have set my SW3 settings to “01110101″ (from 1 to 8).
Instructions
To run your designs from the flash disk, you need to first convert your bit files to System ACE files (.ace). One simple system for doing this is to copy all your bit files to one folder and use a batch file in that folder to perform the conversions from the command line.
- To start, you should create a folder and copy your bit file(s) there (eg. “C:SysACE”).
- If you are copying your bit files from the “implementation” folder of the EDK project, they will be named “download.bit”. You should rename them to something that is appropriate for the designs. For example, if my design is an Ethernet design, I might call it “ethernet.bit”.
- You should create a batch file in this folder called “makeace.bat”. The batch file is just a text file that you can create with Wordpad and it must contain the following text:
@echo off if "%1" == "" goto error xmd -tcl ./genace.tcl -jprog -hw %1.bit -board ml505 -ace my_%1.ace goto end :error echo Makeace - by FPGA Developer http://www.fpgadeveloper.com echo. echo Usage: makeace bitfile (without .bit extension) echo Example: makeace project :end echo.
- To use the batch file, you must open up a command prompt. From Windows, select “Start->Run” and type “cmd”. Press “Enter” and you should have a command prompt.
- Use the “cd” command to reach the folder where you have the bit files and makeace batch file (eg. “cd SysACE”). In this example, you should now have the prompt: “C:SysACE>”.
- From the command line, type “makeace” followed by the name of the bit file you wish to convert (without the .bit extension). For example, to convert the “ethernet.bit” file, we type “makeace ethernet”. This will produce a few files, but the important one is the System ACE file that will be called “my_ethernet.ace”.
You can now copy the System ACE file into your Flash disk and run the design from there. To convert other designs, you need only copy the bit file into the “SysACE” folder, rename it appropriately and run the “makeace” batch file as shown.
Tutorial Overview
In the last tutorial we implemented the embedded Tri-mode Ethernet MAC and tested it by looping back Ethernet packets and monitoring them with Wireshark. In this tutorial, we will again implement the EMAC but this time we will link it to an Aurora core, to implement an Aurora to Ethernet Bridge. With the bridge, we can link two PCs as shown in the diagram below.
To connect the EMAC and Aurora cores we have to use two FIFOs to cross clock domains. The EMAC has a user clock of 125MHz and a data interface of 8 bits, while the Aurora core will have a user clock of 62.5MHz and a data interface of 16 bits. The diagram below illustrates the connections between the EMAC and Aurora core and the clock domain crossing FIFOs.
This tutorial contains screenshots to guide you through the entire implementation process. Click on the images to view a higher resolution.
Requirements
Before following this tutorial, you will need to do the following:
- Ideally, to test the Bridge you should have two (2) FPGA boards and two (2) PCs, however this design has an optional loopback feature that allows the design to be tested with only one FPGA board and one PC.
- Generate the Virtex-5 Embedded Tri-mode Ethernet MAC Wrapper using CORE Generator. For instructions on doing this, please refer to the tutorial Generating the Ethernet MAC
- Generate the Aurora Core using CORE Generator. For instructions on doing this, please refer to the tutorial Generating the Aurora Core
- Generate the Clock Domain Crossing FIFOs using CORE Generator. For instructions on doing this, please refer to the tutorial Generating Clock Domain Crossing FIFOs
- Set the J22 and J23 jumpers on the ML505 to positions 2-3 as shown below. This allows us to use an SGMII (serial) interface with the PHY.
- Install a copy of Wireshark on a PC with a Gigabit Ethernet network card
- Obtain a CAT5 Ethernet cable (or two if you have two FPGA boards and two PCs): regular or crossover, either will work because the PHY on the ML505 has an automatic switching feature that detects what type of cable you are using and switches the TX and RX pins if necessary.
- Obtain a crossover SATA cable if you have two FPGA boards and two PCs that you can use for testing. If you bought the ML505/ML506/ML507 or XUPV5 board, you should have one included in the box.
Try Out the BIT File on Your Board
If you want to test this design before building it, you can download the bit file and try it on your ML50x board. Please click the link below for the file corresponding to your board.
| Board | Virtex-5 Version | Bit file |
| ML505 | XC5VLX50T | AEBridge-ML505.zip |
| ML506 | XC5VSX50T | AEBridge-ML506.zip |
| XUPV5 | XC5VLX110T | AEBridge-XUPV5.zip |
To program your FPGA with the bit file, first extract the contents of your ZIP file to your hard drive (eg. C:\AEBridge-XUPV5\).
- From Windows, select “Start->Run” and type “cmd”. Press “Enter” and you should have a command prompt.
- Use the “cd” command to reach the folder where you extracted the bit file (eg. “cd AEBridge-XUPV5″). In this example, the prompt should now read “C:\AEBridge-XUPV5>”.
- Turn on your ML505 board and ensure that the JTAG programmer is connected.
- From the command line, type “impact -batch download.cmd”.
The FPGA should be programmed and the LCD should be displaying “Aurora to Ethernet Bridge”. For instructions on testing the design, scroll down to the end of the tutorial or click here.
Create the Basic Project
Follow these steps to create the basic project:
- Open XPS. From the dialog box, select “Base System Builder wizard” and OK.
- You will be asked to specify which folder to place the project. Click “Browse” and create a new folder for the project. Click “OK”.
- We are given the choice to create a new project or to create one using the template of another project. Tick “I would like to create a new design” and click “Next”.
- On the “Select Board” page, select “Xilinx” as the board vendor. Select “Virtex 5 ML505 Evaluation Platform” as the board name. Select “1″ as the board revision. Click “Next”.
- On the “Select Processor” page, we normally have a choice between using the PowerPC “hard” processor, or the Microblaze “soft” processor. Since the Virtex-5 does not contain any PowerPCs, we can only select Microblaze. Click “Next”.
- On the “Configure Microblaze” page, select the clock frequency to be 125MHz. For the BRAM local memory, select “64KB”. We will use the RS232 port for debugging rather than the JTAG, so select “No debug”. Click “Next”.
- In selecting the Additional IO Interfaces, leave “DIP_Switches_8Bit” ticked and un-tick everything else.
- On the “Add Internal Peripherals” page, click “Next”.
- On the “Software Setup” page, un-tick “Memory Test” and leave “Peripheral Test” ticked. Click “Next”.
- Click “Generate”.
- Click “Finish”.
Create the Bridge Peripheral
We now create our Bridge peripheral using the Peripheral Wizard.
- Select from the menu “Hardware->Create or Import Peripheral”. Click “Next”.
- Select “Create templates for a new peripheral” and click “Next”.
- We must now decide where to place the files for the peripheral. They can be placed within this project, or they can be made accessible to other projects. Select “To an XPS project”. Click “Next”.
- On the “Name and Version” page, type “bridge” for the peripheral name. Click “Next”.
- On the “Bus Interface” page, select “Processor Local Bus” (PLB) and click “Next”.
- On the “IPIF Services” page, select “User logic software register” and “Include data phase timer”. Un-tick everything else and click “Next”.
- On the “Slave Interface” page, leave the defaults and click “Next”.
- On the “User S/W Register” page, we can specify the number of slave registers we want to implement in our peripheral. Leave the default “1″ and click “Next”.
- On the “Peripheral Simulation Support” page, we can specify if we want the wizard to create a simulation platform for our peripheral. Click “Next” without ticking the option to generate.
- After the “Peripheral Implementation Support” page, the wizard will generate all the template files for us. Tick “Generate ISE and XST project files” and “Generate template driver files”. Click “Next”.
- Click “Finish”. Now our templates are created and we can modify them to include the code for the EMAC and Aurora core.
Copy the Ethernet MAC source files
We need to copy the Ethernet MAC source files generated by CORE Generator into the Bridge peripheral source folder. If you have not generated the source files using CORE Generator, please refer to the tutorial Generating the Ethernet MAC.
- Open Windows Explorer and browse to the folder “TEMACCore\v5_emac_v1_5″. This is the folder you created with CORE Generator.
- In that folder, you will find a subfolder called “example_design”. Select the “example_design” folder, copy and paste it into the “pcores\bridge_v1_00_a\hdl\vhdl” folder within your XPS project. This is the folder where you should find your “user_logic.vhd” file for the Bridge peripheral.
Copy the Aurora core source files
We need to copy the Aurora core source files generated by CORE Generator into the Bridge peripheral source folder. If you have not generated the source files using CORE Generator, please refer to the tutorial Generating the Aurora Core.
- Open Windows Explorer and browse to the folder “AuroraCore”. This is the folder you created with CORE Generator.
- In that folder, you will find a subfolder called “aurora_201″. Select the “aurora_201″ folder, copy and paste it into the “pcores\bridge_v1_00_a\hdl\vhdl” folder within your XPS project. This is the folder where you should find your “user_logic.vhd” file for the Bridge peripheral.
Modify the .PAO file
The .pao file contains a list of all the source files that compose our peripheral. We use this list when we run the Peripheral Wizard in Import mode. Now that we have added the Ethernet MAC and Aurora core source files to the project, we must include them in the .pao file. Note that files must be listed in the .pao file in hierarchical order. The components at the top of the hierarchy are listed at the bottom of the file.
- Select “File->Open” and browse to the “pcores\bridge_v1_00_a\data” folder. Select the file “bridge_v2_1_0.pao” and click “Open”.
- At the bottom of this file you will see these two lines:
lib bridge_v1_00_a user_logic vhdl lib bridge_v1_00_a bridge vhdl |
- Add the following lines just above those two lines. It is important to copy the lines exactly as shown and in the same order.
lib bridge_v1_00_a aurora_201\src\aurora_201_aurora_lane.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_aurora_pkg.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_channel_error_detect.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_channel_init_sm.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_chbond_count_dec.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_error_detect.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_global_logic.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_gtp_wrapper.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_idle_and_ver_gen.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_lane_init_sm.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_rx_ll.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_rx_ll_pdu_datapath.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_sym_dec.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_sym_gen.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_tx_ll.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_tx_ll_control.vhd lib bridge_v1_00_a aurora_201\src\aurora_201_tx_ll_datapath.vhd lib bridge_v1_00_a aurora_201\cc_manager\aurora_201_standard_cc_module.vhd lib bridge_v1_00_a aurora_201\clock_module\aurora_201_clock_module.vhd lib bridge_v1_00_a aurora_201\src\aurora_201.vhd lib bridge_v1_00_a example_design/v5_emac_v1_5.vhd lib bridge_v1_00_a example_design/physical/rx_elastic_buffer.vhd lib bridge_v1_00_a example_design/physical/gtp_dual_1000X.vhd lib bridge_v1_00_a example_design/physical/rocketio_wrapper_gtp.vhd lib bridge_v1_00_a example_design/physical/rocketio_wrapper_gtp_tile.vhd lib bridge_v1_00_a example_design/v5_emac_v1_5_block.vhd lib bridge_v1_00_a example_design/client/fifo/tx_client_fifo_8.vhd lib bridge_v1_00_a example_design/client/fifo/rx_client_fifo_8.vhd lib bridge_v1_00_a example_design/client/fifo/eth_fifo_8.vhd lib bridge_v1_00_a example_design/v5_emac_v1_5_locallink.vhd lib bridge_v1_00_a example_design/client/address_swap_module_8.vhd |
- Save the file.
Now we can use this .pao file with the Peripheral Wizard when we import the Bridge peripheral.
Modify the Bridge Peripheral
Now we will insert code into the “user_logic.vhd” file for our Bridge peripheral to instantiate and connect the Ethernet MAC and Aurora core. The code for defining and instantiating the cores is derived from the example designs that were generated by CORE Generator. If you refer back to the files created by CORE Generator, you will find the top module of the EMAC example in the file “v5_emac_v1_5\example_design\v5_emac_v1_5_example_design.vhd”. You will find the top module of the Aurora core example in the file “aurora_201\examples\aurora_201_aurora_example.vhd”.
- Select from the menu “File->Open” and look in the project folder.
- Open the folders: “pcores\bridge_v1_00_a\hdl\vhdl”.
- Open the file “bridge.vhd”.
- Find the line of code that says “– ADD USER PORTS BELOW THIS LINE” and add the following lines of code just below.
REFCLK_N_IN : in std_logic; REFCLK_P_IN : in std_logic; EMAC_READY : out std_logic; PHY_RESET_0 : out std_logic; HARD_ERROR : out std_logic; SOFT_ERROR : out std_logic; FRAME_ERROR : out std_logic; LANE_UP : out std_logic; CHANNEL_UP : out std_logic; RXP_IN : in std_logic_vector(1 downto 0); RXN_IN : in std_logic_vector(1 downto 0); TXP_OUT : out std_logic_vector(1 downto 0); TXN_OUT : out std_logic_vector(1 downto 0); |
- Find the line of code that says “– MAP USER PORTS BELOW THIS LINE” and add the following lines of code just below.
REFCLK_N_IN => REFCLK_N_IN, REFCLK_P_IN => REFCLK_P_IN, EMAC_READY => EMAC_READY, PHY_RESET_0 => PHY_RESET_0, HARD_ERROR => HARD_ERROR, SOFT_ERROR => SOFT_ERROR, FRAME_ERROR => FRAME_ERROR, LANE_UP => LANE_UP, CHANNEL_UP => CHANNEL_UP, RXP_IN => RXP_IN, RXN_IN => RXN_IN, TXP_OUT => TXP_OUT, TXN_OUT => TXN_OUT, |
- Save and close the file.
- Open the file “user_logic.vhd”. We will need to modify this source code to include our example code.
- Find the line of code that says “–USER libraries added here” and add the following lines of code just below.
library UNISIM; use UNISIM.VCOMPONENTS.ALL; |
- Find the line of code that says “– ADD USER PORTS BELOW THIS LINE” and add the following lines of code just below.
REFCLK_N_IN : in std_logic; REFCLK_P_IN : in std_logic; EMAC_READY : out std_logic; PHY_RESET_0 : out std_logic; HARD_ERROR : out std_logic; SOFT_ERROR : out std_logic; FRAME_ERROR : out std_logic; LANE_UP : out std_logic; CHANNEL_UP : out std_logic; RXP_IN : in std_logic_vector(1 downto 0); RXN_IN : in std_logic_vector(1 downto 0); TXP_OUT : out std_logic_vector(1 downto 0); TXN_OUT : out std_logic_vector(1 downto 0); |
- Find the line of code that says “–USER signal declarations added here” and add the following lines of code just below.
-- Clock signals
signal ref_clk : std_logic;
signal user_clk_eth : std_logic;
signal user_clk_out : std_logic;
-- Reset signals
signal rst_gtp : std_logic;
signal rst_fifos : std_logic;
signal reset_aurora : std_logic;
signal pre_reset_aurora : std_logic_vector(5 downto 0);
-- Registers for the status outputs
signal HARD_ERROR_Buffer : std_logic;
signal SOFT_ERROR_Buffer : std_logic;
signal FRAME_ERROR_Buffer : std_logic;
signal LANE_UP_Buffer : std_logic;
signal CHANNEL_UP_Buffer : std_logic;
-- LocalLink TX Interface
signal tx_d_i : std_logic_vector(0 to 15);
signal tx_rem_i : std_logic;
signal tx_src_rdy_n_i : std_logic;
signal tx_sof_n_i : std_logic;
signal tx_eof_n_i : std_logic;
signal tx_dst_rdy_n_i : std_logic;
-- LocalLink RX Interface
signal rx_d_i : std_logic_vector(0 to 15);
signal rx_rem_i : std_logic;
signal rx_src_rdy_n_i : std_logic;
signal rx_sof_n_i : std_logic;
signal rx_eof_n_i : std_logic;
-- Error Detection Interface
signal hard_error_i : std_logic;
signal soft_error_i : std_logic;
signal frame_error_i : std_logic;
-- Status
signal channel_up_i : std_logic;
signal lane_up_i : std_logic;
signal lane_up_i_i : std_logic;
-- Clock Compensation Control Interface
signal warn_cc_i : std_logic;
signal do_cc_i : std_logic;
-- System Interface
signal dcm_not_locked_i : std_logic;
signal user_clk_aur : std_logic;
signal sync_clk_i : std_logic;
signal power_down_i : std_logic;
signal loopback_i : std_logic_vector(0 to 2);
signal tx_lock_i : std_logic;
signal tx_out_clk_i : std_logic;
signal buf_tx_out_clk_i : std_logic;
-- Aurora Component Declarations
component aurora_201_CLOCK_MODULE
port (
GTP_CLK : in std_logic;
GTP_CLK_LOCKED : in std_logic;
USER_CLK : out std_logic;
SYNC_CLK : out std_logic;
DCM_NOT_LOCKED : out std_logic
);
end component;
component aurora_201
generic(
SIM_GTPRESET_SPEEDUP :integer := 0
);
port(
-- LocalLink TX Interface
TX_D : in std_logic_vector(0 to 15);
TX_REM : in std_logic;
TX_SRC_RDY_N : in std_logic;
TX_SOF_N : in std_logic;
TX_EOF_N : in std_logic;
TX_DST_RDY_N : out std_logic;
-- LocalLink RX Interface
RX_D : out std_logic_vector(0 to 15);
RX_REM : out std_logic;
RX_SRC_RDY_N : out std_logic;
RX_SOF_N : out std_logic;
RX_EOF_N : out std_logic;
-- GTP Serial I/O
RXP : in std_logic;
RXN : in std_logic;
TXP : out std_logic;
TXN : out std_logic;
-- GTP Reference Clock Interface
GTPD1 : in std_logic;
-- Error Detection Interface
HARD_ERROR : out std_logic;
SOFT_ERROR : out std_logic;
FRAME_ERROR : out std_logic;
-- Status
CHANNEL_UP : out std_logic;
LANE_UP : out std_logic;
-- Clock Compensation Control Interface
WARN_CC : in std_logic;
DO_CC : in std_logic;
-- System Interface
DCM_NOT_LOCKED : in std_logic;
USER_CLK : in std_logic;
SYNC_CLK : in std_logic;
PMA_INIT : in std_logic;
RESET : in std_logic;
POWER_DOWN : in std_logic;
LOOPBACK : in std_logic_vector(2 downto 0);
TX_LOCK : out std_logic;
TX_OUT_CLK : out std_logic
);
end component;
component aurora_201_STANDARD_CC_MODULE
port(
-- Clock Compensation Control Interface
WARN_CC : out std_logic;
DO_CC : out std_logic;
-- System Interface
DCM_NOT_LOCKED : in std_logic;
USER_CLK : in std_logic;
CHANNEL_UP : in std_logic
);
end component;
-- EMAC Component Declarations
-- Component Declaration for the TEMAC wrapper with
-- Local Link FIFO.
component v5_emac_v1_5_locallink is
port(
-- EMAC0 Clocking
-- 125MHz clock output from transceiver
CLK125_OUT : out std_logic;
-- 125MHz clock input from BUFG
CLK125 : in std_logic;
-- Tri-speed clock output from EMAC0
CLIENT_CLK_OUT_0 : out std_logic;
-- EMAC0 Tri-speed clock input from BUFG
client_clk_0 : in std_logic;
-- Local link Receiver Interface - EMAC0
RX_LL_CLOCK_0 : in std_logic;
RX_LL_RESET_0 : in std_logic;
RX_LL_DATA_0 : out std_logic_vector(7 downto 0);
RX_LL_SOF_N_0 : out std_logic;
RX_LL_EOF_N_0 : out std_logic;
RX_LL_SRC_RDY_N_0 : out std_logic;
RX_LL_DST_RDY_N_0 : in std_logic;
RX_LL_FIFO_STATUS_0 : out std_logic_vector(3 downto 0);
-- Local link Transmitter Interface - EMAC0
TX_LL_CLOCK_0 : in std_logic;
TX_LL_RESET_0 : in std_logic;
TX_LL_DATA_0 : in std_logic_vector(7 downto 0);
TX_LL_SOF_N_0 : in std_logic;
TX_LL_EOF_N_0 : in std_logic;
TX_LL_SRC_RDY_N_0 : in std_logic;
TX_LL_DST_RDY_N_0 : out std_logic;
-- Client Receiver Interface - EMAC0
EMAC0CLIENTRXDVLD : out std_logic;
EMAC0CLIENTRXFRAMEDROP : out std_logic;
EMAC0CLIENTRXSTATS : out std_logic_vector(6 downto 0);
EMAC0CLIENTRXSTATSVLD : out std_logic;
EMAC0CLIENTRXSTATSBYTEVLD : out std_logic;
-- Client Transmitter Interface - EMAC0
CLIENTEMAC0TXIFGDELAY : in std_logic_vector(7 downto 0);
EMAC0CLIENTTXSTATS : out std_logic;
EMAC0CLIENTTXSTATSVLD : out std_logic;
EMAC0CLIENTTXSTATSBYTEVLD : out std_logic;
-- MAC Control Interface - EMAC0
CLIENTEMAC0PAUSEREQ : in std_logic;
CLIENTEMAC0PAUSEVAL : in std_logic_vector(15 downto 0);
--EMAC-MGT link status
EMAC0CLIENTSYNCACQSTATUS : out std_logic;
-- EMAC0 Interrupt
EMAC0ANINTERRUPT : out std_logic;
-- Clock Signals - EMAC0
-- SGMII Interface - EMAC0
TXP_0 : out std_logic;
TXN_0 : out std_logic;
RXP_0 : in std_logic;
RXN_0 : in std_logic;
PHYAD_0 : in std_logic_vector(4 downto 0);
RESETDONE_0 : out std_logic;
-- unused transceiver
TXN_1_UNUSED : out std_logic;
TXP_1_UNUSED : out std_logic;
RXN_1_UNUSED : in std_logic;
RXP_1_UNUSED : in std_logic;
-- SGMII RocketIO Reference Clock buffer inputs
CLK_DS : in std_logic;
-- Asynchronous Reset
RESET : in std_logic
);
end component;
-- EMAC Signal Declarations
-- address swap transmitter connections - EMAC0
signal tx_ll_data_0_i : std_logic_vector(7 downto 0);
signal tx_ll_sof_n_0_i : std_logic;
signal tx_ll_eof_n_0_i : std_logic;
signal tx_ll_src_rdy_n_0_i : std_logic;
signal tx_ll_dst_rdy_n_0_i : std_logic;
-- address swap receiver connections - EMAC0
signal rx_ll_data_0_i : std_logic_vector(7 downto 0);
signal rx_ll_sof_n_0_i : std_logic;
signal rx_ll_eof_n_0_i : std_logic;
signal rx_ll_src_rdy_n_0_i : std_logic;
signal rx_ll_dst_rdy_n_0_i : std_logic;
signal rx_ll_fifo_status_0_i : std_logic_vector(3 downto 0);
-- create a synchronous reset in the transmitter clock domain
signal ll_pre_reset_0_i : std_logic_vector(5 downto 0);
signal ll_reset_0_i : std_logic;
attribute async_reg : string;
attribute async_reg of ll_pre_reset_0_i : signal is "true";
signal resetdone_0_i : std_logic;
-- EMAC0 Clocking signals
-- 1.25/12.5/125MHz clock signals for tri-speed SGMII
signal client_clk_0_o : std_logic;
signal client_clk_0 : std_logic;
-- Clock Domain Crossing FIFO declarations
-- FIFO 32 bit to 16 bit
signal fifo1_din : std_logic_VECTOR(31 downto 0);
signal fifo1_rd_en : std_logic;
signal fifo1_wr_en : std_logic;
signal fifo1_almost_full : std_logic;
signal fifo1_dout : std_logic_VECTOR(15 downto 0);
signal fifo1_valid : std_logic;
component fifo_32b_to_16b
port (
din : IN std_logic_VECTOR(31 downto 0);
rd_clk : IN std_logic;
rd_en : IN std_logic;
rst : IN std_logic;
wr_clk : IN std_logic;
wr_en : IN std_logic;
almost_full : OUT std_logic;
dout : OUT std_logic_VECTOR(15 downto 0);
empty : OUT std_logic;
full : OUT std_logic;
valid : OUT std_logic);
end component;
-- FIFO 16 bit to 32 bit
signal fifo2_din : std_logic_VECTOR(15 downto 0);
signal fifo2_rd_en : std_logic;
signal fifo2_wr_en : std_logic;
signal fifo2_almost_full : std_logic;
signal fifo2_dout : std_logic_VECTOR(31 downto 0);
signal fifo2_valid : std_logic;
signal fifo2_full : std_logic;
signal odd_bytes : std_logic;
signal insert_blank : std_logic;
component fifo_16b_to_32b
port (
din : IN std_logic_VECTOR(15 downto 0);
rd_clk : IN std_logic;
rd_en : IN std_logic;
rst : IN std_logic;
wr_clk : IN std_logic;
wr_en : IN std_logic;
almost_full : OUT std_logic;
dout : OUT std_logic_VECTOR(31 downto 0);
empty : OUT std_logic;
full : OUT std_logic;
valid : OUT std_logic);
end component;
|
- Find the line of code that says “–USER logic implementation added here” and add the following lines of code just below.
-- Clock buffering
ref_clk_ibufds_i : IBUFDS
port map(
O => ref_clk,
I => REFCLK_P_IN,
IB => REFCLK_N_IN
);
emac_out_clk_bufg_i : BUFG
port map(
I => user_clk_out,
O => user_clk_eth
);
aurora_out_clk_bufg_i : BUFG
port map(
I => tx_out_clk_i,
O => buf_tx_out_clk_i
);
-- Aurora clock module for clock division
clock_module_i : aurora_201_CLOCK_MODULE
port map(
GTP_CLK => buf_tx_out_clk_i,
GTP_CLK_LOCKED => tx_lock_i,
USER_CLK => user_clk_aur,
SYNC_CLK => sync_clk_i,
DCM_NOT_LOCKED => dcm_not_locked_i
);
-- Reset logic
rst_gtp <= Bus2IP_Reset;
rst_fifos <= ll_reset_0_i or reset_aurora;
PHY_RESET_0 <= not rst_gtp; -- 1.25/12.5/125MHz clock from the MAC is routed through a BUFG and -- input to the MAC wrappers to clock the client interface. bufg_client_0 : BUFG port map (I => client_clk_0_o, O => client_clk_0);
-- Status outputs
HARD_ERROR <= HARD_ERROR_Buffer;
SOFT_ERROR <= SOFT_ERROR_Buffer;
FRAME_ERROR <= FRAME_ERROR_Buffer;
LANE_UP <= LANE_UP_Buffer;
CHANNEL_UP <= CHANNEL_UP_Buffer;
-- Register Status Outputs from core
process (user_clk_aur)
begin
if (user_clk_aur 'event and user_clk_aur = '1') then
HARD_ERROR_Buffer <= hard_error_i;
SOFT_ERROR_Buffer <= soft_error_i;
FRAME_ERROR_Buffer <= frame_error_i;
LANE_UP_Buffer <= lane_up_i;
CHANNEL_UP_Buffer <= channel_up_i;
end if;
end process;
-- System Interface
power_down_i <= '0';
loopback_i <= "00" & slv_reg0(31); -- Aurora Module Instantiation aurora_module_i : aurora_201 port map( -- LocalLink TX Interface TX_D => tx_d_i,
TX_REM => tx_rem_i,
TX_SRC_RDY_N => tx_src_rdy_n_i,
TX_SOF_N => tx_sof_n_i,
TX_EOF_N => tx_eof_n_i,
TX_DST_RDY_N => tx_dst_rdy_n_i,
-- LocalLink RX Interface
RX_D => rx_d_i,
RX_REM => rx_rem_i,
RX_SRC_RDY_N => rx_src_rdy_n_i,
RX_SOF_N => rx_sof_n_i,
RX_EOF_N => rx_eof_n_i,
-- GTP Serial I/O
RXP => RXP_IN(0),
RXN => RXN_IN(0),
TXP => TXP_OUT(0),
TXN => TXN_OUT(0),
-- GTP Reference Clock Interface
GTPD1 => ref_clk,
-- Error Detection Interface
HARD_ERROR => hard_error_i,
SOFT_ERROR => soft_error_i,
FRAME_ERROR => frame_error_i,
-- Status
CHANNEL_UP => channel_up_i,
LANE_UP => lane_up_i,
-- Clock Compensation Control Interface
WARN_CC => warn_cc_i,
DO_CC => do_cc_i,
-- System Interface
DCM_NOT_LOCKED => dcm_not_locked_i,
USER_CLK => user_clk_aur,
SYNC_CLK => sync_clk_i,
RESET => reset_aurora,
POWER_DOWN => power_down_i,
LOOPBACK => loopback_i,
PMA_INIT => rst_gtp,
TX_LOCK => tx_lock_i,
TX_OUT_CLK => tx_out_clk_i
);
standard_cc_module_i : aurora_201_STANDARD_CC_MODULE
port map (
-- Clock Compensation Control Interface
WARN_CC => warn_cc_i,
DO_CC => do_cc_i,
-- System Interface
DCM_NOT_LOCKED => dcm_not_locked_i,
USER_CLK => user_clk_aur,
CHANNEL_UP => channel_up_i
);
-- Create synchronous reset in the USER_CLK_AUR domain
gen_reset_aurora : process (user_clk_aur, rst_gtp)
begin
if rst_gtp = '1' then
pre_reset_aurora <= (others => '1');
reset_aurora <= '1';
elsif user_clk_aur'event and user_clk_aur = '1' then
if tx_lock_i = '1' then
pre_reset_aurora(0) <= '0';
pre_reset_aurora(5 downto 1) <= pre_reset_aurora(4 downto 0);
reset_aurora <= pre_reset_aurora(5); end if; end if; end process gen_reset_aurora; ------------------------------------------------------------------------ -- Instantiate the EMAC Wrapper with LL FIFO -- (v5_emac_v1_5_locallink.v) ------------------------------------------------------------------------ v5_emac_ll : v5_emac_v1_5_locallink port map ( -- EMAC0 Clocking -- 125MHz clock output from transceiver CLK125_OUT => user_clk_out,
-- 125MHz clock input from BUFG
CLK125 => user_clk_eth,
-- Tri-speed clock output from EMAC0
CLIENT_CLK_OUT_0 => client_clk_0_o,
-- EMAC0 Tri-speed clock input from BUFG
CLIENT_CLK_0 => client_clk_0,
-- Local link Receiver Interface - EMAC0
RX_LL_CLOCK_0 => user_clk_eth,
RX_LL_RESET_0 => ll_reset_0_i,
RX_LL_DATA_0 => rx_ll_data_0_i,
RX_LL_SOF_N_0 => rx_ll_sof_n_0_i,
RX_LL_EOF_N_0 => rx_ll_eof_n_0_i,
RX_LL_SRC_RDY_N_0 => rx_ll_src_rdy_n_0_i,
RX_LL_DST_RDY_N_0 => rx_ll_dst_rdy_n_0_i,
RX_LL_FIFO_STATUS_0 => rx_ll_fifo_status_0_i,
-- Unused Receiver signals - EMAC0
EMAC0CLIENTRXDVLD => open,
EMAC0CLIENTRXFRAMEDROP => open,
EMAC0CLIENTRXSTATS => open,
EMAC0CLIENTRXSTATSVLD => open,
EMAC0CLIENTRXSTATSBYTEVLD => open,
-- Local link Transmitter Interface - EMAC0
TX_LL_CLOCK_0 => user_clk_eth,
TX_LL_RESET_0 => ll_reset_0_i,
TX_LL_DATA_0 => tx_ll_data_0_i,
TX_LL_SOF_N_0 => tx_ll_sof_n_0_i,
TX_LL_EOF_N_0 => tx_ll_eof_n_0_i,
TX_LL_SRC_RDY_N_0 => tx_ll_src_rdy_n_0_i,
TX_LL_DST_RDY_N_0 => tx_ll_dst_rdy_n_0_i,
-- Unused Transmitter signals - EMAC0
CLIENTEMAC0TXIFGDELAY => "00000000",
EMAC0CLIENTTXSTATS => open,
EMAC0CLIENTTXSTATSVLD => open,
EMAC0CLIENTTXSTATSBYTEVLD => open,
-- MAC Control Interface - EMAC0
CLIENTEMAC0PAUSEREQ => '0',
CLIENTEMAC0PAUSEVAL => "0000000000000000",
--EMAC-MGT link status
EMAC0CLIENTSYNCACQSTATUS => EMAC_READY,
-- EMAC0 Interrupt
EMAC0ANINTERRUPT => open,
-- Clock Signals - EMAC0
-- SGMII Interface - EMAC0
TXP_0 => TXP_OUT(1),
TXN_0 => TXN_OUT(1),
RXP_0 => RXP_IN(1),
RXN_0 => RXN_IN(1),
PHYAD_0 => "00010",
RESETDONE_0 => resetdone_0_i,
-- unused transceiver
TXN_1_UNUSED => open,
TXP_1_UNUSED => open,
RXN_1_UNUSED => '1',
RXP_1_UNUSED => '0',
-- SGMII RocketIO Reference Clock buffer inputs
CLK_DS => ref_clk,
-- Asynchronous Reset
RESET => rst_gtp
);
-- Create synchronous reset in the transmitter clock domain.
gen_ll_reset_emac0 : process (user_clk_eth, rst_gtp)
begin
if rst_gtp = '1' then
ll_pre_reset_0_i <= (others => '1');
ll_reset_0_i <= '1';
elsif user_clk_eth'event and user_clk_eth = '1' then
if resetdone_0_i = '1' then
ll_pre_reset_0_i(0) <= '0';
ll_pre_reset_0_i(5 downto 1) <= ll_pre_reset_0_i(4 downto 0);
ll_reset_0_i <= ll_pre_reset_0_i(5);
end if;
end if;
end process gen_ll_reset_emac0;
----------------------------------------------------
-- FIFO1 Instantiation and connections
----------------------------------------------------
-- EMAC TX (8 bits) <- FIFO1 <- Aurora RX (16 bits) fifo1_i : fifo_32b_to_16b port map ( din => fifo1_din,
rd_clk => user_clk_eth,
rd_en => fifo1_rd_en,
rst => rst_fifos,
wr_clk => user_clk_aur,
wr_en => fifo1_wr_en,
almost_full => fifo1_almost_full,
dout => fifo1_dout,
empty => open,
full => open,
valid => fifo1_valid);
-- Connections between EMAC TX and FIFO1
tx_ll_data_0_i <= fifo1_dout(7 downto 0);
tx_ll_sof_n_0_i <= not fifo1_dout(8);
tx_ll_eof_n_0_i <= not fifo1_dout(9);
tx_ll_src_rdy_n_0_i <= (not fifo1_valid) or fifo1_dout(10);
fifo1_rd_en <= not tx_ll_dst_rdy_n_0_i;
-- Connections between FIFO1 and Aurora
fifo1_din(23 downto 16) <= rx_d_i(0 to 7);
fifo1_din(7 downto 0) <= rx_d_i(8 to 15);
fifo1_din(24) <= not rx_sof_n_i;
fifo1_din(25) <= (not rx_eof_n_i) and (not rx_rem_i);
fifo1_din(9) <= (not rx_eof_n_i) and rx_rem_i;
fifo1_din(10) <= (not rx_eof_n_i) and (not rx_rem_i);
fifo1_wr_en <= not rx_src_rdy_n_i; ---------------------------------------------------- -- FIFO2 Instantiation and connections ---------------------------------------------------- -- EMAC RX (8 bits) -> FIFO2 -> Aurora TX (16 bits)
fifo2_i : fifo_16b_to_32b
port map (
din => fifo2_din,
rd_clk => user_clk_aur,
rd_en => fifo2_rd_en,
rst => rst_fifos,
wr_clk => user_clk_eth,
wr_en => fifo2_wr_en,
almost_full => fifo2_almost_full,
dout => fifo2_dout,
empty => open,
full => fifo2_full,
valid => fifo2_valid);
-- Connections between FIFO2 and EMAC RX
fifo2_din(7 downto 0) <= rx_ll_data_0_i;
fifo2_din(8) <= (not rx_ll_sof_n_0_i) and (not insert_blank);
fifo2_din(9) <= (not rx_ll_eof_n_0_i) and (not insert_blank);
fifo2_wr_en <= (not rx_ll_src_rdy_n_0_i) or insert_blank;
rx_ll_dst_rdy_n_0_i <= fifo2_almost_full;
-- Connections between Aurora TX and FIFO2
tx_d_i(0 to 7) <= fifo2_dout(23 downto 16);
tx_d_i(8 to 15) <= fifo2_dout(7 downto 0);
tx_sof_n_i <= not fifo2_dout(24);
tx_eof_n_i <= not (fifo2_dout(9) or fifo2_dout(25));
tx_rem_i <= fifo2_dout(9);
tx_src_rdy_n_i <= not fifo2_valid;
fifo2_rd_en <= not tx_dst_rdy_n_i;
-- Logic to generate "odd_bytes" signal that is asserted for
-- every ODD byte of an Ethernet frame written into FIFO2.
process (user_clk_eth, rst_fifos)
begin
if rst_fifos = '1' then
odd_bytes <= '1';
elsif user_clk_eth'event and user_clk_eth = '1' then
if rx_ll_src_rdy_n_0_i = '0' and fifo2_almost_full = '0' then
odd_bytes <= (not odd_bytes) or (not rx_ll_eof_n_0_i);
end if;
end if;
end process;
-- Logic to generate "insert_blank" signal to write an extra byte
-- into FIFO2 when the frame contained an ODD number of bytes.
process (user_clk_eth, rst_fifos)
begin
if rst_fifos = '1' then
insert_blank <= '0';
elsif user_clk_eth'event and user_clk_eth = '1' then
insert_blank <= odd_bytes and (not rx_ll_eof_n_0_i) and (not rx_ll_src_rdy_n_0_i) and (not fifo2_almost_full);
end if;
end process;
|
- Save and close the file.
Import the Bridge Peripheral
Now we will use the Peripheral Wizard again, but this time using the import function.
- Select from the menu “Hardware->Create or Import Peripheral” and click “Next”.
- Select “Import existing peripheral” and click “Next”.
- Select “To an XPS project”, ensure that the folder chosen is the project folder, and click “Next”.
- For the name of the peripheral, type “bridge”. Tick “Use version” and select the same version number that we originally created. Click “Next”. It will ask if we are willing to overwrite the existing peripheral and we should answer “Yes”.
- Tick “HDL source files” and “Netlist files” and click “Next”.
- Select “Use existing Peripheral Analysis Order file (*.pao)” and click “Browse”. From the project folder, go to “pcores\bridge_v1_00_a\data” and select the “bridge_v2_1_0.pao” file. Click “Next”.
- On the “HDL analysis information” page, click “Next”. The wizard will mention if any errors are found in the design.
- On the “Bus Interfaces” page, tick “PLB Slave” and click “Next”.
- On the “SPLB: Port” page, click “Next”.
- On the “SPLB: Parameter” page, click “Next”.
- On the “Identify Interrupt Signals” page, untick “Select and Configure Interrupts” and click “Next”.
- On the “Parameter Attributes” page, click “Next”.
- On the “Port Attributes” page, click “Next”.
- On the “Netlist Files” page, click “Select Files” and browse to the “ClockCrossFIFO” folder. You should have created this folder earlier in the Clock Domain Crossing FIFO tutorial. Select both NGC files and click “OK. You should now see the two FIFO netlist files listed in the dialog box as shown below. Click “Next”.
- Click “Finish”.
The Bridge peripheral is now ready to use and it should be accessible through the “IP Catalog->Project Local pcores” in the XPS interface.
Create an Instance of the Peripheral
Now we are ready to create an instance of the peripheral into our project.
- From the “IP Catalog” find the “bridge” IP core in the “Project Local pcores” group. Right click on the core and select “Add IP”.
- From the “System Assembly View” using the “Bus Interface” filter, connect the “bridge_0″ to the PLB bus.
- Click on the “Ports” filter. Click on the “+” for “bridge_0″ to view its ports.
- Click on the “Net” field for the “CHANNEL_UP” port. Type “CHANNEL_UP” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External”.
- Click on the “Net” field for the “LANE_UP” port. Type “LANE_UP” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External”.
- Click on the “Net” field for the “FRAME_ERROR” port. Type “FRAME_ERROR” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External”.
- Click on the “Net” field for the “SOFT_ERROR” port. Type “SOFT_ERROR” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External”.
- Click on the “Net” field for the “HARD_ERROR” port. Type “HARD_ERROR” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External”.
- Click on the “Net” field for the “PHY_RESET_0″ port. Type “PHY_RESET_0″ in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External”.
- Click on the “Net” field for the “EMAC_READY” port. Type “EMAC_READY” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External”.
- Click on the “Net” field for the “REFCLK_P_IN” port. Type “REFCLK_P_IN” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External”.
- Click on the “Net” field for the “REFCLK_N_IN” port. Type “REFCLK_N_IN” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External”.
- Click on the “Addresses” filter. Change the “Size” for “bridge_0″ to 64K. Then click “Generate Addresses”.
Now we have created an instance of the Bridge peripheral in our design.
Create a GPIO Instance for the LCD
Our software application will control the LCD so we need to instantiate a GPIO peripheral to connect to it.
- From the “IP Catalog” find the “XPS General Purpose IO” peripheral in the “General Purpose IO” group. Right click on the core and select “Add IP”.
- From the “System Assembly View”, using the “Bus Interface” filter you will notice that the GPIO was added as “xps_gpio_0″. Click on the “xps_gpio_0″ peripheral and rename it to “LCD”, then connect it to the PLB bus.
- Double click on the “LCD” to bring up the peripheral settings. Set the “GPIO Data Channel Width” to 7 bits then click “OK”.
- Click on the “Ports” filter. Click on the “+” for “LCD” to view its ports.
- Click on the “Net” field for the “GPIO_IO” port. Type “LCD_IO” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External”.
- Click on the “Addresses” filter. Change the “Size” for “LCD” to 64K. Then click “Generate Addresses”.
Our GPIO for the LCD is now instantiated in our project.
Modify the Constraints file
The Bridge peripheral requires timing and pin constraints, as well as a constraint to select the RocketIO GTPs we will use for a link to the PHY and the SATA HOST 1 connector. The clocks used must be constrained to 125MHz and 62.5MHz while the PHY reset and status signals must be assigned to specific pins. The GTP and pins that we select here were obtained from the schematic for the ML505.
- Click the “Project” tab and double click on the UCF file to open it.
- Add the following lines to the end of the file:
##### Constraints added by tutorial ##### ##### Clock Constraints ################# # User Clock Constraints # GTP reference clock NET "*ref_clk" PERIOD = 8.0 ns; # 125MHz EMAC user clock NET "*user_clk_eth" TNM_NET = "clk_gtp"; TIMEGRP "v5_emac_v1_5_gtp_clk" = "clk_gtp"; TIMESPEC "TS_v5_emac_v1_5_gtp_clk" = PERIOD "v5_emac_v1_5_gtp_clk" 7700 ps HIGH 50 %; # 62.5MHz Aurora user clock NET "*user_clk_aur" PERIOD = 16.0 ns; ####### LEDs, LCD and PHY reset ######### # Error pins NET "FRAME_ERROR_pin" LOC = AD25; #LED 5 NET "FRAME_ERROR_pin" IOSTANDARD=LVCMOS18; NET "FRAME_ERROR_pin" PULLDOWN; NET "FRAME_ERROR_pin" SLEW=SLOW; NET "FRAME_ERROR_pin" DRIVE=2; NET "SOFT_ERROR_pin" LOC = G16; #LED 4 NET "SOFT_ERROR_pin" IOSTANDARD=LVCMOS33; NET "SOFT_ERROR_pin" PULLDOWN; NET "SOFT_ERROR_pin" SLEW=SLOW; NET "SOFT_ERROR_pin" DRIVE=2; NET "HARD_ERROR_pin" LOC = AD26; #LED 3 NET "HARD_ERROR_pin" IOSTANDARD=LVCMOS18; NET "HARD_ERROR_pin" PULLDOWN; NET "HARD_ERROR_pin" SLEW=SLOW; NET "HARD_ERROR_pin" DRIVE=2; # Status pins NET "CHANNEL_UP_pin" LOC = G15; #LED 2 NET "CHANNEL_UP_pin" IOSTANDARD=LVCMOS33; NET "CHANNEL_UP_pin" PULLDOWN; NET "CHANNEL_UP_pin" SLEW=SLOW; NET "CHANNEL_UP_pin" DRIVE=2; NET "LANE_UP_pin" LOC = L18; #LED 1 NET "LANE_UP_pin" IOSTANDARD=LVCMOS33; NET "LANE_UP_pin" PULLDOWN; NET "LANE_UP_pin" SLEW=SLOW; NET "LANE_UP_pin" DRIVE=2; NET "EMAC_READY_pin" LOC = H18; #LED 0 NET "EMAC_READY_pin" IOSTANDARD=LVCMOS33; NET "EMAC_READY_pin" PULLDOWN; NET "EMAC_READY_pin" SLEW=SLOW; NET "EMAC_READY_pin" DRIVE=2; # PHY Reset signal NET "PHY_RESET_0_pin" LOC = J14; # ML505 PHY Reset Net "PHY_RESET_0_pin" IOSTANDARD=LVCMOS33; # Module LCD_IO constraints # LCD_FPGA_DB4 Net LCD_IO_pin<6> LOC = T9; Net LCD_IO_pin<6> IOSTANDARD=LVCMOS33; Net LCD_IO_pin<6> PULLDOWN; Net LCD_IO_pin<6> SLEW=SLOW; Net LCD_IO_pin<6> DRIVE=2; # LCD_FPGA_DB5 Net LCD_IO_pin<5> LOC = G7; Net LCD_IO_pin<5> IOSTANDARD=LVCMOS33; Net LCD_IO_pin<5> PULLDOWN; Net LCD_IO_pin<5> SLEW=SLOW; Net LCD_IO_pin<5> DRIVE=2; # LCD_FPGA_DB6 Net LCD_IO_pin<4> LOC = G6; Net LCD_IO_pin<4> IOSTANDARD=LVCMOS33; Net LCD_IO_pin<4> PULLDOWN; Net LCD_IO_pin<4> SLEW=SLOW; Net LCD_IO_pin<4> DRIVE=2; # LCD_FPGA_DB7 Net LCD_IO_pin<3> LOC = T11; Net LCD_IO_pin<3> IOSTANDARD=LVCMOS33; Net LCD_IO_pin<3> PULLDOWN; Net LCD_IO_pin<3> SLEW=SLOW; Net LCD_IO_pin<3> DRIVE=2; # LCD_FPGA_RW Net LCD_IO_pin<2> LOC = AC10; Net LCD_IO_pin<2> IOSTANDARD=LVCMOS33; Net LCD_IO_pin<2> PULLDOWN; Net LCD_IO_pin<2> SLEW=SLOW; Net LCD_IO_pin<2> DRIVE=2; # LCD_FPGA_RS Net LCD_IO_pin<1> LOC = J17; Net LCD_IO_pin<1> IOSTANDARD=LVCMOS33; Net LCD_IO_pin<1> PULLDOWN; Net LCD_IO_pin<1> SLEW=SLOW; Net LCD_IO_pin<1> DRIVE=2; # LCD_FPGA_E Net LCD_IO_pin<0> LOC = AC9; Net LCD_IO_pin<0> IOSTANDARD=LVCMOS33; Net LCD_IO_pin<0> PULLDOWN; Net LCD_IO_pin<0> SLEW=SLOW; Net LCD_IO_pin<0> DRIVE=2; ######################### mgt clock module constraints ######################## NET REFCLK_N_IN_pin LOC=P3; NET REFCLK_P_IN_pin LOC=P4; ################################# mgt wrapper constraints ##################### ## GTP_DUAL for the SATA HOST 1 connector INST */aurora_module_i/gtp_wrapper_i/GTP_DUAL_INST LOC=GTP_DUAL_X0Y2; ## GTP_DUAL for the Tri-mode EMAC INST "*GTP_DUAL_1000X_inst?GTP_1000X?tile0_rocketio_wrapper_i?gtp_dual_i" LOC=GTP_DUAL_X0Y3; ################################## # BLOCK Level constraints ################################## # EMAC0 Clocking # EMAC0 Tri-speed clock input from BUFG NET "*CLIENT_CLK_0" TNM_NET = "clk_client0"; TIMEGRP "v5_emac_v1_5_gtp_clk_client0" = "clk_client0"; TIMESPEC "TS_v5_emac_v1_5_gtp_clk_client0" = PERIOD "v5_emac_v1_5_gtp_clk_client0" 7700 ps HIGH 50 %; #----------------------------------------------------------- # EMAC0 Fabric Rx Elastic Buffer Timing Constraints: - #----------------------------------------------------------- NET "*GTP_DUAL_1000X_inst?RXRECCLK_0_BUFR" TNM_NET = "clk_rec_clk0"; TIMEGRP "v5_emac_v1_5_client_rec_clk0" = "clk_rec_clk0"; TIMESPEC "TS_v5_emac_v1_5_rec_clk0" = PERIOD "v5_emac_v1_5_client_rec_clk0" 7700 ps HIGH 50 %; # Control Gray Code delay and skew INST "*GTP_DUAL_1000X_inst?rx_elastic_buffer_inst_0?rd_addr_gray_?" TNM = "rx_elastic_rd_to_wr_0"; TIMESPEC "TS_rx_elastic_rd_to_wr_0" = FROM "rx_elastic_rd_to_wr_0" TO "clk_rec_clk0" 7500 ps DATAPATHONLY; INST "*GTP_DUAL_1000X_inst?rx_elastic_buffer_inst_0?wr_addr_gray_?" TNM = "elastic_metastable_0"; TIMESPEC "ts_elastic_meta_protect_0" = FROM "elastic_metastable_0" 5 ns DATAPATHONLY; # Reduce clock period to allow 3 ns for metastability settling time INST "*GTP_DUAL_1000X_inst?rx_elastic_buffer_inst_0?rd_wr_addr_gray*" TNM = "rx_graycode_0"; INST "*GTP_DUAL_1000X_inst?rx_elastic_buffer_inst_0?rd_occupancy*" TNM = "rx_binary_0"; TIMESPEC "ts_rx_buf_meta_protect_0" = FROM "rx_graycode_0" TO "rx_binary_0" 5 ns; ################################## # LocalLink Level constraints ################################## # EMAC0 LocalLink client FIFO constraints. INST "*client_side_FIFO_emac0?tx_fifo_i?rd_tran_frame_tog" TNM = "tx_fifo_rd_to_wr_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?rd_retran_frame_tog" TNM = "tx_fifo_rd_to_wr_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?rd_col_window_pipe_1" TNM = "tx_fifo_rd_to_wr_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?rd_addr_txfer*" TNM = "tx_fifo_rd_to_wr_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?rd_txfer_tog" TNM = "tx_fifo_rd_to_wr_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_frame_in_fifo" TNM = "tx_fifo_wr_to_rd_0"; TIMESPEC "TS_tx_fifo_rd_to_wr_0" = FROM "tx_fifo_rd_to_wr_0" TO "v5_emac_v1_5_gtp_clk_client0" 8000 ps DATAPATHONLY; TIMESPEC "TS_tx_fifo_wr_to_rd_0" = FROM "tx_fifo_wr_to_rd_0" TO "v5_emac_v1_5_gtp_clk_client0" 8000 ps DATAPATHONLY; # Reduce clock period to allow 3 ns for metastability settling time INST "*client_side_FIFO_emac0?tx_fifo_i?wr_tran_frame_tog" TNM = "tx_metastable_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_rd_addr*" TNM = "tx_metastable_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_txfer_tog" TNM = "tx_metastable_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?frame_in_fifo" TNM = "tx_metastable_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_retran_frame_tog*" TNM = "tx_metastable_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_col_window_pipe_0" TNM = "tx_metastable_0"; TIMESPEC "ts_tx_meta_protect_0" = FROM "tx_metastable_0" 5 ns DATAPATHONLY; INST "*client_side_FIFO_emac0?tx_fifo_i?rd_addr_txfer*" TNM = "tx_addr_rd_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_rd_addr*" TNM = "tx_addr_wr_0"; TIMESPEC "TS_tx_fifo_addr_0" = FROM "tx_addr_rd_0" TO "tx_addr_wr_0" 10ns; ## RX Client FIFO # Group the clock crossing signals into timing groups INST "*client_side_FIFO_emac0?rx_fifo_i?wr_store_frame_tog" TNM = "rx_fifo_wr_to_rd_0"; INST "*client_side_FIFO_emac0?rx_fifo_i?rd_addr_gray*" TNM = "rx_fifo_rd_to_wr_0"; TIMESPEC "TS_rx_fifo_wr_to_rd_0" = FROM "rx_fifo_wr_to_rd_0" TO "v5_emac_v1_5_gtp_clk_client0" 8000 ps DATAPATHONLY; TIMESPEC "TS_rx_fifo_rd_to_wr_0" = FROM "rx_fifo_rd_to_wr_0" TO "v5_emac_v1_5_gtp_clk_client0" 8000 ps DATAPATHONLY; # Reduce clock period to allow for metastability settling time INST "*client_side_FIFO_emac0?rx_fifo_i?wr_rd_addr_gray_sync*" TNM = "rx_metastable_0"; INST "*client_side_FIFO_emac0?rx_fifo_i?rd_store_frame_tog" TNM = "rx_metastable_0"; TIMESPEC "ts_rx_meta_protect_0" = FROM "rx_metastable_0" 5 ns; # PHY Autonegotiate ON INST *?v5_emac EMAC0_PHYINITAUTONEG_ENABLE = TRUE; |
- Save and close the file.
The constraints given above that assign the GTP for the EMAC and the Aurora core are specific to the ML505 board. We have reiterated those constraints below just so that you can see them. It is important that you change these assignments if you are using another board such as the ML506, ML507 or XUPV5.
## GTP_DUAL for the SATA HOST 1 connector INST */aurora_module_i/gtp_wrapper_i/GTP_DUAL_INST LOC=GTP_DUAL_X0Y2; ## GTP_DUAL for the Tri-mode EMAC INST "*GTP_DUAL_1000X_inst?GTP_1000X?tile0_rocketio_wrapper_i?gtp_dual_i" LOC=GTP_DUAL_X0Y3; |
Make sure that the GTP assignments are the right ones for your particular board by checking the table below. We need to assign the GTP_DUAL for the EMAC to SGMII (BANK112) and the Aurora core to SATA (BANK114).
| ML505 | ML506 | ML507 | XUPV5 | |
| XC5VLX50T | XC5VSX50T | XC5VFX70T | XC5VLX110T | |
| SGMII (BANK112) | GTP_DUAL X0Y3 | GTP_DUAL X0Y3 | GTX_DUAL X0Y4 | GTP_DUAL X0Y4 |
| SATA (BANK114) | GTP_DUAL X0Y2 | GTP_DUAL X0Y2 | GTX_DUAL X0Y3 | GTP_DUAL X0Y3 |
Modify the Software Application
Our software application will write a message on the LCD and control the loopback setting. In the main loop, the program polls the DIP switches for a change in switch 1. When switch 1 is ON, the loopback mode is enabled. When switch 1 is OFF, the loopback mode is disabled.
- From the “Applications” tab, open “Sources” within the “Project: TestApp_Peripheral” tree. Open the “TestApp_Peripheral.c” source file.
- Replace all the code in this file with the following source and save the file.
#include "xparameters.h"
#include "xgpio.h"
#include "xstatus.h"
#include "bridge.h"
// DIP Switch flags
#define DIPS_1 0x00000080
#define DIPS_2 0x00000040
#define DIPS_3 0x00000020
#define DIPS_4 0x00000010
#define DIPS_5 0x00000008
#define DIPS_6 0x00000004
#define DIPS_7 0x00000002
#define DIPS_8 0x00000001
// LCD Display strings
#define INIT_LCD1 "Design by FPGA"
#define INIT_LCD2 " Developer.com"
#define WELCOME_LCD1 "Aurora to"
#define WELCOME_LCD2 " Ethernet Bridge"
// Masks to the pins on the GPIO port
#define LCD_DB4 0x01
#define LCD_DB5 0x02
#define LCD_DB6 0x04
#define LCD_DB7 0x08
#define LCD_RW 0x10
#define LCD_RS 0x20
#define LCD_E 0x40
#define LCD_TEST 0x80
// Global variables
// Pointer and base address of Bridge peripheral
Xuint32 *bridge_0_baseaddr_p = (Xuint32 *) XPAR_BRIDGE_0_BASEADDR;
Xuint32 bridge_0_baseaddr;
// LCD GPIO peripheral
XGpio LCD;
// LCD Control Function prototypes
void writeLCD(Xuint8 *str1, Xuint8 *str2);
void delay(Xuint32 period);
void gpio_write(Xuint32 c);
Xuint32 gpio_read(void);
void lcd_clk(void);
void lcd_set_test(void);
void lcd_reset_test(void);
void lcd_set_rs(void);
void lcd_reset_rs(void);
void lcd_set_rw(void);
void lcd_reset_rw(void);
void lcd_write(Xuint32 c);
void lcd_clear(void);
void lcd_puts(const char * s);
void lcd_putch(Xuint32 c);
void lcd_goto(Xuint32 line,Xuint32 pos);
void lcd_init(void);
// Loopback mode function prototypes
void enable_loopback(void);
void disable_loopback(void);
// ------------------------------------------------------------------
// Main function
// ------------------------------------------------------------------
int main (void)
{
XGpio DIPs;
XStatus status;
Xuint32 value;
Xuint32 oldvalue;
// Check the peripheral pointers
XASSERT_NONVOID(bridge_0_baseaddr_p != XNULL);
bridge_0_baseaddr = (Xuint32) bridge_0_baseaddr_p;
// Initialize the GPIO driver for the DIP switches
status = XGpio_Initialize(&DIPs,XPAR_DIP_SWITCHES_8BIT_DEVICE_ID);
if (status != XST_SUCCESS)
return XST_FAILURE;
// Set the direction for all signals to be inputs
XGpio_SetDataDirection(&DIPs, 1, 0xFFFFFFFF);
// Read the initial state of the DIP switches
value = XGpio_DiscreteRead(&DIPs,1);
// Enable loopback if set by DIP switches
if(value & DIPS_1)
enable_loopback();
else
disable_loopback();
// Initialize the GPIO driver for the LCD
status = XGpio_Initialize(&LCD,XPAR_LCD_DEVICE_ID);
if (status != XST_SUCCESS)
return XST_FAILURE;
// Set the direction for all signals to be outputs
XGpio_SetDataDirection(&LCD, 1, 0x00);
// Initialize the LCD
lcd_init();
writeLCD(INIT_LCD1,INIT_LCD2);
delay(12500000);
writeLCD(WELCOME_LCD1,WELCOME_LCD2);
while(1){
// Record the old DIP settings
oldvalue = value;
// Read the new DIP settings
value = XGpio_DiscreteRead(&DIPs,1);
// If DIP settings have changed, then change loopback mode
if(value != oldvalue){
// Enable loopback if set by DIP switches
if(value & DIPS_1)
enable_loopback();
else
disable_loopback();
}
}
}
// LCD Control Functions
void writeLCD(Xuint8 *str1, Xuint8 *str2)
{
lcd_clear();
lcd_puts(str1);
lcd_goto(1,0);
lcd_puts(str2);
}
// Simple delay function
// Very approximately 1 period = 80ns
void delay(Xuint32 period)
{
volatile Xuint32 i;
for(i = 0; i < period; i++){} } // Write to GPIO outputs void gpio_write(Xuint32 c) { // Write to the GP IOs XGpio_DiscreteWrite(&LCD, 1, c & 0x0FF); } // Read the GPIO outputs Xuint32 gpio_read() { // Read from the GP IOs return(XGpio_DiscreteRead(&LCD, 1)); } // Clock the LCD (toggles E) void lcd_clk() { Xuint32 c; // Get existing outputs c = gpio_read(); delay(10); // Assert clock signal gpio_write(c | LCD_E); delay(10); // Deassert the clock signal gpio_write(c & (~LCD_E)); delay(10); } // Assert the RS signal void lcd_set_rs() { Xuint32 c; // Get existing outputs c = gpio_read(); // Assert RS gpio_write(c | LCD_RS); delay(10); } // Deassert the RS signal void lcd_reset_rs() { Xuint32 c; // Get existing outputs c = gpio_read(); // Assert RS gpio_write(c & (~LCD_RS)); delay(10); } // Assert the RW signal void lcd_set_rw() { Xuint32 c; // Get existing outputs c = gpio_read(); // Assert RS gpio_write(c | LCD_RW); delay(10); } // Deassert the RW signal void lcd_reset_rw() { Xuint32 c; // Get existing outputs c = gpio_read(); // Assert RS gpio_write(c & (~LCD_RW)); delay(10); } // Write a byte to LCD (4 bit mode) void lcd_write(Xuint32 c) { Xuint32 temp; // Get existing outputs temp = gpio_read(); temp = temp & 0xF0; // Set the high nibble temp = temp | ((c >> 4) & 0x0F);
gpio_write(temp);
// Clock
lcd_clk();
// Delay for "Write data into internal RAM 43us"
delay(2500);
// Set the low nibble
temp = temp & 0xF0;
temp = temp | (c & 0x0F);
gpio_write(temp);
// Clock
lcd_clk();
// Delay for "Write data into internal RAM 43us"
delay(2500);
}
// Clear LCD
void lcd_clear(void)
{
lcd_reset_rs();
// Clear LCD
lcd_write(0x01);
// Delay for "Clear display 1.53ms"
delay(125000);
}
// Write a string to the LCD
void lcd_puts(const char * s)
{
lcd_set_rs();
while(*s)
lcd_write(*s++);
}
// Write character to the LCD
void lcd_putch(Xuint32 c)
{
lcd_set_rs();
lcd_write(c);
}
// Change cursor position
// (line = 0 or 1, pos = 0 to 15)
void lcd_goto(Xuint32 line, Xuint32 pos)
{
lcd_reset_rs();
pos = pos & 0x3F;
if(line == 0)
lcd_write(0x80 | pos);
else
lcd_write(0xC0 | pos);
}
// Initialize the LCD
void lcd_init(void)
{
Xuint32 temp;
// Write mode (always)
lcd_reset_rw();
// Write control bytes
lcd_reset_rs();
// Delay 15ms
delay(200000);
// Initialize
temp = gpio_read();
temp = temp | LCD_DB5;
gpio_write(temp);
lcd_clk();
lcd_clk();
lcd_clk();
// Delay 15ms
delay(200000);
// Function Set: 4 bit mode, 1/16 duty, 5x8 font, 2 lines
lcd_write(0x28);
// Display ON/OFF Control: ON
lcd_write(0x0C);
// Entry Mode Set: Increment (cursor moves forward)
lcd_write(0x06);
// Clear the display
lcd_clear();
}
// Enable loopback mode
void enable_loopback(void)
{
BRIDGE_mWriteSlaveReg0(bridge_0_baseaddr,0,1);
}
// Disable loopback mode
void disable_loopback(void)
{
BRIDGE_mWriteSlaveReg0(bridge_0_baseaddr,0,0);
}
|
Download Project to your Board
Follow these steps to compile the project and program the FPGA.
- Turn on the ML505 board.
- From the XPS software, select “Device Configuration->Download Bitstream”.
EDK will now compile the project and when finished it will program the FPGA. When completed, the LCD output should display the message “Aurora to Ethernet Bridge”. When you get this message, you can continue with the following tests.
Test the Bridge in Loopback Mode
- To perform this test you only need one ML505 board, one PC and one CAT5 Ethernet cable.
- Locate the DIP switches (SW8) in the corner of the ML505 board, next to the LCD. Turn switch 1 to the ON position to enable loopback mode.
- Ensure that LEDs 0, 1 and 2 are ON. These LEDs can be found below the LCD and are numbered 0, 1 and 2. These LEDs correspond to EMAC_READY, LANE_UP and CHANNEL_UP respectively.
- Open Wireshark on the PC to be used for testing. You can use any PC with a Gigabit Ethernet network card installed and working.
- From the menu select “Edit->Preferences”. In the dialog box that opens, select “User Interface->Columns” and set the columns as shown in the screenshot below. Then click “OK”.
- From the menu select “Capture->Options”. In the dialog box that opens, select the Gigabit Ethernet network card to which you will connect the ML505, then click “Start”.
- Connect the CAT5 Ethernet cable between the ML505 and the PC running Wireshark.
- You should notice that the Ethernet connection LEDs light up on both the ML505 and the PC. The connection LEDs on the PC should be on the Ethernet (RJ45) connector on the back of your PC. The connection LEDs on the ML505 are located next to the PCI edge connector and they are shown in the photo below.
In order from left to right, as shown in the photo, the LEDs indicate: CONNECTION, TX, RX, 10Mbps, 100Mbps, 1000Mbps. - We will produce Ethernet packets from the PC by using “ping”. From Windows, select “Start->Run” and type “cmd”. Press “Enter” and you should have a command prompt. From the command line, type “ping www.google.com”. Note that even before running “ping”, you may already see Ethernet packets in Wireshark. This can happen when your PC is trying to connect to a network.
- Observe that when you run the ping command, the RX and TX LEDs on the ML505 will light up at the same time, indicating that each frame received is looped back and transmitted to the PC.
- Observe the packets in Wireshark by clicking on them. In the screenshot below, we see that the PC sent packets 1, 3 and 5, while the ML505 sent back packets 2, 4 and 6. Notice also the short time delay of 240us between the sent packet and the received copy.
- If you like, you can set switch 1 of the DIP switches to OFF to disable the loopback function and try running ping again. You should see this time that only three new Ethernet frames appear. You should also notice that only the EMAC RX LED lights up.
Test the Bridge between Two PCs
- To perform this test you will need two (2) ML505 boards, two (2) PCs with Gigabit Ethernet connections, two (2) CAT5 Ethernet cables and one (1) crossover SATA cable.
- On BOTH ML505 boards, locate the DIP switches (SW8) in the corner of the ML505 board, next to the LCD. Turn switch 1 to the OFF position to DISABLE loopback mode.
- Connect a crossover SATA cable from one ML505 board’s “SATA HOST 1″ connector to the other ML505 board’s “SATA HOST 1″ connector.
- Connect CAT5 Ethernet cables from each ML505 board to each PC.
- The connections should be as shown in the diagram below:
- Turn ON both ML505 boards and download the bit files to each board. Ensure that both boards are running and displaying the message “Aurora to Ethernet Bridge” message on their LCDs. The LEDs 0, 1 and 2 should also be ON.
- Turn on both PCs.
- From one PC, use Windows Explorer to locate a folder on the hard drive that you would like to access from the other PC. Right click on that folder and click “Sharing and Security”. For our example, we will assume the folder name is “fpgadeveloper”.
- From the “Properties” dialog box, tick “Share this folder” and click “OK”.
- From Windows, select “Start->Run” and type “cmd”. Press “Enter” and you should have a command prompt. From the command line, type “ipconfig” to get the IP address of the current PC. Record the IP address of the PC. For our example, we will assume the IP address is 123.456.789.012
- Now go to the OTHER PC, open Windows Explorer and type in the “Address” field the following line without the quotation marks: “//123.456.789.012/fpgadeveloper”
- Obviously you should replace the IP address and folder name with the ones you have used. You should see the folder contents appear in Windows Explorer.
- Click on one of the files to access it. You should see that the EMAC RX/TX LEDs will be lighting up as Ethernet packets flow through both Bridges.
You can experiment with this setup by doing other things such as video streaming from one PC to another, or you can replace one of the PCs with a router to connect you to a network. Let me know if you find any interesting uses.
If you have problems setting up file sharing with your computers, there are plenty of resources on the internet that you could try. Make sure to check that the problem is really the file sharing by connecting the two computers directly through a single Ethernet cable.
You now have a working Aurora to Ethernet Bridge running at 1Gbps. To develop the project further, try this idea:
- Assign the Aurora GTP to the SFP connector (rather than the SATA connector), buy yourself an SFP Optical Transceiver and communicate with another board over an optical fiber. The benefit of this is distance, with some SFP optical transceivers you can communicate over kilometers of fiber!
Download the Project Folder
If you had problems with this tutorial, you can download the Aurora to Ethernet Bridge project folder for EDK version 10.1.03. Click on the link below corresponding to the project files for your ML50x board.
| Board | Virtex-5 Version | Project files |
| ML505 | XC5VLX50T | AEBridge-ML505-EDK10-1.zip |
| ML506 | XC5VSX50T | AEBridge-ML506-EDK10-1.zip |
| XUPV5 | XC5VLX110T | AEBridge-XUPV5-EDK10-1.zip |
Tutorial Overview
The Virtex-5 Embedded Tri-mode Ethernet MAC is useful for designs requiring Ethernet connectivity. Fortunately, Xilinx has made it easy for us to start developing with the Ethernet MACs by providing several online examples and application notes. One of the examples can be obtained when you use CORE Generator to generate the Ethernet MAC wrapper. The generated example is a simple design that mirrors incoming Ethernet packets, swapping the source and destination MAC addresses. In this tutorial, we implement the example design provided by CORE Generator by working the example code into a custom peripheral for EDK 10.1.
This tutorial contains screenshots to guide you through the entire implementation process. Click on the images to view a higher resolution.
Requirements
Before following this tutorial, you will need to do the following:
- Generate the Virtex-5 Embedded Tri-mode Ethernet MAC Wrapper using CORE Generator. For instructions on doing this, please refer to the tutorial Generating the Ethernet MAC
- Set the J22 and J23 jumpers on the ML505 to positions 2-3 as shown below. This allows us to use an SGMII (serial) interface with the PHY.
- Install a copy of Wireshark on a PC with a Gigabit Ethernet network card
- Obtain a CAT5 Ethernet cable: regular or crossover, either will work because the PHY on the ML505 has an automatic switching feature that detects what type of cable you are using and switches the TX and RX pins if necessary.
- Buy an ML505/ML506/ML507 or XUPV5 board if you don’t already have one. Xilinx supplies the ML50x boards, but the best deal is the XUPV5 from Digilent. Click the Digilent link on this page for more information.
Create the Basic Project
Follow these steps to create the basic project:
- Open XPS. From the dialog box, select “Base System Builder wizard” and OK.
- You will be asked to specify which folder to place the project. Click “Browse” and create a new folder for the project. Click “OK”.
- We are given the choice to create a new project or to create one using the template of another project. Tick “I would like to create a new design” and click “Next”.
- On the “Select Board” page, select “Xilinx” as the board vendor. Select “Virtex 5 ML505 Evaluation Platform” as the board name. Select “1″ as the board revision. Click “Next”.
- On the “Select Processor” page, we normally have a choice between using the PowerPC “hard” processor, or the Microblaze “soft” processor. Since the Virtex-5 does not contain any PowerPCs, we can only select Microblaze. Click “Next”.
- On the “Configure Microblaze” page, select the clock frequency to be 125MHz. For the BRAM local memory, select “64KB”. We will use the RS232 port for debugging rather than the JTAG, so select “No debug”. Click “Next”.
- In selecting the Additional IO Interfaces, leave “RS232_Uart_1″ ticked and un-tick everything else.
- On the “Add Internal Peripherals” page, click “Next”.
- On the “Software Setup” page, select “RS232_Uart_1″ for both STDIN and STDOUT. Un-tick “Memory Test” and leave “Peripheral Test” ticked. Click “Next”.
- Click “Generate”.
- Click “Finish”.
Create the Ethernet MAC Peripheral
We now create our Ethernet MAC peripheral using the Peripheral Wizard.
- Select from the menu “Hardware->Create or Import Peripheral”. Click “Next”.
- Select “Create templates for a new peripheral” and click “Next”.
- We must now decide where to place the files for the peripheral. They can be placed within this project, or they can be made accessible to other projects. Select “To an XPS project”. Click “Next”.
- On the “Name and Version” page, type “eth_mac” for the peripheral name. Click “Next”.
- On the “Bus Interface” page, select “Processor Local Bus” (PLB) and click “Next”.
- On the “IPIF Services” page, select “Include data phase timer”. Un-tick everything else and click “Next”.
- On the “Slave Interface” page, leave the defaults and click “Next”.
- On the “Peripheral Simulation Support” page, we can specify if we want the wizard to create a simulation platform for our peripheral. Click “Next” without ticking the option to generate.
- After the “Peripheral Implementation Support” page, the wizard will generate all the template files for us. Tick “Generate ISE and XST project files” and “Generate template driver files”. Click “Next”.
- Click “Finish”. Now our templates are created and we can modify them to include the code for the timer.
Copy the Ethernet MAC source files
We need to copy the Ethernet MAC source files generated by CORE Generator into the Ethernet MAC peripheral source folder. If you have not generated the source files using CORE Generator, please refer to the tutorial Generating the Ethernet MAC.
- Open Windows Explorer and browse to the folder “TEMACCore\v5_emac_v1_5″. This is the folder you created with CORE Generator.
- In that folder, you will find a subfolder called “example_design”. Copy the “example_design” folder into the “pcores\eth_mac_v1_00_a\hdl\vhdl” folder within your XPS project. This is the folder where you should find your “user_logic.vhd” file for the Ethernet MAC peripheral.
Modify the .PAO file
The .pao file contains a list of all the source files that compose our peripheral. We use this list when we run the Peripheral Wizard in Import mode. Now that we have added the Ethernet MAC example source files to the project, we must include them in the .pao file. Note that files must be listed in the .pao file in hierarchical order. The components at the top of the hierarchy are listed at the bottom of the file.
- Select “File->Open” and browse to the “pcores\eth_mac_v1_00_a\data” folder. Select the file “eth_mac_v2_1_0.pao” and click “Open”.
- At the bottom of this file you will see these two lines:
lib eth_mac_v1_00_a user_logic vhdl lib eth_mac_v1_00_a eth_mac vhdl |
- Add the following lines just above those two lines. It is important to copy the lines exactly as shown and in the same order.
lib eth_mac_v1_00_a example_design/v5_emac_v1_5.vhd lib eth_mac_v1_00_a example_design/physical/rx_elastic_buffer.vhd lib eth_mac_v1_00_a example_design/physical/gtp_dual_1000X.vhd lib eth_mac_v1_00_a example_design/physical/rocketio_wrapper_gtp.vhd lib eth_mac_v1_00_a example_design/physical/rocketio_wrapper_gtp_tile.vhd lib eth_mac_v1_00_a example_design/v5_emac_v1_5_block.vhd lib eth_mac_v1_00_a example_design/client/fifo/tx_client_fifo_8.vhd lib eth_mac_v1_00_a example_design/client/fifo/rx_client_fifo_8.vhd lib eth_mac_v1_00_a example_design/client/fifo/eth_fifo_8.vhd lib eth_mac_v1_00_a example_design/v5_emac_v1_5_locallink.vhd lib eth_mac_v1_00_a example_design/client/address_swap_module_8.vhd |
- Save the file.
Now we can use this .pao file with the Peripheral Wizard when we import the Ethernet MAC peripheral.
Modify the Ethernet MAC Peripheral
If you refer back to the example design source files created by CORE Generator, you will find the top module contained in the file “v5_emac_v1_5\example_design\v5_emac_v1_5_example_design.vhd”. We copied that file into our peripheral source folder, but we wont directly use it in our design (notice that we didn’t include it in our .pao file). Instead, we will take the code from this file and work it into our “user_logic.vhd” file, the top module for our peripheral.
- Select from the menu “File->Open” and look in the project folder.
- Open the folders: “pcores\eth_mac_v1_00_a\hdl\vhdl”.
- Open the file “eth_mac.vhd”.
- Find the line of code that says “– ADD USER PORTS BELOW THIS LINE” and add the following lines of code just below.
REFCLK_N_IN : in std_logic; REFCLK_P_IN : in std_logic; GTP_READY : out std_logic; PHY_RESET_0 : out std_logic; RXP_IN : in std_logic; RXN_IN : in std_logic; TXP_OUT : out std_logic; TXN_OUT : out std_logic; |
- Find the line of code that says “– MAP USER PORTS BELOW THIS LINE” and add the following lines of code just below.
REFCLK_N_IN => REFCLK_N_IN, REFCLK_P_IN => REFCLK_P_IN, GTP_READY => GTP_READY, PHY_RESET_0 => PHY_RESET_0, RXP_IN => RXP_IN, RXN_IN => RXN_IN, TXP_OUT => TXP_OUT, TXN_OUT => TXN_OUT, |
- Save and close the file.
- Open the file “user_logic.vhd”. We will need to modify this source code to include our example code.
- Find the line of code that says “–USER libraries added here” and add the following lines of code just below.
library UNISIM; use UNISIM.VCOMPONENTS.ALL; |
- Find the line of code that says “– ADD USER PORTS BELOW THIS LINE” and add the following lines of code just below.
REFCLK_N_IN : in std_logic; REFCLK_P_IN : in std_logic; GTP_READY : out std_logic; PHY_RESET_0 : out std_logic; RXP_IN : in std_logic; RXN_IN : in std_logic; TXP_OUT : out std_logic; TXN_OUT : out std_logic; |
- Find the line of code that says “–USER signal declarations added here” and add the following lines of code just below.
-- Component Declaration for the TEMAC wrapper with
-- Local Link FIFO.
component v5_emac_v1_5_locallink is
port(
-- EMAC0 Clocking
-- 125MHz clock output from transceiver
CLK125_OUT : out std_logic;
-- 125MHz clock input from BUFG
CLK125 : in std_logic;
-- Tri-speed clock output from EMAC0
CLIENT_CLK_OUT_0 : out std_logic;
-- EMAC0 Tri-speed clock input from BUFG
client_clk_0 : in std_logic;
-- Local link Receiver Interface - EMAC0
RX_LL_CLOCK_0 : in std_logic;
RX_LL_RESET_0 : in std_logic;
RX_LL_DATA_0 : out std_logic_vector(7 downto 0);
RX_LL_SOF_N_0 : out std_logic;
RX_LL_EOF_N_0 : out std_logic;
RX_LL_SRC_RDY_N_0 : out std_logic;
RX_LL_DST_RDY_N_0 : in std_logic;
RX_LL_FIFO_STATUS_0 : out std_logic_vector(3 downto 0);
-- Local link Transmitter Interface - EMAC0
TX_LL_CLOCK_0 : in std_logic;
TX_LL_RESET_0 : in std_logic;
TX_LL_DATA_0 : in std_logic_vector(7 downto 0);
TX_LL_SOF_N_0 : in std_logic;
TX_LL_EOF_N_0 : in std_logic;
TX_LL_SRC_RDY_N_0 : in std_logic;
TX_LL_DST_RDY_N_0 : out std_logic;
-- Client Receiver Interface - EMAC0
EMAC0CLIENTRXDVLD : out std_logic;
EMAC0CLIENTRXFRAMEDROP : out std_logic;
EMAC0CLIENTRXSTATS : out std_logic_vector(6 downto 0);
EMAC0CLIENTRXSTATSVLD : out std_logic;
EMAC0CLIENTRXSTATSBYTEVLD : out std_logic;
-- Client Transmitter Interface - EMAC0
CLIENTEMAC0TXIFGDELAY : in std_logic_vector(7 downto 0);
EMAC0CLIENTTXSTATS : out std_logic;
EMAC0CLIENTTXSTATSVLD : out std_logic;
EMAC0CLIENTTXSTATSBYTEVLD : out std_logic;
-- MAC Control Interface - EMAC0
CLIENTEMAC0PAUSEREQ : in std_logic;
CLIENTEMAC0PAUSEVAL : in std_logic_vector(15 downto 0);
--EMAC-MGT link status
EMAC0CLIENTSYNCACQSTATUS : out std_logic;
-- EMAC0 Interrupt
EMAC0ANINTERRUPT : out std_logic;
-- Clock Signals - EMAC0
-- SGMII Interface - EMAC0
TXP_0 : out std_logic;
TXN_0 : out std_logic;
RXP_0 : in std_logic;
RXN_0 : in std_logic;
PHYAD_0 : in std_logic_vector(4 downto 0);
RESETDONE_0 : out std_logic;
-- unused transceiver
TXN_1_UNUSED : out std_logic;
TXP_1_UNUSED : out std_logic;
RXN_1_UNUSED : in std_logic;
RXP_1_UNUSED : in std_logic;
-- SGMII RocketIO Reference Clock buffer inputs
CLK_DS : in std_logic;
-- Asynchronous Reset
RESET : in std_logic
);
end component;
---------------------------------------------------------------------
-- Component Declaration for 8-bit address swapping module
---------------------------------------------------------------------
component address_swap_module_8
port (
rx_ll_clock : in std_logic;
rx_ll_reset : in std_logic;
rx_ll_data_in : in std_logic_vector(7 downto 0);
rx_ll_sof_in_n : in std_logic;
rx_ll_eof_in_n : in std_logic;
rx_ll_src_rdy_in_n : in std_logic;
rx_ll_data_out : out std_logic_vector(7 downto 0);
rx_ll_sof_out_n : out std_logic;
rx_ll_eof_out_n : out std_logic;
rx_ll_src_rdy_out_n : out std_logic;
rx_ll_dst_rdy_in_n : in std_logic
);
end component;
------------------------
-- Signal Declarations
------------------------
-- address swap transmitter connections - EMAC0
signal tx_ll_data_0_i : std_logic_vector(7 downto 0);
signal tx_ll_sof_n_0_i : std_logic;
signal tx_ll_eof_n_0_i : std_logic;
signal tx_ll_src_rdy_n_0_i : std_logic;
signal tx_ll_dst_rdy_n_0_i : std_logic;
-- address swap receiver connections - EMAC0
signal rx_ll_data_0_i : std_logic_vector(7 downto 0);
signal rx_ll_sof_n_0_i : std_logic;
signal rx_ll_eof_n_0_i : std_logic;
signal rx_ll_src_rdy_n_0_i : std_logic;
signal rx_ll_dst_rdy_n_0_i : std_logic;
-- create a synchronous reset in the transmitter clock domain
signal ll_pre_reset_0_i : std_logic_vector(5 downto 0);
signal ll_reset_0_i : std_logic;
attribute async_reg : string;
attribute async_reg of ll_pre_reset_0_i : signal is "true";
signal resetdone_0_i : std_logic;
-- EMAC0 Clocking signals
-- Transceiver output clock (REFCLKOUT at 125MHz)
signal user_clk_out : std_logic;
-- 125MHz clock input to wrappers
signal user_clk : std_logic;
-- Input 125MHz differential clock for transceiver
signal ref_clk : std_logic;
-- 1.25/12.5/125MHz clock signals for tri-speed SGMII
signal client_clk_0_o : std_logic;
signal client_clk_0 : std_logic;
|
- Find the line of code that says “–USER logic implementation added here” and add the following lines of code just below.
-- PHY Reset logic
PHY_RESET_0 <= not Bus2IP_Reset; -- EMAC0 Clocking -- Generate the clock input to the GTP -- clk_ds can be shared between multiple MAC instances. clkingen : IBUFDS port map ( I => REFCLK_P_IN,
IB => REFCLK_N_IN,
O => ref_clk);
-- 125MHz from transceiver is routed through a BUFG and
-- input to the MAC wrappers.
-- This clock can be shared between multiple MAC instances.
bufg_clk125 : BUFG port map (I => user_clk_out, O => user_clk);
-- 1.25/12.5/125MHz clock from the MAC is routed through a BUFG and
-- input to the MAC wrappers to clock the client interface.
bufg_client_0 : BUFG port map (I => client_clk_0_o, O => client_clk_0);
--------------------------------------------
-- Instantiate the EMAC Wrapper with LL FIFO
-- (v5_emac_v1_5_locallink.v)
--------------------------------------------
v5_emac_ll : v5_emac_v1_5_locallink
port map (
-- EMAC0 Clocking
-- 125MHz clock output from transceiver
CLK125_OUT => user_clk_out,
-- 125MHz clock input from BUFG
CLK125 => user_clk,
-- Tri-speed clock output from EMAC0
CLIENT_CLK_OUT_0 => client_clk_0_o,
-- EMAC0 Tri-speed clock input from BUFG
CLIENT_CLK_0 => client_clk_0,
-- Local link Receiver Interface - EMAC0
RX_LL_CLOCK_0 => user_clk,
RX_LL_RESET_0 => ll_reset_0_i,
RX_LL_DATA_0 => rx_ll_data_0_i,
RX_LL_SOF_N_0 => rx_ll_sof_n_0_i,
RX_LL_EOF_N_0 => rx_ll_eof_n_0_i,
RX_LL_SRC_RDY_N_0 => rx_ll_src_rdy_n_0_i,
RX_LL_DST_RDY_N_0 => rx_ll_dst_rdy_n_0_i,
RX_LL_FIFO_STATUS_0 => open,
-- Unused Receiver signals - EMAC0
EMAC0CLIENTRXDVLD => open,
EMAC0CLIENTRXFRAMEDROP => open,
EMAC0CLIENTRXSTATS => open,
EMAC0CLIENTRXSTATSVLD => open,
EMAC0CLIENTRXSTATSBYTEVLD => open,
-- Local link Transmitter Interface - EMAC0
TX_LL_CLOCK_0 => user_clk,
TX_LL_RESET_0 => ll_reset_0_i,
TX_LL_DATA_0 => tx_ll_data_0_i,
TX_LL_SOF_N_0 => tx_ll_sof_n_0_i,
TX_LL_EOF_N_0 => tx_ll_eof_n_0_i,
TX_LL_SRC_RDY_N_0 => tx_ll_src_rdy_n_0_i,
TX_LL_DST_RDY_N_0 => tx_ll_dst_rdy_n_0_i,
-- Unused Transmitter signals - EMAC0
CLIENTEMAC0TXIFGDELAY => "00000000",
EMAC0CLIENTTXSTATS => open,
EMAC0CLIENTTXSTATSVLD => open,
EMAC0CLIENTTXSTATSBYTEVLD => open,
-- MAC Control Interface - EMAC0
CLIENTEMAC0PAUSEREQ => '0',
CLIENTEMAC0PAUSEVAL => "0000000000000000",
--EMAC-MGT link status
EMAC0CLIENTSYNCACQSTATUS => GTP_READY,
-- EMAC0 Interrupt
EMAC0ANINTERRUPT => open,
-- Clock Signals - EMAC0
-- SGMII Interface - EMAC0
TXP_0 => TXP_OUT,
TXN_0 => TXN_OUT,
RXP_0 => RXP_IN,
RXN_0 => RXN_IN,
PHYAD_0 => "00010",
RESETDONE_0 => resetdone_0_i,
-- unused transceiver
TXN_1_UNUSED => open,
TXP_1_UNUSED => open,
RXN_1_UNUSED => '1',
RXP_1_UNUSED => '0',
-- SGMII RocketIO Reference Clock buffer inputs
CLK_DS => ref_clk,
-- Asynchronous Reset
RESET => Bus2IP_Reset
);
--------------------------------------------
-- Instatiate the address swapping module
--------------------------------------------
client_side_asm_emac0 : address_swap_module_8
port map (
rx_ll_clock => user_clk,
rx_ll_reset => ll_reset_0_i,
rx_ll_data_in => rx_ll_data_0_i,
rx_ll_sof_in_n => rx_ll_sof_n_0_i,
rx_ll_eof_in_n => rx_ll_eof_n_0_i,
rx_ll_src_rdy_in_n => rx_ll_src_rdy_n_0_i,
rx_ll_data_out => tx_ll_data_0_i,
rx_ll_sof_out_n => tx_ll_sof_n_0_i,
rx_ll_eof_out_n => tx_ll_eof_n_0_i,
rx_ll_src_rdy_out_n => tx_ll_src_rdy_n_0_i,
rx_ll_dst_rdy_in_n => tx_ll_dst_rdy_n_0_i
);
rx_ll_dst_rdy_n_0_i <= tx_ll_dst_rdy_n_0_i;
-- Create synchronous reset in the transmitter clock domain.
gen_ll_reset_emac0 : process (user_clk, Bus2IP_Reset)
begin
if Bus2IP_Reset = '1' then
ll_pre_reset_0_i <= (others => '1');
ll_reset_0_i <= '1';
elsif user_clk'event and user_clk = '1' then
if resetdone_0_i = '1' then
ll_pre_reset_0_i(0) <= '0';
ll_pre_reset_0_i(5 downto 1) <= ll_pre_reset_0_i(4 downto 0);
ll_reset_0_i <= ll_pre_reset_0_i(5);
end if;
end if;
end process gen_ll_reset_emac0;
|
- Save and close the file.
If you examine the “v5_emac_v1_5_example_design.vhd” from the CORE Generator output, you will see that most of the code we inserted into “user_logic.vhd” was directly copied from the example code. The main differences are:
- PHY Reset: We needed to add a signal (PHY_RESET_0) to drive the external Ethernet PHY reset pin. The PHY on the ML505 board has an active low reset input, so we connect it to the logical “not” of the bus reset signal.
- The clock signal names were changed for clarity. Most Xilinx documents refer to these clocks as REFCLK and USERCLK.
Import the Ethernet MAC Peripheral
Now we will use the Peripheral Wizard again, but this time using the import function.
- Select from the menu “Hardware->Create or Import Peripheral” and click “Next”.
- Select “Import existing peripheral” and click “Next”.
- Select “To an XPS project”, ensure that the folder chosen is the project folder, and click “Next”.
- For the name of the peripheral, type “eth_mac”. Tick “Use version” and select the same version number that we originally created. Click “Next”. It will ask if we are willing to overwrite the existing peripheral and we should answer “Yes”.
- Tick “HDL source files” and click “Next”.
- Select “Use existing Peripheral Analysis Order file (*.pao)” and click “Browse”. From the project folder, go to “pcores\eth_mac_v1_00_a\data” and select the “eth_mac_v2_1_0.pao” file. Click “Next”.
- On the “HDL analysis information” page, click “Next”. The wizard will mention if any errors are found in the design.
- On the “Bus Interfaces” page, tick “PLB Slave” and click “Next”.
- On the “SPLB: Port” page, click “Next”.
- On the “SPLB: Parameter” page, click “Next”.
- On the “Identify Interrupt Signals” page, untick “Select and Configure Interrupts” and click “Next”.
- On the “Parameter Attributes” page, click “Next”.
- On the “Port Attributes” page, click “Next”.
- Click “Finish”.
The Ethernet MAC peripheral is now ready to use and it should be accessible through the “IP Catalog->Project Local pcores” in the XPS interface. Note that although we can access it through the IP Catalog, other projects will not find it there because it is only associated with our project, as we specified in the Peripheral Wizard.
Create an Instance of the Peripheral
Now we are ready to create an instance of the peripheral into our project.
- From the “IP Catalog” find the “eth_mac” IP core in the “Project Local pcores” group. Right click on the core and select “Add IP”.
- From the “System Assembly View” using the “Bus Interface” filter, connect the “eth_mac_0″ to the PLB bus.
- Click on the “Ports” filter. Click on the “+” for “eth_mac_0″ to view its ports.
- Click on the “Net” field for the “PHY_RESET_0″ port. Type “PHY_RESET_0″ in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External” and press “Enter”.
- Click on the “Net” field for the “GTP_READY” port. Type “GTP_READY” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External” and press “Enter”.
- Click on the “Net” field for the “REFCLK_P_IN” port. Type “REFCLK_P_IN” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External” and press “Enter”.
- Click on the “Net” field for the “REFCLK_N_IN” port. Type “REFCLK_N_IN” in this field and press “Enter”. Now click again the same field and open the drop down menu. Select “Make External” and press “Enter”.
- Click on the “Addresses” filter. Change the “Size” for “eth_mac_0″ to 64K. Then click “Generate Addresses”.
Now we have created an instance of the Ethernet MAC peripheral in our design.
Modify the Constraints file
The Ethernet MAC peripheral requires timing and pin constraints, as well as a constraint to select the RocketIO GTP we will use for a link to the PHY. The clocks used must be constrained to 125MHz while the PHY reset and GTP ready signals must be assigned to specific pins. The GTP and pins that we select here were obtained from the schematic for the ML505.
- Click the “Project” tab and double click on the UCF file to open it.
- Add the following lines to the end of the file:
################################## # These constraints were adapted from the example # design produced by CORE Generator: # v5_emac_v1_5_example_design.ucf ################################## CONFIG PART = 5vlx50tff1136-1; ################################## # BLOCK Level constraints ################################## # EMAC0 Clocking # 125MHz clock input from BUFG NET "*user_clk" TNM_NET = "clk_gtp"; TIMEGRP "v5_emac_v1_5_gtp_clk" = "clk_gtp"; TIMESPEC "TS_v5_emac_v1_5_gtp_clk" = PERIOD "v5_emac_v1_5_gtp_clk" 7700 ps HIGH 50 %; # EMAC0 Tri-speed clock input from BUFG NET "*CLIENT_CLK_0" TNM_NET = "clk_client0"; TIMEGRP "v5_emac_v1_5_gtp_clk_client0" = "clk_client0"; TIMESPEC "TS_v5_emac_v1_5_gtp_clk_client0" = PERIOD "v5_emac_v1_5_gtp_clk_client0" 7700 ps HIGH 50 %; #----------------------------------------------------------- # EMAC0 Fabric Rx Elastic Buffer Timing Constraints: - #----------------------------------------------------------- NET "*GTP_DUAL_1000X_inst?RXRECCLK_0_BUFR" TNM_NET = "clk_rec_clk0"; TIMEGRP "v5_emac_v1_5_client_rec_clk0" = "clk_rec_clk0"; TIMESPEC "TS_v5_emac_v1_5_rec_clk0" = PERIOD "v5_emac_v1_5_client_rec_clk0" 7700 ps HIGH 50 %; # Control Gray Code delay and skew INST "*GTP_DUAL_1000X_inst?rx_elastic_buffer_inst_0?rd_addr_gray_?" TNM = "rx_elastic_rd_to_wr_0"; TIMESPEC "TS_rx_elastic_rd_to_wr_0" = FROM "rx_elastic_rd_to_wr_0" TO "clk_rec_clk0" 7500 ps DATAPATHONLY; INST "*GTP_DUAL_1000X_inst?rx_elastic_buffer_inst_0?wr_addr_gray_?" TNM = "elastic_metastable_0"; TIMESPEC "ts_elastic_meta_protect_0" = FROM "elastic_metastable_0" 5 ns DATAPATHONLY; # Reduce clock period to allow 3 ns for metastability settling time INST "*GTP_DUAL_1000X_inst?rx_elastic_buffer_inst_0?rd_wr_addr_gray*" TNM = "rx_graycode_0"; INST "*GTP_DUAL_1000X_inst?rx_elastic_buffer_inst_0?rd_occupancy*" TNM = "rx_binary_0"; TIMESPEC "ts_rx_buf_meta_protect_0" = FROM "rx_graycode_0" TO "rx_binary_0" 5 ns; ################################## # LocalLink Level constraints ################################## # EMAC0 LocalLink client FIFO constraints. INST "*client_side_FIFO_emac0?tx_fifo_i?rd_tran_frame_tog" TNM = "tx_fifo_rd_to_wr_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?rd_retran_frame_tog" TNM = "tx_fifo_rd_to_wr_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?rd_col_window_pipe_1" TNM = "tx_fifo_rd_to_wr_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?rd_addr_txfer*" TNM = "tx_fifo_rd_to_wr_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?rd_txfer_tog" TNM = "tx_fifo_rd_to_wr_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_frame_in_fifo" TNM = "tx_fifo_wr_to_rd_0"; TIMESPEC "TS_tx_fifo_rd_to_wr_0" = FROM "tx_fifo_rd_to_wr_0" TO "v5_emac_v1_5_gtp_clk_client0" 8000 ps DATAPATHONLY; TIMESPEC "TS_tx_fifo_wr_to_rd_0" = FROM "tx_fifo_wr_to_rd_0" TO "v5_emac_v1_5_gtp_clk_client0" 8000 ps DATAPATHONLY; # Reduce clock period to allow 3 ns for metastability settling time INST "*client_side_FIFO_emac0?tx_fifo_i?wr_tran_frame_tog" TNM = "tx_metastable_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_rd_addr*" TNM = "tx_metastable_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_txfer_tog" TNM = "tx_metastable_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?frame_in_fifo" TNM = "tx_metastable_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_retran_frame_tog*" TNM = "tx_metastable_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_col_window_pipe_0" TNM = "tx_metastable_0"; TIMESPEC "ts_tx_meta_protect_0" = FROM "tx_metastable_0" 5 ns DATAPATHONLY; INST "*client_side_FIFO_emac0?tx_fifo_i?rd_addr_txfer*" TNM = "tx_addr_rd_0"; INST "*client_side_FIFO_emac0?tx_fifo_i?wr_rd_addr*" TNM = "tx_addr_wr_0"; TIMESPEC "TS_tx_fifo_addr_0" = FROM "tx_addr_rd_0" TO "tx_addr_wr_0" 10ns; ## RX Client FIFO # Group the clock crossing signals into timing groups INST "*client_side_FIFO_emac0?rx_fifo_i?wr_store_frame_tog" TNM = "rx_fifo_wr_to_rd_0"; INST "*client_side_FIFO_emac0?rx_fifo_i?rd_addr_gray*" TNM = "rx_fifo_rd_to_wr_0"; TIMESPEC "TS_rx_fifo_wr_to_rd_0" = FROM "rx_fifo_wr_to_rd_0" TO "v5_emac_v1_5_gtp_clk_client0" 8000 ps DATAPATHONLY; TIMESPEC "TS_rx_fifo_rd_to_wr_0" = FROM "rx_fifo_rd_to_wr_0" TO "v5_emac_v1_5_gtp_clk_client0" 8000 ps DATAPATHONLY; # Reduce clock period to allow for metastability settling time INST "*client_side_FIFO_emac0?rx_fifo_i?wr_rd_addr_gray_sync*" TNM = "rx_metastable_0"; INST "*client_side_FIFO_emac0?rx_fifo_i?rd_store_frame_tog" TNM = "rx_metastable_0"; TIMESPEC "ts_rx_meta_protect_0" = FROM "rx_metastable_0" 5 ns; ################################## # EXAMPLE DESIGN Level constraints ################################## # Place the transceiver components. Please alter to your chosen transceiver. INST "*GTP_DUAL_1000X_inst?GTP_1000X?tile0_rocketio_wrapper_i?gtp_dual_i" LOC = "GTP_DUAL_X0Y3"; NET REFCLK_N_IN_pin LOC = P3; NET REFCLK_P_IN_pin LOC = P4; ################################## # Additions by FPGA Developer # http://www.fpgadeveloper.com ################################## # GTP Ready pin NET "GTP_READY_pin" LOC = AE24; # LED 7 # PHY Reset pin NET "PHY_RESET_0_pin" LOC = J14; # ML505 PHY Reset # PHY Autonegotiate ON INST *?v5_emac EMAC0_PHYINITAUTONEG_ENABLE = TRUE; |
- Save and close the file.
Modify the Software Application
In this example, our software application will not do anything other than send a message to Hyperterminal to let you know that it is running. All processing of Ethernet packets is done in hardware through the Ethernet MAC peripheral.
- From the “Applications” tab, open “Sources” within the “Project: TestApp_Peripheral” tree. Open the “TestApp_Peripheral.c” source file.
- Replace all the code in this file with the following source and save the file.
#include "xparameters.h"
#include "xbasic_types.h"
#include "xstatus.h"
int main (void)
{
// Display message
xil_printf("%c[2J",27);
xil_printf("Tri-mode Ethernet MAC Loop-back");
xil_printf(" by FPGA Developer\n\r");
xil_printf("http://www.fpgadeveloper.com\n\r");
// Stay in an infinite loop
while(1){
}
}
|
Download and Test the Project
- Open a Hyperterminal window with the required settings. For the correct settings, see Hyperterminal Settings.
- Turn on the ML505 board.
- From the XPS software, select “Device Configuration->Download Bitstream”.
The Hyperterminal output should display the message “Tri-mode Ethernet MAC Loop-back by FPGA Developer”. When you get this message, you can continue with the following steps.
- Open Wireshark on the PC to be used for testing. You can use any PC with a Gigabit Ethernet network card installed and working.
- From the menu select “Edit->Preferences”. In the dialog box that opens, select “User Interface->Columns” and set the columns as shown in the screenshot below. Then click “OK”.
- From the menu select “Capture->Options”. In the dialog box that opens, select the Gigabit Ethernet network card to which you will connect the ML505, then click “Start”.
- Connect the CAT5 Ethernet cable between the ML505 and the PC running Wireshark.
- You should notice that the Ethernet connection LEDs light up on both the ML505 and the PC. The connection LEDs on the PC should be on the Ethernet (RJ45) connector on the back of your PC. The connection LEDs on the ML505 are located next to the PCI edge connector and they are shown in the photo below.
In order from left to right, as shown in the photo, the LEDs indicate: CONNECTION, TX, RX, 10Mbps, 100Mbps, 1000Mbps. - We will produce Ethernet packets from the PC by using “ping”. From Windows, select “Start->Run” and type “cmd”. Press “Enter” and you should have a command prompt. From the command line, type “ping www.google.com”. Note that even before running “ping”, you may already see Ethernet packets in Wireshark. This can happen when your PC is trying to connect to a network.
- Observe the packets in Wireshark by clicking on them. In the screenshot below, we see that the PC sent packets 1, 3 and 5, while the ML505 sent back packets 2, 4 and 6 with the MAC destination and source addresses swapped. Notice also the short time delay of 225us between the sent packet and the received copy.
- Also observe that the RX and TX LEDs on the ML505 will light up at the same time, indicating that each packet received is immediately transmitted back to the sender (after swapping the MAC sender/destination addresses).
You can download the project files for this tutorial and try it on your ML50x board. Please select the file corresponding to your board, right-click on it and select “Save Link As”.
| Board | Virtex-5 Version | Project files |
| ML505 | XC5VLX50T | EthernetMAC-ML505-EDK10-1.zip |
| ML506 | XC5VSX50T | EthernetMAC-ML506-EDK10-1.zip |
| ML507 | XC5VFX70T | EthernetMAC-ML507-EDK10-1.zip |
| XUPV5 | XC5VLX110T | EthernetMAC-ML509-EDK10-1.zip |
You now have a working Ethernet connection running at 1Gbps. To develop the project further, remove the address swap module and try some of these ideas:
- TCP/IP stack: Connect the Ethernet MAC LocalLink interface to read/write FIFOs and run a TCP/IP stack on the Microblaze. A lightweight TCP/IP stack for the Microblaze is discussed in the application note XAPP1026.
- Ethernet-to-Aurora Bridge: Add an Aurora core to the design and create a transparent bridge.
- Gigabit PC interface: Don’t bother with TCP/IP and use the Ethernet MAC for a high-speed PC link.
- Video/audio processing: Use VLC Media Player to stream video into the Virtex-5, then process it and send it out of the DVI interface.
Remember that the interface to the Ethernet MAC is LocalLink, so you can virtually hook up anything with an 8-bit wide LocalLink interface.
Here is a maintained list of our step-by-step online tutorials and examples for the Xilinx Virtex-5 FPGA based on the ML505 Evaluation Platform from Xilinx. The following tutorials guide the user through various FPGA designs that combine the Microblaze with custom user logic peripherals.
Xilinx Platform Studio (XPS) Tutorials for ML505
The following tutorials develop working embedded projects that employ the Microblaze soft processor. They are developed using EDK version 10.1 of the Xilinx Platform Studio (XPS).
Version 13.1- Convert an ML505 EDK project for the XUPV5
For some reason, the Base System Builder in EDK doesn't support the XUPV5 board so when making an EDK project for the XUPV5 we have to select the ML505 board and modify the project settings later. If you have not yet created an EDK project, you should ...
- Creating a project using the Base System Builder
What am I learning here? In this post we'll look at using the Base System Builder in EDK version 13.1. Specifically you'll learn: How to create an EDK project with the Base System Builder How to add a software application to an EDK project H...
- Aurora to Ethernet Bridge
Tutorial Overview In the last tutorial we implemented the embedded Tri-mode Ethernet MAC and tested it by looping back Ethernet packets and monitoring them with Wireshark. In this tutorial, we will again implement the EMAC but this time we will link...
- Tri-mode Ethernet MAC
Tutorial Overview The Virtex-5 Embedded Tri-mode Ethernet MAC is useful for designs requiring Ethernet connectivity. Fortunately, Xilinx has made it easy for us to start developing with the Ethernet MACs by providing several online examples and appl...
- Other Tutorials and Examples
Here are links to some useful tutorials and examples hosted on other websites, including Xilinx: Xilinx EDK Concepts, Tools, and Techniques A Hands-on Guide to Effective Embedded System Design
- Microblaze 16x2 LCD Driver
Tutorial Overview In this example, we will develop a driver for the 16x2 character LCD on the ML505/6/7 board. The LCD driver will be mostly a Microblaze design, as opposed to being an IP design. The physical interface to the LCD will be made throug...
- Timer with Interrupts
Tutorial Overview In this tutorial we will add code to a peripheral template generated by the Peripheral Wizard to create a simple timer. The peripheral will generate an interrupt when the timer expires. The Microblaze will process the interrupt thr...
- Integrating a VHDL Design into a Peripheral
Tutorial Overview This tutorial is similar to the previous one titled: Integrating a Blackbox into a Peripheral however in this case, instead of integrating an .ngc file into a peripheral, we integrate one or more VHDL files. Sometimes we have a VHD...
- Integrating a Blackbox into a Peripheral
Tutorial Overview Sometimes we have an .ngc file from CORE Generator (or some other source) that we would like to bring into EDK as a peripheral. This project is a simple example of integrating a blackbox design into a peripheral generated by the Pe...
- Create a Peripheral using the Peripheral Wizard
Tutorial Overview In this tutorial we will create a simple project that uses our own IP peripheral (instead of using the XPS General Purpose IO peripheral provided by Xilinx) to read from the DIP switches and write to the LEDs. The software applicat...
- Manually Add a Peripheral to a Project
Tutorial Overview In the previous example, we created a project using the BSB and all of the work related to the hardware design was done by the BSB. In this example, we will create the same simple project, but this time we will add the GPIO for the...
- Create a Project Using the Base System Builder
Tutorial Overview In this example, we will develop a simple FPGA project using the Base System Builder that includes three peripherals: the RS232 UART and two GPIOs. One GPIO will be used for the DIP switches and the other for the LEDs. We will then...
Tutorials and Examples
The examples on this website are provided in a tutorial form. Each tutorial guides the user through the entire process of building a working project from “scratch”. The tutorials guide the user through all steps, with explanations, screen shots and source code. Each tutorial extends or builds on the concepts developed in the previous tutorials. It is recommended that beginners follow the tutorials in sequence.
Scope and Requirements
Most of these projects involve use of the Microblaze soft processor and interfacing it with peripherals developed in VHDL. It is assumed that the reader has a basic understanding of the C programming language and VHDL. All debugging is done through one of the RS232 ports of the ML505 Evaluation Platform. It is therefore necessary that the user have a PC with an RS232 port (comport/serial port) or RS232-to-USB converter, and a copy of Hyperterminal or other terminal program. For the required Hyperterminal settings, click here.
Below are several frequently asked questions about the ML505/6/7 and XUPV5 boards. Click on the question to jump to the answer. If you have a question about the ML505/6/7 or XUPV5 boards, please contact us at the email address given at the end of this page.
- What is the speed grade of Virtex-5 on my ML505/ML506/ML507/XUPV5 board?
- What are the differences between the ML505/6/7 and XUPV5 boards?
- What is the XUPV5 (ML509) board?
- Why cant I find the XUPV5 (or ML509) board in the Base System Builder (BSB)?
- I have a design for an ML50x board (eg. ML505) that I want to migrate to a different ML50x board (eg. ML509). What do I have to change?
- The Virtex-5 on my ML50x board gets very hot when in use. What should I do about it?
- How can I buy an ML50x board and how much does it cost?
What is the speed grade of Virtex-5 on my ML505/ML506/ML507/XUPV5 board?
All the ML505/6/7 and XUPV5 boards use a Virtex-5 of speed grade -1.
The ML505 has been made in four variations that use the same printed-circuit-board (PCB) but a different version Virtex-5. The table below lists the different boards and the Virtex-5 it is loaded with:
| Board | Virtex-5 Version | Package | Speed Grade |
| ML505 | XC5VLX50T | FFG1136 | -1C |
| ML506 | XC5VSX50T | FFG1136 | -1C |
| ML507 | XC5VFX70T | FFG1136 | -1C |
| XUPV5 | XC5VLX110T | FFG1136 | -1C |
For more information, please refer to the ML505/ML506/ML507 Evaluation Platform User Guide.
The XUPV5 board is a version of the ML505 offered by the Xilinx University Program (XUP). It uses the same printed-circuit-board (PCB) as the ML505 but a Virtex-5 XC5VLX110T rather than the XC5VLX50T. It is also known as the ML509 board because it is labeled so. The board is popular because it can be purchased from Digilent for only US$750.
Why cant I find the XUPV5 (or ML509) board in the Base System Builder (BSB)?
The XUPV5 was only recently released. It should eventually be added to future versions of the EDK. Until then, you can instead select the ML505 board in the BSB and then use “Project->Project Options” to change the Virtex-5 version to the correct one for the XUPV5 board. You may also have to change your constraints file (.ucf) if you use it to specify the FPGA or if you are instantiating RocketIO GTPs. See next question.
Firstly use “Project->Project Options” to change the Virtex-5 version to the correct one for the board you are migrating to. You may also have to change your constraints file (.ucf) if you use it to specify the FPGA or if you are instantiating RocketIO GTPs. The GTP placement names for one version of Virtex-5 do not necessarily refer to the same GTPs on another Virtex-5. For this reason, you might have to change your .ucf file to specify the correct GTPs that you want to use. Use the table below to ensure that you are using the correct placement names for the board that you are using.
| ML505 | ML506 | ML507 | XUPV5 | |
| XC5VLX50T | XC5VSX50T | XC5VFX70T | XC5VLX110T | |
| SFP/SMA (BANK116) | GTP_DUAL X0Y4 | GTP_DUAL X0Y4 | GTX_DUAL X0Y5 | GTP_DUAL X0Y5 |
| SGMII (BANK112) | GTP_DUAL X0Y3 | GTP_DUAL X0Y3 | GTX_DUAL X0Y4 | GTP_DUAL X0Y4 |
| SATA (BANK114) | GTP_DUAL X0Y2 | GTP_DUAL X0Y2 | GTX_DUAL X0Y3 | GTP_DUAL X0Y3 |
| PCIe (BANK118) | GTP_DUAL X0Y1 | GTP_DUAL X0Y1 | GTX_DUAL X0Y2 | GTP_DUAL X0Y2 |
The banks and their corresponding placement names can be found in the RocketIO User Guides. Refer to “Package Placement Information” in Chapter 4 of the appropriate RocketIO User Guide for your board:
- For ML505/ML506/XUPV5: RocketIO GTP User Guide (UG196)
- For ML507: RocketIO GTX User Guide (UG198)
The Virtex-5 on my ML50x board gets very hot when in use. What should I do about it?
The Virtex-5 FPGA is a very powerful device that will naturally generate heat when in operation. Several Xilinx application notes suggest using a heatsink/fan with the ML505 board to reduce the overheating problem.
- ML505/506 SGMII Design Creation
- ML505/506/507 MIG Design Creation
- ML505 Standard IP with System Monitor
A suitable heatsink/fan can be purchased from Radian Heatsinks. A full list of compatible heatsinks can be found at the link below:
http://www.radianheatsinks.com/docs/virtex-chart.pdf
Other suitable and cost effective heatsinks can be purchased from Digilent. See the list of them in the “Related Products” section of the XUPV5 page.
- The ML505/ML506/ML507 can be purchased from Xilinx for the price of US$1,195.
- As an option for universities, the Xilinx University Program offers a version of the board known as the XUPV5 (or ML509). It can be purchased from Digilent for US$750.
Hardware Details
The ML505 Evaluation Platform from Xilinx is a development board for the Virtex-5 FPGA. It contains many useful hardware features including:
- Xilinx Virtex-5 XC5VLX50T FPGA
- 10/100/1000 tri-speed Ethernet PHY
- USB host and peripheral controllers
- Programmable system clock generator
- Stereo AC97 codec with line in, line out, headphone, microphone, and SPDIF digital audio jacks
- PS/2 (2) – Keyboard, Mouse
- RS-232 port
- 16×2 character LCD
- Video Input
- Video (DVI/VGA) Output
- DIP Switch (8), LEDs (8), and Pushbuttons (5)
- PCI Express® Edge Connector (x1 Endpoint)
- SFP (1000Base-X)
Variations
The ML505 has been made in four variations that use the same printed-circuit-board (PCB) but a different version Virtex-5. The table below lists the different boards and the Virtex-5 it is loaded with:
| Board | Virtex-5 Version | Package | Speed Grade |
| ML505 | XC5VLX50T | FFG1136 | -1C |
| ML506 | XC5VSX50T | FFG1136 | -1C |
| ML507 | XC5VFX70T | FFG1136 | -1C |
| XUPV5 | XC5VLX110T | FFG1136 | -1C |
For more information, please refer to the ML505/ML506/ML507 Evaluation Platform User Guide.
How to buy it
- The ML505/ML506/ML507 can be purchased from Xilinx for the price of US$1,195.
- The best deal for universities, offered by the Xilinx University Program, is a version of the board known as the XUPV5 (or ML509). It can be purchased from Digilent at only US$750. Click the Digilent link for more information.
Here are links to some useful tutorials and examples hosted on other websites, including Xilinx:
Xilinx
EDK Concepts, Tools, and Techniques
A Hands-on Guide to Effective Embedded System Design



Recent Comments