February 14, 200816 minutes
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:
Create the Basic Project
Follow these steps to create the basic project:

C as the board revision. Click “Next”.



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.

plb_bram_if_cntlr_1 and click “Next”.

RS232_Uart_1 for both STDIN and STDOUT. Un-tick “Memory Test” and leave “Peripheral Test” ticked. Click “Next”.

plb_bram_if_cntlr_1 for the Instruction, Data, Stack and Heap memories. Click “Next”.

Create the DCM Peripheral
Follow these steps to create the DCM peripheral:

mgt_dcm for the peripheral name. Click “Next”.


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”.
pcores\mgt_dcm_v1_00_a\hdl\vhdl.mgt_dcm.vhd.-- 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;-- 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,pcores\mgt_dcm_v1_00_a\hdl\vhdl.user_logic.vhd.-- 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;--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;--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;Import the DCM Peripheral
Now we will use the Peripheral Wizard to import the DCM peripheral.

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”.

pcores\mgt_dcm_v1_00_a\data and select the mgt_dcm_v2_1_0.pao file. Click “Next”.


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.
mgt_dcm IP core in the “Project Repository” group. Right click on the core and select “Add IP”.

mgt_dcm_0 to the OPB bus.

mgt_dcm_0 to view its ports.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”.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”.TOP_BREF_CLK port. Type TOP_BREF_CLK in this field and press “Enter”.USER_CLK port. Type USER_CLK in this field and press “Enter”. The result should look like the image below.

TOP_BREF_CLK_P_pin and TOP_BREF_CLK_N_pin, with nets called TOP_BREF_CLK_P and TOP_BREF_CLK_N respectively.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.




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.
pcores\oscillator_v1_00_a\hdl\vhdl.oscillator.vhd.-- 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;-- 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,pcores\oscillator_v1_00_a\hdl\vhdl.user_logic.vhd. We will need to modify this source code to instantiate the GT_CUSTOM and connect it as an oscillator.-- 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;--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;--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;Import the Oscillator Peripheral
Now we will use the Peripheral Wizard in Import mode.


pcores\oscillator_v1_00_a\data and select the oscillator_v2_1_0.pao file. Click “Next”.



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.

oscillator_0 to the OPB bus.

oscillator_0 to view its ports.TOP_BREF_CLK port. Type TOP_BREF_CLK in this field and press “Enter”.USER_CLK port. Type USER_CLK in this field and press “Enter”. The ports should look as shown in the screen shot below.

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.
UCF File: data/system.ucf from within the “Project Files” tree. The .ucf file should open.#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;Modify the Software Application
Now all we need to do is modify the software application to test our oscillator peripheral.
TestApp_Peripheral.c source 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);
}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.