Here is a maintained list of our step-by-step online tutorials and examples for the Xilinx Virtex-II Pro FPGA based on the XUPV2P Development Board from Digilent. The following tutorials guide the user through various FPGA designs that combine the PowerPC with custom user logic peripherals.
Xilinx Platform Studio (XPS) Tutorials for XUPV2P
The following tutorials develop working embedded projects that employ the Microblaze soft processor. They are developed using EDK.
Version 13.1- Timer with Interrupts
Overview In this tutorial we will improve on the Timer peripheral developed in Create a Simple Timer Peripheral. The improvement is achieved by enabling the peripheral to generate an interrupt when the timer expires. The PowerPC then processes the i...
- Aurora Transceiver for the PLB
Overview In this tutorial we will create a peripheral containing the Aurora core to implement a high speed serial transceiver with a RocketIO MGT. It will be an improved version of the Aurora transceiver developed in the tutorial titled Create an Auro...
- Known Issues
Below we describe various problems with the XUPV2P board and/or XPS software, and the solution or work-around. No Vista Support for 9.1 or Older Presently, the EDK and ISE platforms versions 9.1 and older do not support Vista. You must upgrade to v...
- Create an Aurora Transceiver
Overview In this tutorial we will create a peripheral containing the Aurora core to implement a high speed serial transceiver with a RocketIO MGT. The peripheral can be used to connect two XUPV2P boards using the SATA connectors and transfer data be...
- 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 Xilinx Creating an OPB IPIF-based IP and Using it ...
- Integrating a VHDL Design into a Peripheral
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 VHDL design ...
- Integrating a Blackbox into a Peripheral
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 Peripheral ...
- Create a Simple Timer Peripheral
Overview In this project, we will add code to a peripheral template generated by the Peripheral Wizard to create a simple timer. The timer peripheral will be used by the PowerPC to make the LEDs flash with a fixed period. Figure: The Timer pe...
- XUPV2P Library Files
To develop projects in XPS for the XUPV2P board it is necessary to copy the XUPV2P library files into a directory on the C drive of your computer. These files contain software libraries and hardware specific information for the XUPV2P board that are ne...
- Create a Peripheral using the Peripheral Wizard
Overview In this tutorial we will create a simple project that uses our own IP core (instead of using the General Purpose IO core provided by Xilinx) to read from the DIP switches and write to the LEDs. The software application will display the DIP ...
- Manually Add a Peripheral to a Project
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 LEDs man...
- Create a Project Using the Base System Builder
Tutorial Overview In this example, we will create a simple 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 use a...
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
The projects on this website all involve use of the PowerPC microprocessors and interfacing them 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 the RS232 port of the XUPV2P Development Board. 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.
Overview
In this tutorial we will use a RocketIO MGT for possibly its simplest application, a programmable oscillator. This can be achieved by feeding the MGT with a repetitive data pattern (e.g. “10101010101010101010″). By changing the data pattern we can adjust the output frequency and duty cycle.
Figure: The Oscillator peripheral
–>
The diagram above illustrates the oscillator peripheral. In it we use 4 registers to store a 4 x 32 bit repeating pattern to be fed to the RocketIO primitive (GT_CUSTOM). Note that we could have used any number of registers to store the pattern. In our user_logic.vhd file we instantiate the GT_CUSTOM and create a counter which we use for loading the GT_CUSTOM. The counter counts from 1 to 4 and each time it loads the corresponding register contents into the GT_CUSTOM for transmission.
We will also create a Digital Clock Manager (DCM) peripheral to generate the reference clocks for the RocketIO MGT. The DCM peripheral will only contain two clock buffers and will not require registers or FIFOs.
In our design, the GT_CUSTOM is configured for a width of 2 bytes and the 8b10b encoder/decoder is bypassed, so our data width is 10 x 2 = 20 bits. The registers in our peripheral are 32 bits wide, chosen to be the same width as the OPB data bus. Because of this mismatch, we don’t use all the bits in the registers. Instead, we only use the 20 least significant bits of each register.
This tutorial contains screenshots to guide you through the entire implementation process. You can click on the images to view a higher resolution when necessary.
Requirements
Apart from the obvious requirements (XPS software and XUPV2P board) this project requires the following:
- SMA Connectors: To be able to verify the oscillator output, you will need to install SMA connectors at J19 and J20 of your XUPV2P board.
- Two coaxial cables: To connect the oscillator output to an oscilloscope, two SMA coaxial cables are required.
Create the Basic Project
Follow these steps to create the basic project:
- Open XPS and from the dialog box, select “Base System Builder wizard” and OK.
- Create a new folder for the project and select it using “Browse”. In “Advanced Options” tick “Use repository paths” and select the “C:\XUPV2P\lib” folder using “Browse”. Click “OK”.
- Tick “I would like to create a new design” and click “Next”.
- Select “Xilinx” as the board vendor. Select “XUP Virtex II Pro Development System” as the board name. Select “C” as the board revision. Click “Next”.
- Tick “PowerPC” and click “Next”.
- Select all clock frequencies to be 100MHz. Select “No debug”. Click “Next”.
- In selecting the Additional IO Interfaces, tick “onewire_0″ and “RS232_Uart_1″. Untick everything else. We will not actually use the “onewire_0″ interface in this project, but leaving it in has shown to be important. For an explanation, refer to “The Onewire Problem” on the Known Issues page.
- When Adding Internal Peripherals, select 64KB for the “plb_bram_if_cntlr_1″ and click “Next”.
- Select “RS232_Uart_1″ for both STDIN and STDOUT. Un-tick “Memory Test” and leave “Peripheral Test” ticked. Click “Next”.
- On the “Configure Peripheral Test Application” page, select “plb_bram_if_cntlr_1″ for the Instruction, Data, Stack and Heap memories. Click “Next”.
- Click “Generate”.
- Click “Finish”.
- Tick “Start using Platform Studio” and click “OK”.
Create the DCM Peripheral
Follow these steps to create the DCM peripheral:
- Select from the menu “Hardware->Create or Import Peripheral”. Click “Next”.
- Select “Create templates for a new peripheral” and click “Next”.
- Select “To an XPS project” and click “Next”.
- Type “mgt_dcm” for the peripheral name. Click “Next”.
- Select “On-chip Peripheral Bus” (OPB) and click “Next”.
- The DCM peripheral is very simple and doesn’t need interrupts, registers or FIFOs. Un-tick everything and click “Next”.
- On the “IP Interconnect” page, leave everything as is. Click “Next”.
- On the “Peripheral Simulation Support” page, 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.
Modify the DCM Peripheral
Now we will add code in our peripheral template to instantiate two clock buffers that will generate the clock sources REF_CLK and USER_CLK for the RocketIO MGTs. This DCM example originates from the Xilinx RocketIO Transceiver User Guide (ug024), see section “Digital Clock Manager (DCM) Examples”.
- Select from the menu “File->Open” and from the project folder, browse to “pcores\mgt_dcm_v1_00_a\hdl\vhdl”.
- Open the file “mgt_dcm.vhd”.
- Find the line of code that says “– ADD USER PORTS BELOW THIS LINE” and add the following lines of code just below.
TOP_BREF_CLK_P : in std_logic; TOP_BREF_CLK_N : in std_logic; TOP_BREF_CLK : out std_logic; USER_CLK : 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.
TOP_BREF_CLK_P => TOP_BREF_CLK_P, TOP_BREF_CLK_N => TOP_BREF_CLK_N, TOP_BREF_CLK => TOP_BREF_CLK, USER_CLK => USER_CLK, |
- Save and close the file.
- Select from the menu “File->Open” and from the project folder, browse to “pcores\mgt_dcm_v1_00_a\hdl\vhdl”.
- Open the file “user_logic.vhd”.
- Find the line of code that says “– ADD USER PORTS BELOW THIS LINE” and add the following lines of code just below.
TOP_BREF_CLK_P : in std_logic; TOP_BREF_CLK_N : in std_logic; TOP_BREF_CLK : out std_logic; USER_CLK : 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 IBUFGDS_LVDS_25
port(
O : out std_ulogic;
I : in std_ulogic;
IB : in std_ulogic
);
end component;
component BUFG
port(
O : out std_ulogic;
I : in std_ulogic
);
end component;
signal top_bref_clk_i : std_logic;
signal user_clk_i : std_logic;
|
- Find the line of code that says “–USER logic implementation added here” and add the following lines of code just below.
-- Differential Clock Buffer for top BREF_CLK
diff_clk_buff_top_i : IBUFGDS_LVDS_25
port map(
I => TOP_BREF_CLK_P,
IB => TOP_BREF_CLK_N,
O => top_bref_clk_i
);
-- BUFG used to drive USER_CLK on global clock net
user_clock_bufg_i : BUFG
port map(
I => top_bref_clk_i,
O => user_clk_i
);
TOP_BREF_CLK <= top_bref_clk_i;
USER_CLK <= user_clk_i;
|
- Save and close the file.
Import the DCM Peripheral
Now we will use the Peripheral Wizard to import the DCM peripheral.
- 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 “mgt_dcm”. 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\mgt_dcm_v1_00_a\data” and select the “mgt_dcm_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 “OPB Slave” and click “Next”.
- On the SOPB: Port page, click “Next”.
- On the SOPB: Parameter page, click “Next”.
- On the “Identify Interrupt Signals” page, un-tick “Select and configure interrupt(s)” and click “Next”.
- On the “Parameter Attributes” page, click “Next”.
- On the “Port Attributes” page, click “Next”.
- Click “Finish”.
The DCM peripheral should now be accessible through the “IP Catalog->Project Repository” in the XPS interface.
Create an Instance of the DCM Peripheral
Follow these steps to create an instance of the peripheral in the project.
- From the “IP Catalog” find the “mgt_dcm” IP core in the “Project Repository” group. Right click on the core and select “Add IP”.
- From the “System Assembly View” using the “Bus Interface” filter, connect the “mgt_dcm_0″ to the OPB bus.
- Click on the “Ports” filter. Click on the “+” for “mgt_dcm_0″ to view its ports.
- Click on the “Net” field for the “TOP_BREF_CLK_P” port. Type “TOP_BREF_CLK_P” 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 “TOP_BREF_CLK_N” port. Type “TOP_BREF_CLK_N” 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 “TOP_BREF_CLK” port. Type “TOP_BREF_CLK” in this field and press “Enter”.
- Click on the “Net” field for the “USER_CLK” port. Type “USER_CLK” in this field and press “Enter”. The result should look like the image below.
- Now if you click the “+” for “External Ports”, you should be able to find the two ports “TOP_BREF_CLK_P_pin” and “TOP_BREF_CLK_N_pin”, with nets called “TOP_BREF_CLK_P” and “TOP_BREF_CLK_N” respectively.
- Click on the “Addresses” filter. Change the “Size” for “mgt_dcm_0″ to 64K. Then click “Generate Addresses”.
Now we have an instance of the DCM peripheral in the project. The single DCM peripheral will supply the reference clock to all the MGTs accessible on the XUPV2P board.
Create the Oscillator Peripheral
Follow these steps to create the Oscillator peripheral.
- Select from the menu “Hardware->Create or Import Peripheral”. Click “Next”.
- Select “Create templates for a new peripheral” and click “Next”.
- Select “To an XPS project” and click “Next”.
- Type “oscillator” for the peripheral name. Click “Next”.
- Select “On-chip Peripheral Bus” (OPB) and click “Next”.
- Tick “User logic S/W register support”, un-tick everything else and click “Next”.
- Choose “4″ for the number of software accessible registers. Choose 32-bits for the size of the registers.
- On the “IP Interconnect” page leave everything as is. Click “Next”.
- On the “Peripheral Simulation Support” page, click “Next” without ticking the option to generate.
- After the “Peripheral Implementation Support” page, tick “Generate ISE and XST project files” and “Generate template driver files”. Click “Next”.
- Click “Finish”. Now our templates are created.
Modify the Oscillator Peripheral
Now we will add code in our peripheral template to instantiate a RocketIO primitive called GT_CUSTOM and set it up as an oscillator.
- Select from the menu “File->Open” and from the project folder, browse to “pcores\oscillator_v1_00_a\hdl\vhdl”.
- Open the file “oscillator.vhd”.
- Find the line of code that says “– ADD USER PORTS BELOW THIS LINE” and add the following lines of code just below.
TOP_BREF_CLK : in std_logic; USER_CLK : in std_logic; RXP : in std_logic; RXN : in std_logic; TXP : out std_logic; TXN : 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.
TOP_BREF_CLK => TOP_BREF_CLK, USER_CLK => USER_CLK, RXP => RXP, RXN => RXN, TXP => TXP, TXN => TXN, |
- Save and close the file.
- Select from the menu “File->Open” and browse from the project folder to “pcores\oscillator_v1_00_a\hdl\vhdl”.
- Open the file “user_logic.vhd”. We will need to modify this source code to instantiate the GT_CUSTOM and connect it as an oscillator.
- Find the line of code that says “– ADD USER PORTS BELOW THIS LINE” and add the following lines of code just below.
TOP_BREF_CLK : in std_logic; USER_CLK : in std_logic; RXP : in std_logic; RXN : in std_logic; TXP : out std_logic; TXN : out std_logic; |
- Find the line of code that says “–USER signal declarations added here” and add the following lines of code just below.
signal mgt_txdata : std_logic_vector(19 downto 0);
signal count : std_logic_vector(3 downto 0);
component GT_CUSTOM
generic(
REF_CLK_V_SEL : integer);
port(
CHBONDDONE : out std_logic;
CHBONDO : out std_logic_vector(3 downto 0);
CONFIGOUT : out std_logic;
RXBUFSTATUS : out std_logic_vector(1 downto 0);
RXCHARISCOMMA : out std_logic_vector(3 downto 0);
RXCHARISK : out std_logic_vector(3 downto 0);
RXCHECKINGCRC : out std_logic;
RXCLKCORCNT : out std_logic_vector(2 downto 0);
RXCOMMADET : out std_logic;
RXCRCERR : out std_logic;
RXDATA : out std_logic_vector(31 downto 0);
RXDISPERR : out std_logic_vector(3 downto 0);
RXLOSSOFSYNC : out std_logic_vector(1 downto 0);
RXNOTINTABLE : out std_logic_vector(3 downto 0);
RXREALIGN : out std_logic;
RXRECCLK : out std_logic;
RXRUNDISP : out std_logic_vector(3 downto 0);
TXBUFERR : out std_logic;
TXKERR : out std_logic_vector(3 downto 0);
TXN : out std_logic;
TXP : out std_logic;
TXRUNDISP : out std_logic_vector(3 downto 0);
BREFCLK : in std_logic;
BREFCLK2 : in std_logic;
CHBONDI : in std_logic_vector(3 downto 0);
CONFIGENABLE : in std_logic;
CONFIGIN : in std_logic;
ENCHANSYNC : in std_logic;
ENMCOMMAALIGN : in std_logic;
ENPCOMMAALIGN : in std_logic;
LOOPBACK : in std_logic_vector(1 downto 0);
POWERDOWN : in std_logic;
REFCLK : in std_logic;
REFCLK2 : in std_logic;
REFCLKSEL : in std_logic;
RXN : in std_logic;
RXP : in std_logic;
RXPOLARITY : in std_logic;
RXRESET : in std_logic;
RXUSRCLK : in std_logic;
RXUSRCLK2 : in std_logic;
TXBYPASS8B10B : in std_logic_vector(3 downto 0);
TXCHARDISPMODE : in std_logic_vector(3 downto 0);
TXCHARDISPVAL : in std_logic_vector(3 downto 0);
TXCHARISK : in std_logic_vector(3 downto 0);
TXDATA : in std_logic_vector(31 downto 0);
TXFORCECRCERR : in std_logic;
TXINHIBIT : in std_logic;
TXPOLARITY : in std_logic;
TXRESET : in std_logic;
TXUSRCLK : in std_logic;
TXUSRCLK2 : in 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.
rock0 : GT_CUSTOM
generic map(
REF_CLK_V_SEL => 1)
port map(
CHBONDDONE => open,
CHBONDI => "0000",
CHBONDO => open,
CONFIGENABLE => '0',
CONFIGIN => '0',
CONFIGOUT => open,
ENCHANSYNC => '0',
ENMCOMMAALIGN => '0',
ENPCOMMAALIGN => '0',
LOOPBACK => "00",
POWERDOWN => '0',
BREFCLK => TOP_BREF_CLK,
BREFCLK2 => '0',
REFCLK => '0',
REFCLK2 => '0',
REFCLKSEL => '0',
RXBUFSTATUS => open,
RXCHARISCOMMA => open,
RXCHARISK => open,
RXCHECKINGCRC => open,
RXCLKCORCNT => open,
RXCOMMADET => open,
RXCRCERR => open,
RXDATA => open,
RXDISPERR => open,
RXLOSSOFSYNC => open,
RXN => RXN,
RXNOTINTABLE => open,
RXP => RXP,
RXPOLARITY => '0',
RXREALIGN => open,
RXRECCLK => open,
RXRESET => '0',
RXRUNDISP => open,
RXUSRCLK => '0',
RXUSRCLK2 => '0',
TXBUFERR => open,
TXBYPASS8B10B => "1111",
TXCHARDISPMODE(3 downto 2) => "00",
TXCHARDISPMODE(1) => mgt_txdata(19),
TXCHARDISPMODE(0) => mgt_txdata(9),
TXCHARDISPVAL(3 downto 2) => "00",
TXCHARDISPVAL(1) => mgt_txdata(18),
TXCHARDISPVAL(0) => mgt_txdata(8),
TXCHARISK(3 downto 2) => "00",
TXCHARISK(1 downto 0) => "00",
TXDATA(31 downto 16) => "0000000000000000",
TXDATA(15 downto 8) => mgt_txdata(17 downto 10),
TXDATA(7 downto 0) => mgt_txdata(7 downto 0),
TXFORCECRCERR => '0',
TXINHIBIT => '0',
TXKERR => open,
TXN => TXN,
TXP => TXP,
TXPOLARITY => '0',
TXRESET => Bus2IP_Reset,
TXRUNDISP => open,
TXUSRCLK => USER_CLK,
TXUSRCLK2 => USER_CLK);
-- This process manages a counter and feeds the MGT
-- with data from the slave registers
process (USER_CLK, Bus2IP_Reset)
begin
if Bus2IP_Reset = '1' then
mgt_txdata <= (others => '0');
count <= (others => '0');
elsif USER_CLK'event and USER_CLK = '1' then
if count = "0011" then
count <= (others => '0');
else
count <= count + 1; end if; case count is when "0000" => mgt_txdata <= slv_reg0(12 to 31); when "0001" => mgt_txdata <= slv_reg1(12 to 31); when "0010" => mgt_txdata <= slv_reg2(12 to 31); when others => mgt_txdata <= slv_reg3(12 to 31);
end case;
end if;
end process;
|
- Save and close the file.
Import the Oscillator Peripheral
Now we will use the Peripheral Wizard in Import mode.
- 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 “oscillator”. 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\oscillator_v1_00_a\data” and select the “oscillator_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 “OPB Slave” and click “Next”.
- On the SOPB: Port page, click “Next”.
- On the SOPB: Parameter page, click “Next”.
- On the “Identify Interrupt Signals” page, un-tick “Select and configure interrupt(s)” and click “Next”.
- On the “Parameter Attributes” page, click “Next”.
- On the “Port Attributes” page, click “Next”.
- Click “Finish”.
The oscillator peripheral should now be accessible through the “IP Catalog->Project Repository” in the XPS interface.
Create an Instance of the Oscillator Peripheral
Follow these steps to create an instance of the peripheral in the project.
- From the “IP Catalog” find the “oscillator” IP core in the “Project Repository” group. Right click on the core and select “Add IP”.
- From the “System Assembly View” using the “Bus Interface” filter, connect the “oscillator_0″ to the OPB bus.
- Click on the “Ports” filter. Click on the “+” for “oscillator_0″ to view its ports.
- Click on the “Net” field for the “TOP_BREF_CLK” port. Type “TOP_BREF_CLK” in this field and press “Enter”.
- Click on the “Net” field for the “USER_CLK” port. Type “USER_CLK” in this field and press “Enter”. The ports should look as shown in the screen shot below.
- Click on the “Addresses” filter. Change the “Size” for “oscillator_0″ to 64K. Then click “Generate Addresses”.
We have now made an instantiation of the oscillator peripheral in our design.
Modify the UCF Constraints File
Now we must add some lines to the project’s .ucf file to tell XPS: (1) which physical RocketIO MGT to use, (2) where the external reference clock pins are, and (3) the frequency or period of the reference clock.
- Click on the “Project” tab and double-click on “UCF File: data/system.ucf” from within the “Project Files” tree. The .ucf file should open.
- Insert the following code at the end of the .ucf file.
#Clock constraints NET USER_CLK PERIOD = 75 MHz; NET TOP_BREF_CLK PERIOD = 75 MHz; #Reference clock pin locations NET TOP_BREF_CLK_P_pin LOC = F16; NET TOP_BREF_CLK_N_pin LOC = G16; NET TOP_BREF_CLK_P_pin IOSTANDARD = LVDS_25; NET TOP_BREF_CLK_N_pin IOSTANDARD = LVDS_25; # SATA0 HOST - GT_X0Y1 # SATA1 TARGET - GT_X1Y1 # SATA2 HOST - GT_X2Y1 # SMA connectors - GT_X3Y1 # Place oscillator at SMA (REFCLK) INST oscillator_0/oscillator_0/USER_LOGIC_I/rock0 LOC=GT_X3Y1; |
- Save and close the file.
Modify the Software Application
Now all we need to do is modify the software application to test our oscillator 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 "oscillator.h"
// Pointer to the peripheral
Xuint32 *oscillator_0_baseaddr_p =
(Xuint32 *) XPAR_OSCILLATOR_0_BASEADDR;
// Base address of the peripheral
Xuint32 oscillator_0_baseaddr;
int main (void)
{
// Check that the oscillator exists
XASSERT_NONVOID(oscillator_0_baseaddr_p != XNULL);
oscillator_0_baseaddr = (Xuint32) oscillator_0_baseaddr_p;
// Write the data pattern to the slave registers
OSCILLATOR_mWriteSlaveReg0(oscillator_0_baseaddr,0xAAAAA);
OSCILLATOR_mWriteSlaveReg1(oscillator_0_baseaddr,0xAAAAA);
OSCILLATOR_mWriteSlaveReg2(oscillator_0_baseaddr,0xAAAAA);
OSCILLATOR_mWriteSlaveReg3(oscillator_0_baseaddr,0xAAAAA);
xil_printf("\n\rOscillator running\n\r");
while(1){}
return(0);
}
|
- From the menu select “Device Configuration->Download Bitstream”.
The data rate of our MGT in this example is 1.5Gbps because we are using a reference clock of 75MHz which gets multiplied by 20. The code in this example loads the slave registers with a “10101010101010101010″ (0xAAAAA) data pattern. This will produce an oscillator output of 750MHz with a 50% duty cycle. If we changed the pattern to “11001100110011001100″ (0xCCCCC) then we would have an oscillator output of 375MHz with a 50% duty cycle.
Before the FPGA is programmed, make sure you have a Hyperterminal window opened so that you don’t miss the debug output. When the project runs, it sends the message “Oscillator running” to Hyperterminal so that you know that the slave registers have been loaded. You can then check the oscillator output at J19 and J20 on the XUPV2P board by connecting them to an oscilloscope by coaxial cables.
Please note that although this connection will not do any harm to your board, it does not provide the correct termination required by the CML outputs of the RocketIO MGTs. CML outputs require a 50 ohm termination to VCC whereas a typical oscilloscope provides a termination of 50 ohms to ground. This would not matter if the SMA connectors were AC-coupled to the MGT pins, but on the XUPV2P board they are in fact DC-coupled.
The project folder for this tutorial can be downloaded in a compressed ZIP file MGTOscillator.zip
. Right-click on the link and select “Save Link As”.
In the next tutorial, Create an Aurora Transceiver, we show how to use the RocketIO MGTs to create a high speed serial communications link between two FPGAs.
RocketIO Tutorials
Here is a list of our tutorials related to RocketIO multi-gigabit transceivers:
- Aurora to Ethernet Bridge
- Tri-mode Ethernet MAC
- Aurora Transceiver for the PLB
- Create an Aurora Transceiver
- Create an Oscillator with a RocketIO MGT
- RocketIO FAQ
RocketIO Frequently Asked Questions
Here is a list of common questions about RocketIO:
What is the best way to get started developing with the RocketIOs?
The RocketIOs are very sophisticated devices and require a lot of time to understand and integrate into your designs. Fortunately, Xilinx provides many tools and examples to help you get developing faster. Here are our suggestions:
- Download the Aurora IP core from the Xilinx website. When you generate the Aurora IP core using CORE Generator, a working example with documentation is also generated.
- If you want to implement your own protocol, generate the GTP wrapper using CORE Generator. The GTP wrapper provides a working example and documentation.
You might also find our tutorials helpful.
Are the RocketIO MGTs on the Virtex-II Pro compatible with the SATA standard? Can the SATA protocol be implemented on the RocketIOs?
According to Xilinx technical support, the answer is NO. The RocketIO MGTs do not fully comply with the SATA standard. This however has not stopped people from trying it anyway. Here are some references:
When I make changes to a peripheral, what is the most efficient way to re-build the project? How can I avoid having to re-build the entire project?
Sometimes we are developing a peripheral and we have to re-build and test it several times over. In this situation, we don’t have to “Clean Hardware” and re-build the entire project from scratch every time. Instead, we can make use of an option in the .mpd file of the peripheral in development.
- First make sure your modified .vhd files are all saved.
- Select “File->Open” and browse to the “data” folder of your modified peripheral. Select the .mpd file and click “Open”.
- In the .mpd file there will be a line saying “OPTION CORE_STATE = ACTIVE”. Change the “ACTIVE” to “DEVELOPMENT” and save the file.
- Now select “Project->Rescan User Repositories”.
Now every time that you select “Device Configuration->Download Bitstream”, XPS will check if you have made changes to the peripheral and re-build it into the project if necessary.
There is an exception to the above case and that is if you have modified the ports of your peripheral. In this case, you must use the Peripheral Wizard to Import your peripheral, change the .mpd file and then run “Project->Rescan User Repositories” again. Remember, every time that you run the Peripheral Wizard, it will re-write your .mpd file, so each time you will have to change the “ACTIVE” back to “DEVELOPMENT”. For a more detailed description of the Import process, see the tutorial Create a Peripheral Using the Peripheral Wizard.
How can I copy a peripheral from one project into another?
If you developed a peripheral in one project and you want to use it in another, you just have to copy all the peripheral files and use “Project->Rescan User Repositories”.
- In Windows Explorer, browse to the “pcores” folder of the project where you have a peripheral you want to copy.
- Select and copy the folder of the peripheral you want to copy.
- Paste this folder into the “pcores” folder of the project in which you want to use the peripheral.
- Now do the same thing for the “drivers” folder. Note that not all peripherals have drivers, so this folder may not exist for the peripheral you want to copy.
- Open the project in XPS and select “Project->Rescan User Repositories”.
Now the peripheral should appear in the “IP Catalog” of the project.
Here are links to some useful reference documents:
Xilinx
Xilinx University Program Virtex-II Pro Development System
Hardware Reference Manual
Xilinx
XUPV2P Schematics
Complete Schematics for the XUPV2P Development Board
Xilinx
Embedded System Tools Reference Manual
Embedded Development Kit EDK 8.1i
Xilinx
Xilinx Synthesis Technology (XST) User Guide
Describes XST Support for HDL
Xilinx
Xilinx RocketIO Transceiver User Guide
User Guide for the RocketIO Multi-gigabit Transceiver
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
Xilinx
Creating an OPB IPIF-based IP and Using it in EDK
Adding Custom Logic to an Embedded Design
Xilinx
Using the RocketIO Controller in Virtex-II Pro for Frequency Multiplication
An example design similar to the Oscillator example on this website
Digilent
Using the Base System Builder
A Quick Start Guide to the BSB
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 VHDL design that we developed in ISE, or some other program, and we would like to bring it into the EDK as a peripheral. In this tutorial, we will create the same multiplier peripheral as was created in the previous tutorial.
The multiplier will take in two 16 bit unsigned inputs and have a 32 bit unsigned output. A single 32 bit write to the peripheral will contain the two 16 bit inputs, separated by the lower and higher 16 bits. A single 32 bit read from the peripheral will contain the result from the multiplication of the two 16 bit inputs. Instead of registers, we will use a read and write FIFO for the interface with the software application. In this way, the peripheral write FIFO can be loaded with a number of multiplications to perform, and the results can be pushed into the read FIFO for the software application to retrieve at its convenience. Practically, this design does not serve much purpose, but it is a simple demonstration of integrating VHDL designs into peripherals.
For a more powerful example of integrating a VHDL design into a peripheral, see Creating an Aurora Transceiver, in which we create a peripheral from the Aurora core source files generated by CORE Generator.
This tutorial contains screenshots to guide you through the entire implementation process. You can click on the images to view a higher resolution when necessary.
Are you using EDK 10.1?
Try the updated version of this tutorial based on the Virtex-5 FPGA on the ML505 board: Integrating a VHDL Design into a Peripheral
Create the Basic Project
Follow these steps to create the basic project:
- Open XPS and from the dialog box, select “Base System Builder wizard” and OK.
- Create a new folder for the project and select it using “Browse”. In “Advanced Options” tick “Use repository paths” and select the “C:\XUPV2P\lib” folder using “Browse”. Click “OK”.
- Tick “I would like to create a new design” and click “Next”.
- Select “Xilinx” as the board vendor. Select “XUP Virtex II Pro Development System” as the board name. Select “C” as the board revision. Click “Next”.
- Tick “PowerPC” and click “Next”.
- Select all clock frequencies to be 100MHz. Select “No debug”. Click “Next”.
- In selecting the Additional IO Interfaces, leave “RS232_Uart_1″ ticked and un-tick everything else.
- When Adding Internal Peripherals, select 64KB for the “plb_bram_if_cntlr_1″ and click “Next”.
- Select “RS232_Uart_1″ for both STDIN and STDOUT. Un-tick “Memory Test” and leave “Peripheral Test” ticked. Click “Next”.
- Click “Generate”.
- Click “Finish”.
- Tick “Start using Platform Studio” and click “OK”.
Create the Multiplier Peripheral
Follow these steps to create the multiplier peripheral.
- 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”.
- Type “my_multiplier” for the peripheral name. Click “Next”.
- Select “On-chip Peripheral Bus” (OPB) and click “Next”.
- The Peripheral Wizard can generate our VHDL template to include many different features. We will only need “FIFO”. Tick that option, un-tick everything else and click “Next”.
- For the FIFO Service settings, leave the defaults ticked: Include read FIFO, Include write FIFO, Use packet mode, Use vacancy calculation. Choose 32-bits for the width of the FIFOs, and choose a depth of 512.
- On the “IP Interconnect” page we can customize our connection to the OPB but we will leave everything as is for simplicity. 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.
Create the Multiplier core in VHDL
Follow these steps to create the Multiplier core:
- Select “File->New”. This will open a new text document that we will use for the multiplier VHDL source code.
- Copy and paste the following code into the new text document.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity multiplier is
port(
clk : in std_logic;
a : in std_logic_vector(15 downto 0);
b : in std_logic_vector(15 downto 0);
p : out std_logic_vector(31 downto 0)
);
end multiplier;
architecture IMP of multiplier is
begin
process (clk)
begin
if (clk'event and clk = '1') then
p <= unsigned(a) * unsigned(b);
end if;
end process;
end IMP;
|
- Save the file as “multiplier.vhd” in the “pcores\my_multiplier_v1_00_a\hdl\vhdl” folder.
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 another source file to the project (“multiplier.vhd”), we must include it in the .pao file.
- Select “File->Open” and browse to the “pcores\my_multiplier_v1_00_a\data” folder. Select the file “my_multiplier_v2_1_0.pao” and click “Open”.
- At the bottom of this file you will see these two lines:
lib my_multiplier_v1_00_a user_logic vhdl lib my_multiplier_v1_00_a my_multiplier vhdl |
- Add the line “lib my_multiplier_v1_00_a multiplier vhdl” just above those two lines.
- Save the file.
Now we can use this .pao file with the Peripheral Wizard and it will know to include the “multiplier.vhd” file in our design. Notice that the .pao file lists the source files in hierarchical order. Thus if you have a VHDL design consisting of multiple files, it is important to know the hierarchical order of your components. The components at the top of the chain are listed at the bottom of the file.
Modify the Peripheral
Now we will add code in our peripheral template to instantiate a multiplier core and we will connect it to the read and write FIFOs.
- Select from the menu “File->Open” and look in the project folder.
- Open the folders: “pcores\my_multiplier_v1_00_a\hdl\vhdl”. This folder contains two source files that describe our peripheral “my_multiplier.vhd” and “user_logic.vhd”. The first file is the main part of the peripheral and it implements the interface to the OPB. The second file is where we place our custom logic to make the peripheral do what we need it to do. This part is instantiated by the first file.
- Open the file “user_logic.vhd”. We will need to modify this source code to instantiate the multiplier and connect it to the read and write FIFOs.
- Find the line of code that says “–USER signal declarations added here” and add the following lines of code just below.
component multiplier
port (
clk: in std_logic;
a: in std_logic_VECTOR(15 downto 0);
b: in std_logic_VECTOR(15 downto 0);
p: out std_logic_VECTOR(31 downto 0));
end component;
|
- Find the line of code that says “–USER logic implementation added here” and add the following lines of code just below.
multiplier_0 : multiplier
port map (
clk => Bus2IP_Clk,
a => WFIFO2IP_Data(16 to 31),
b => WFIFO2IP_Data(0 to 15),
p => IP2RFIFO_Data);
|
- Find the line of code that says “IP2RFIFO_Data <= WFIFO2IP_Data;” and comment it out (or delete it). Now, the read FIFO will be loaded with data from the multiplier.
- Save and close the file.
Import the Multiplier Peripheral
Now we will use the Peripheral Wizard in Import mode.
- 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 “my_multiplier”. 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\my_multiplier_v1_00_a\data” and select the “my_multiplier_v2_1_0.pao” file. Click “Next”.
- On the HDL analysis information page, if you scroll down, you will see the “multiplier.vhd” file listed third from the bottom. Click “Next”. The wizard will mention if any errors are found in the design.
- On the Bus Interfaces page, tick “OPB Slave” and click “Next”.
- On the “SOPB: Port” page, click “Next”.
- On the “SOPB: Parameter” page, click “Next”.
- On the “Parameter Attributes” page, click “Next”.
- On the “Port Attributes” page, click “Next”.
- Click “Finish”.
The multiplier peripheral should now be accessible through the “IP Catalog->Project Repository” in the XPS interface.
Create an Instance of the Peripheral
Follow these steps to create an instance of the peripheral in the project.
- From the “IP Catalog” find the “my_multiplier” IP core in the “Project Repository” group. Right click on the core and select “Add IP”.
- From the “System Assembly View” using the “Bus Interface” filter, connect the “my_multiplier_0″ to the OPB bus.
- Click on the “Addresses” filter. Change the “Size” for “my_multiplier_0″ to 64K. Then click “Generate Addresses”.
Now we have an instance of the multiplier peripheral in our project and our hardware design is complete.
Modify the Software Application
Now all we need to do is modify the software application to test our multiplier 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.
#include "xparameters.h"
#include "xbasic_types.h"
#include "xstatus.h"
#include "my_multiplier.h"
Xuint32 *baseaddr_p = (Xuint32 *)XPAR_MY_MULTIPLIER_0_BASEADDR;
int main (void) {
Xuint32 i;
Xuint32 temp;
Xuint32 baseaddr;
// Clear the screen
xil_printf("%c[2J",27);
// Check that the peripheral exists
XASSERT_NONVOID(baseaddr_p != XNULL);
baseaddr = (Xuint32) baseaddr_p;
xil_printf("Multiplier Test\n\r");
// Reset read and write packet FIFOs to initial state
MY_MULTIPLIER_mResetWriteFIFO(baseaddr);
MY_MULTIPLIER_mResetReadFIFO(baseaddr);
// Push data to write packet FIFO
for(i = 1; i <= 4; i++ ){
temp = (i << 16) + i;
xil_printf("Wrote: 0x%08x \n\r", temp);
MY_MULTIPLIER_mWriteToFIFO(baseaddr, temp);
}
// pop data out from read packet FIFO
for(i = 0; i < 4; i++){
temp = MY_MULTIPLIER_mReadFromFIFO(baseaddr);
xil_printf("Read: 0x%08x \n\r", temp);
}
// Reset the read and write FIFOs
MY_MULTIPLIER_mResetWriteFIFO(baseaddr);
MY_MULTIPLIER_mResetReadFIFO(baseaddr);
xil_printf("End of test\n\n\r");
// Stay in an infinite loop
while(1){
}
}
|
- Save and close the file.
Download and Test the Project
- Open a Hyperterminal window with the required settings. For the correct settings, see Hyperterminal Settings.
- Turn on the XUPV2P board.
- From the XPS software, select “Device Configuration->Download Bitstream”.
The Hyperterminal output should look as shown in the image below:
Remember, those numbers are in hexadecimal so 0×10 = 16!
The project folder for this tutorial can be downloaded in a compressed ZIP file MultiplierVHDL.zip
. Right-click on the link and select “Save Link As”.
For a more powerful example of integrating a VHDL design into a peripheral, see Creating an Aurora Transceiver. In this tutorial, we create a peripheral to allow serial communication at 1.5Gbps between two XUPV2P boards connected by a SATA cable.
In the next tutorial, Timer with Interrupts, we show how to create a peripheral that is capable of generating interrupts on the PowerPC.
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 Peripheral Wizard. We will first create a blackbox multiplier using the Xilinx CORE Generator and then we will use the generated .ngc file in our peripheral.
The multiplier will take in two 16 bit unsigned inputs and have a 32 bit unsigned output. A single 32 bit write to the peripheral will contain the two 16 bit inputs, separated by the lower and higher 16 bits. A single 32 bit read from the peripheral will contain the result from the multiplication of the two 16 bit inputs. Instead of registers, we will use a read and write FIFO for the interface with the software application. In this way, the peripheral write FIFO can be loaded with a number of multiplications to perform, and the results can be pushed into the read FIFO for the software application to retrieve at its convenience. Practically, this design does not serve much purpose, but it is a simple demonstration of integrating blackbox designs into peripherals.
This tutorial contains screenshots to guide you through the entire implementation process. You can click on the images to view a higher resolution when necessary.
Are you using EDK 10.1?
Try the updated version of this tutorial based on the Virtex-5 FPGA on the ML505 board: Integrating a Blackbox into a Peripheral
Create the Basic Project
Follow these steps to create the basic project:
- Open XPS and from the dialog box, select “Base System Builder wizard” and OK.
- Create a new folder for the project and select it using “Browse”. In “Advanced Options” tick “Use repository paths” and select the “C:\XUPV2P\lib” folder using “Browse”. Click “OK”.
- Tick “I would like to create a new design” and click “Next”.
- Select “Xilinx” as the board vendor. Select “XUP Virtex II Pro Development System” as the board name. Select “C” as the board revision. Click “Next”.
- Tick “PowerPC” and click “Next”.
- Select all clock frequencies to be 100MHz. Select “No debug”. Click “Next”.
- In selecting the Additional IO Interfaces, leave “RS232_Uart_1″ ticked and un-tick everything else.
- When Adding Internal Peripherals, select 64KB for the “plb_bram_if_cntlr_1″ and click “Next”.
- Select “RS232_Uart_1″ for both STDIN and STDOUT. Un-tick “Memory Test” and leave “Peripheral Test” ticked. Click “Next”.
- Click “Generate”.
- Click “Finish”.
- Tick “Start using Platform Studio” and click “OK”.
Create the Multiplier Peripheral
Follow these steps to create the multiplier peripheral.
- 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”.
- Type “my_multiplier” for the peripheral name. Click “Next”.
- Select “On-chip Peripheral Bus” (OPB) and click “Next”.
- The Peripheral Wizard can generate our VHDL template to include many different features. We will only need “FIFO”. Tick that option, un-tick everything else and click “Next”.
- For the FIFO Service settings, leave the defaults ticked: Include read FIFO, Include write FIFO, Use packet mode, Use vacancy calculation. Choose 32-bits for the width of the FIFOs, and choose a depth of 512.
- On the “IP Interconnect” page we can customize our connection to the OPB but we will leave everything as is for simplicity. 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.
Create the Multiplier with CORE Generator
Follow these steps to generate the Multiplier.
- Leaving XPS running and your project open, from the “Start” menu, open Xilinx CORE Generator.
- Select “File->New Project”.
- Click “Browse” and select an appropriate location for a Coregen project. Within a Coregen project, you can create several cores that don’t necessarily relate to each other. Just select the folder where you normally place your projects, for example “C:\XUPV2P\Projects”. Click “OK”.
- CORE Generator will ask you if you want to create the “coregen” folder. Click “OK”.
- You will be asked for the specifications of the FPGA you are using. Under the “Part” tab, select these options: Family “Virtex2P”, Device “xc2vp30″, Package “ff896″, Speed grade “-7″. Click “OK”.
- When you have created your Coregen project, click on the “View by Function” tab to get a list of cores that you are able to generate.
- Open “Math Functions->Multipliers” and double-click on “Multiplier”.
- A dialog box should open to allow you to select the features of the Multiplier you want. For “Multiplier Type” select “Parallel Multiplier”. Select “Unsigned” for both port inputs and give them a width of 16 bits.
- Click “Finish”. Your Multiplier core will be generated and CORE Generator will display a list of all the generated files. Close this window, and close CORE Generator.
Modify the Peripheral
When we create a peripheral with read and write FIFOs, the Peripheral Wizard generates code in the user_logic.vhd file that loops the data from the write FIFO to the read FIFO. This makes it easy to test for the first time because one can write data to the peripheral and verify that it was received by reading back the same data. In our case, the loop-back design reduces the number of modifications we need to make because we want to do the same thing, only we want to first pass the data through the multiplier before putting it through to the read FIFO. Now we will add code in our peripheral template to instantiate a multiplier core and connect it to the read and write FIFOs.
- Select from the menu “File->Open” and look in the project folder.
- Open the folders: “pcores\my_multiplier_v1_00_a\hdl\vhdl”. This folder contains two source files that describe our peripheral “my_multiplier.vhd” and “user_logic.vhd”. The first file is the main part of the peripheral and it implements the interface to the OPB. The second file is where we place our custom logic to make the peripheral do what we need it to do. This part is instantiated by the first file.
- Open the file “user_logic.vhd”. We will need to modify this source code to instantiate the multiplier and connect it to the read and write FIFOs.
- Find the line of code that says “–USER signal declarations added here” and add the following lines of code just below.
component multiplier_v9_0
port (
clk: IN std_logic;
a: IN std_logic_VECTOR(15 downto 0);
b: IN std_logic_VECTOR(15 downto 0);
p: OUT std_logic_VECTOR(31 downto 0));
end component;
|
- Find the line of code that says “–USER logic implementation added here” and add the following lines of code just below.
multiplier_0 : multiplier_v9_0
port map (
clk => Bus2IP_Clk,
a => WFIFO2IP_Data(16 to 31),
b => WFIFO2IP_Data(0 to 15),
p => IP2RFIFO_Data);
|
- Find the line of code that says “IP2RFIFO_Data <= WFIFO2IP_Data;” and comment it out (or delete it). Now, the read FIFO will be loaded with data from the multiplier.
- Save and close the file.
Import the 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 “my_multiplier”. 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”.
- Now we are asked about the files that make up our peripheral. As usual we tick “HDL source files” and in this case, to include our .ngc file, we will also tick “Netlist files”. Now click “Next”.
- Select “Use existing Peripheral Analysis Order file (*.pao)” and click “Browse”. From the project folder, go to “pcores\my_multiplier_v1_00_a\data” and select the “my_multiplier_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 “OPB Slave” and click “Next”.
- On the SOPB: Port page, click “Next”.
- On the SOPB: Parameter page, click “Next”.
- On the “Parameter Attributes” page, click “Next”.
- On the “Port Attributes” page, click “Next”.
- Now we should arrive at the “Netlist Files” page where we are asked to locate any netlist files or black-box components that are instantiated in our peripheral. Click “Select Files” and navigate your way to the Coregen project folder “coregen” that you created using CORE Generator earlier. You will find a file called “multiplier_v9_0_mult_gen_v9_0_xst_1.ngc”. Rename this file to “multiplier_v9_0.ngc”, then select the file and click “Open”. The file should now be listed on the “Netlist Files” page. Click “Next”.
- Click “Finish”.
When you include .ngc files in a peripheral design as we just did, the Peripheral Wizard does some things behind-the-scenes that are important to know. Firstly, it makes a copy of the .ngc file and places it in the “pcores\my_multiplier_v1_00_a\netlist” folder (if that folder doesn’t exist, it creates one). Secondly, it creates a file called “my_multiplier_v2_1_0.bbd” in the “pcores\my_multiplier_v1_00_a\data” folder with the following contents:
############################################################ ## Filename: C:\XUPV2P\Projects\Multiplier5\pcores- /my_multiplier_v1_00_a/data/my_multiplier_v2_1_0.bbd ## Description: Black Box Definition ## Date: Mon Feb 11 16:53:42 2008 (by Create a- nd Import Peripheral Wizard) ############################################################ Files ############################################################ multiplier_v9_0.ngc |
Finally, the Peripheral Wizard adds these two lines to the “my_multiplier_v2_1_0.mpd” file in the “pcores\my_multiplier_v1_00_a\data” folder:
OPTION STYLE = MIX OPTION RUN_NGCBUILD = TRUE |
The multiplier peripheral should now be accessible through the “IP Catalog->Project Repository” in the XPS interface.
Create an Instance of the Peripheral
Follow these steps to create an instance of the peripheral in the project.
- From the “IP Catalog” find the “my_multiplier” IP core in the “Project Repository” group. Right click on the core and select “Add IP”.
- From the “System Assembly View” using the “Bus Interface” filter, connect the “my_multiplier_0″ to the OPB bus.
- Click on the “Addresses” filter. Change the “Size” for “my_multiplier_0″ to 64K. Then click “Generate Addresses”.
Now we have an instance of the multiplier peripheral in our project and our hardware design is complete.
Modify the Software Application
Now all we need to do is modify the software application to test our multiplier 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"
#include "my_multiplier.h"
Xuint32 *baseaddr_p = (Xuint32 *)XPAR_MY_MULTIPLIER_0_BASEADDR;
int main (void) {
Xuint32 i;
Xuint32 temp;
Xuint32 baseaddr;
// Clear the screen
xil_printf("%c[2J",27);
// Check that the peripheral exists
XASSERT_NONVOID(baseaddr_p != XNULL);
baseaddr = (Xuint32) baseaddr_p;
xil_printf("Multiplier Test\n\r");
// Reset read and write packet FIFOs to initial state
MY_MULTIPLIER_mResetWriteFIFO(baseaddr);
MY_MULTIPLIER_mResetReadFIFO(baseaddr);
// Push data to write packet FIFO
for(i = 1; i <= 4; i++ ){
temp = (i << 16) + i;
xil_printf("Wrote: 0x%08x \n\r", temp);
MY_MULTIPLIER_mWriteToFIFO(baseaddr, temp);
}
// pop data out from read packet FIFO
for(i = 0; i < 4; i++){
temp = MY_MULTIPLIER_mReadFromFIFO(baseaddr);
xil_printf("Read: 0x%08x \n\r", temp);
}
// Reset the read and write FIFOs
MY_MULTIPLIER_mResetWriteFIFO(baseaddr);
MY_MULTIPLIER_mResetReadFIFO(baseaddr);
xil_printf("End of test\n\n\r");
// Stay in an infinite loop
while(1){
}
}
|
- Save and close the file.
Download and Test the Project
- Open a Hyperterminal window with the required settings. For the correct settings, see Hyperterminal Settings.
- Turn on the XUPV2P board.
- From the XPS software, select “Device Configuration->Download Bitstream”.
The Hyperterminal output should look as shown in the image below:
Remember, those numbers are in hexadecimal so 0×10 = 16!
The project folder for this tutorial can be downloaded in a compressed ZIP file MultiplierNGC.zip
. Right-click on the link and select “Save Link As”.
For an example of integrating a black-box FIFO into a peripheral, see Creating an Aurora Transceiver. In this tutorial, we create an Aurora peripheral to allow serial communication at 1.5Gbps between two XUPV2P boards connected by a SATA cable.
In the next tutorial, Integrating a VHDL Design into a Peripheral, we show how to integrate a custom VHDL design into the Peripheral Wizard templates.
Overview
In this project, we will add code to a peripheral template generated by the Peripheral Wizard to create a simple timer. The timer peripheral will be used by the PowerPC to make the LEDs flash with a fixed period.
The timer will use two registers, one to store the delay period and the other for starting, stopping and checking if the timer has expired. We will call the first register the delay register and the second register the control register. The delay register will be set by the software application to determine how long of a delay it requires. This value will remain in the delay register unchanged and the software application will be able to read this value if for some reason it needs to. The control register will only use the first two bits, being bit 0 and bit 1. Bit 0 will be read-only and will be used by the timer peripheral to signal to the software application that the timer has expired. Bit 1 will be read and writeable, and it will be used by the software application to make the timer “run”. When a “1″ is written to this bit, the timer will start counting down from the delay value. When a “0″ is written to this bit, the timer will reset.
This tutorial contains screenshots to guide you through the entire implementation process. You can click on the images to view a higher resolution when necessary.
Create the Basic Project
Follow these steps to create the basic project:
- Open XPS and from the dialog box, select “Base System Builder wizard” and OK.
- Create a new folder for the project and select it using “Browse”. In “Advanced Options” tick “Use repository paths” and select the “C:\XUPV2P\lib” folder using “Browse”. Click “OK”.
- Tick “I would like to create a new design” and click “Next”.
- Select “Xilinx” as the board vendor. Select “XUP Virtex II Pro Development System” as the board name. Select “C” as the board revision. Click “Next”.
- Tick “PowerPC” and click “Next”.
- Select all clock frequencies to be 100MHz. Select “No debug”. Click “Next”.
- In selecting the Additional IO Interfaces, tick “RS232_Uart_1″ and “LEDs_4Bit”. Untick everything else.
- When Adding Internal Peripherals, select 64KB for the “plb_bram_if_cntlr_1″ and click “Next”.
- Select “RS232_Uart_1″ for both STDIN and STDOUT. Un-tick “Memory Test” and leave “Peripheral Test” ticked. Click “Next”.
- On the “Configure Peripheral Test Application” page, select “plb_bram_if_cntlr_1″ for the Instruction, Data, Stack and Heap memories. Click “Next”.
- Click “Generate”.
- Click “Finish”.
- Tick “Start using Platform Studio” and click “OK”.
Modify the Software Application
The software application that the BSB has created for us will test the LEDs by making them flash one at a time. We want to modify this application so that it makes all the LEDs flash at the same time.
- 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 "xgpio.h"
#include "xstatus.h"
XGpio GpioOutput;
int main (void) {
Xuint32 status;
unsigned int i;
// Initialize the GPIO driver so that it's ready to use,
status = XGpio_Initialize(&GpioOutput,
XPAR_LEDS_4BIT_DEVICE_ID);
if (status != XST_SUCCESS)
return XST_FAILURE;
// Set the direction for all signals to be outputs
XGpio_SetDataDirection(&GpioOutput, 1, 0x0);
while(1){
// Turn OFF the LEDs
XGpio_DiscreteWrite(&GpioOutput, 1, 0xF);
// Wait for a period
for(i = 0; i < 0x0F00000; i++){}
// Turn ON the LEDs
XGpio_DiscreteWrite(&GpioOutput, 1, 0x0);
// Wait for a period
for(i = 0; i < 0x0F00000; i++){}
}
}
|
- From the menu select “Device Configuration->Download Bitstream”.
The bitstream will be created and downloaded into the FPGA. When the application runs, you will see the LEDs on the XUPV2P board flashing.
If you read through the code, you will notice that we have used simple “for” loops to implement delays between turning the LEDs on and turning them off. Without the delays, the LEDs would flash more quickly than the human eye can see. The main problems with using these “for” loops are: (1) we can’t be very precise about the delay time because it depends on how quickly the processor completes the “for” loop which depends on how many instructions per second it can perform and whether any interrupt routines are executed during that time, (2) the main program can’t do anything during the time that we wait.
For these reasons, instead of using the PowerPC to calculate the delays, it is more convenient to use an external timer module. An independent timer peripheral can count-down the delay that we specify and will not be influenced by other processes occurring at the same time. To check the timer, the PowerPC has the choice of either (1) polling the timer peripheral to find out when the delay period has expired or (2) receive an interrupt when the delay period has expired. In this tutorial, we will use the polling method for simplicity. The interrupt method is explored in the tutorial Timer with Interrupts.
Create the Timer Peripheral
We now create our Timer 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”.
- Type “my_timer” for the peripheral name. Click “Next”.
- Select “On-chip Peripheral Bus” (OPB) and click “Next”.
- The Peripheral Wizard can generate our VHDL template to include many different features. Tick “User logic S/W register support”. Un-tick everything else and click “Next”.
- Choose “2″ for the number of software accessible registers. Choose 32-bits for the size of the registers, as we will use a 32-bit timer.
- On the “IP Interconnect” page we can customize our connection to the OPB but we will leave everything as is for simplicity. 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.
Modify the Peripheral
Now we want to add a simple timer to this peripheral template and connect it up with the registers that the Peripheral Wizard created for us.
- Select from the menu “File->Open” and look in the project folder.
- Open the folders: “pcores\my_timer_v1_00_a\hdl\vhdl”. This folder contains two source files that describe our peripheral “my_timer.vhd” and “user_logic.vhd”. The first file is the main part of the peripheral and it implements the interface to the OPB. The second file is where we place our custom logic to make the peripheral do what we need it to do. This part is instantiated by the first file.
- Open the file “user_logic.vhd”. We will need to modify this source code to include our timer code.
- Find the line of code that says “–USER signal declarations added here” and add the following lines of code just below.
-- Timer signals and components signal timer_count : std_logic_vector(0 to C_DWIDTH-1); signal timer_expired : std_logic; signal timer_run : std_logic; |
- Find the line of code that says “–USER logic implementation added here” and add the following lines of code just below.
-- Timer connections
timer_run <= slv_reg1(1);
-- Timer process - times the delay between bursts
process (Bus2IP_Clk, Bus2IP_Reset)
begin
-- if the peripheral is told to reset, then reset the timer
if Bus2IP_Reset = '1' then
timer_count <= (others => '0');
timer_expired <= '1';
-- otherwise, if there is a clock event, run the timer
elsif Bus2IP_Clk'event and Bus2IP_Clk = '1' then
-- if the timer is not running, then reset the timer
if timer_run = '0' then
timer_count <= slv_reg0;
timer_expired <= '0';
-- if the timer count is not zero then decrease the count
elsif timer_count /= 0 then
timer_count <= timer_count - 1;
timer_expired <= '0';
-- otherwise, the timer has expired
else
timer_expired <= '1';
end if;
end if;
end process;
|
- Find the line of code that says “when “01″ => slv_ip2bus_data <= slv_reg1″ and replace it with the three lines of code below. Now, when the timer control register is read from, bit 0 will represent the timer_expired signal.
when "01" => slv_ip2bus_data(1 to C_DWIDTH-1) <= slv_reg1(1 to C_DWIDTH-1); slv_ip2bus_data(0) <= timer_expired; |
- Save and close the file.
Import the Timer 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 “my_timer”. 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\my_timer_v1_00_a\data” and select the “my_timer_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 “OPB Slave” and click “Next”.
- On the SOPB: Port page, click “Next”.
- On the SOPB: Parameter page, click “Next”.
- On the “Parameter Attributes” page, click “Next”.
- On the “Port Attributes” page, click “Next”.
- Click “Finish”.
The timer peripheral is now ready to use and it should be accessible through the “IP Catalog->Project Repository” 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 Timer Peripheral
Now we are ready to create an instance of the peripheral into our project which can then be downloaded into the FPGA and tested by using simple code running on the PowerPC.
- From the “IP Catalog” find the “my_timer” IP core in the “Project Repository” group. Right click on the core and select “Add IP”.
- From the “System Assembly View” using the “Bus Interface” filter, connect the “my_timer_0″ to the OPB bus.
- Click on the “Addresses” filter. Change the “Size” for “my_timer_0″ to 64K. Then click “Generate Addresses”.
Now we have created an instance of the Timer peripheral in our design.
Modify the Software Application
Now the timer peripheral is in our project and ready for us to use. We can now modify our software application to use the timer to produce the delays between turning the LEDs on and turning them off.
In the code below, to interact with the timer peripheral, we are using the “my_timer” driver that was created by the peripheral wizard and located in the project folder at “\drivers\my_timer”. The include file “my_timer.h” provides us with simple functions for reading and writing to the registers that we created in our peripheral. In general, you should always check the peripheral driver source code whenever you create a peripheral because it often contains useful functions for the features you included in the 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 "xgpio.h"
#include "xstatus.h"
#include "my_timer.h"
#define TIMER_RESET 0x00000000
#define TIMER_RUN 0x40000000
#define TIMER_EXPIRED 0x80000000
#define TIMER_HALFSEC 0x02FAF080
XGpio GpioOutput;
unsigned int *my_timer_p =
(unsigned int *) XPAR_MY_TIMER_0_BASEADDR;
int main (void) {
Xuint32 my_timer;
Xuint32 status;
// Check that the my_timer peripheral exists
XASSERT_NONVOID(my_timer_p != XNULL);
my_timer = (Xuint32) my_timer_p;
// Load the delay register with the delay time of 0.5s
MY_TIMER_mWriteSlaveReg0(my_timer, TIMER_HALFSEC);
// Initialize the GPIO driver
status = XGpio_Initialize(&GpioOutput,
XPAR_LEDS_4BIT_DEVICE_ID);
if (status != XST_SUCCESS)
return XST_FAILURE;
// Set the direction for all signals to be outputs
XGpio_SetDataDirection(&GpioOutput, 1, 0x0);
while(1){
// Turn OFF the LEDs
XGpio_DiscreteWrite(&GpioOutput, 1, 0xF);
// Start the timer and wait for it to expire
MY_TIMER_mWriteSlaveReg1(my_timer, TIMER_RUN);
while(!(MY_TIMER_mReadSlaveReg1(my_timer) & TIMER_EXPIRED)){}
// Reset the timer
MY_TIMER_mWriteSlaveReg1(my_timer, TIMER_RESET);
// Turn ON the LEDs
XGpio_DiscreteWrite(&GpioOutput, 1, 0x0);
// Start the timer and wait for it to expire
MY_TIMER_mWriteSlaveReg1(my_timer, TIMER_RUN);
while(!(MY_TIMER_mReadSlaveReg1(my_timer) & TIMER_EXPIRED)){}
// Reset the timer
MY_TIMER_mWriteSlaveReg1(my_timer, TIMER_RESET);
}
}
|
Download and Test the Project
- Turn on the XUPV2P board.
- From the XPS software, select “Device Configuration->Download Bitstream”.
The bitstream will be created and downloaded into the FPGA. When the application runs, you will see the LEDs on the XUPV2P board flashing once every second. The timer peripheral is set for a delay period of half a second. Every time the timer expires, the state of the LEDs is inverted so that the LEDs remain ON for half a second and OFF for half a second.
The project folder for this tutorial can be downloaded in a compressed ZIP file SimpleTimer.zip
. Right-click on the link and select “Save Link As”.
In the next tutorial, Integrating a Black Box into a Peripheral, we show how to integrate a netlist (.NGC) file into a peripheral. For an improved version of the timer peripheral using interrupts, see Timer with Interrupts.
Most of these projects use the RS-232 UART on the XUPV2P for simple debugging IO. The Hyperterminal settings for use with these projects are given in the table below.
| Baud rate | 9600 bps |
| Data bits | 8 bits |
| Parity | None |
| Stop bits | 1 bit |
| Flow control | None |
The com port that is used (eg. COM1) will depend on whether you have a serial port already installed on your computer, or if you need to use a USB-Serial converter. To find out what com ports you have available on your computer, right click on “My Computer” and select “Manage”. Click on “Device Manager” that lies within “System Tools”. Then find and open “Ports” in the list of devices. There you will find a list of installed ports. The com ports are named COM1, COM2, etc. When you know the port number that you are using, you can select that port in setting up Hyperterminal.



Recent Comments