September 24, 200938 minutes
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:
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
XC5VLX50T
XC5VSX50T
XC5VLX110T
To program your FPGA with the bit file, first extract the contents of your ZIP file to your hard drive (eg. C:\AEBridge-XUPV5).
cmd. Press “Enter” and you should have a command prompt.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>”.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:
DIP_Switches_8Bit ticked and un-tick everything else.
Create the Bridge Peripheral
We now create our Bridge peripheral using the Peripheral Wizard.
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.
TEMACCore\v5_emac_v1_5. This is the folder you created with CORE Generator.
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.
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.
pcores\bridge_v1_00_a\data folder. Select the file bridge_v2_1_0.pao and click “Open”.lib bridge_v1_00_a user_logic vhdl
lib bridge_v1_00_a bridge vhdllib 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.vhdNow 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.
pcores\bridge_v1_00_a\hdl\vhdl.bridge.vhd.-- 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);-- 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,user_logic.vhd. We will need to modify this source code to include our example code.--USER libraries added here and add the following lines of code just below.library UNISIM;
use UNISIM.VCOMPONENTS.ALL;-- 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);--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;--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;Import the Bridge Peripheral
Now we will use the Peripheral Wizard again, but this time using the import function.
pcores\bridge_v1_00_a\data and select the bridge_v2_1_0.pao file. Click “Next”.
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.
bridge_0 to the PLB bus.
bridge_0 to view its ports.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”.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”.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”.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”.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”.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”.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”.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”.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”.
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.
xps_gpio_0. Click on the xps_gpio_0 peripheral and rename it to “LCD”, then connect it to the PLB bus.
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”.

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.
##### 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;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).
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.
TestApp_Peripheral.c source 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.
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
In order from left to right, as shown in the photo, the LEDs indicate: CONNECTION, TX, RX, 10Mbps, 100Mbps, 1000Mbps. 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.
Test the Bridge between Two PCs
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//123.456.789.012/fpgadeveloperYou 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:
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
XC5VLX50T
XC5VSX50T
XC5VLX110T