--==============================================================================
-- © Copyright CERN for the benefit of the HPTD interest group 2019. All rights not
-- expressly granted are reserved.
--
-- This file is part of TClink.
--
-- TClink is free VHDL code: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- TClink is distributed in the hope that it will be useful,
-- but WITHout ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with TClink. If not, see .
--==============================================================================
--! @file tb_lpgbt10G.vhd
--==============================================================================
--! Standard library
library ieee;
--! Standard packages
use ieee.std_logic_1164.all;
use std.textio.all;
use ieee.numeric_std.all;
use ieee.math_real.uniform;
use ieee.math_real.floor;
--! Specific packages
--! Include the LpGBT-FPGA specific package
use work.lpgbtfpga_package.all;
-------------------------------------------------------------------------------
-- --
-- CERN, EP-ESE-BE, HPTD
-- --
-------------------------------------------------------------------------------
--
-- unit name: lpGBT10G uplink protocol test-bench (tb_lpgbt10G)
--
--! @brief lpGBT10G protocol test-bench
--!
--! @author Eduardo Brandao de Souza Mendes - eduardo.brandao.de.souza.mendes@cern.ch
--! @date 27\01\2019
--! @version 1.0
--! @details
--!
--! Dependencies:\n
--!
--!
--! References:\n
--! \n
--!
--!
--! Modified by:\n
--! Author: Eduardo Brandao de Souza Mendes
-------------------------------------------------------------------------------
--! \n\nLast changes:\n
--! 27\01\2019 - EBSM - Created\n
--!
-------------------------------------------------------------------------------
--! @todo - \n
--! \n
--
-------------------------------------------------------------------------------
--==============================================================================
--! Entity declaration for tb_lpgbt10G
--==============================================================================
entity tb_lpgbt10G is
generic(
g_DATARATE : integer RANGE 0 to 2 := DATARATE_10G24 ; --! Datarate selection can be: DATARATE_10G24 or DATARATE_5G12
g_FEC : integer RANGE 0 to 2 := FEC5 ; --! FEC selection can be: FEC5 or FEC12
g_PAYLOAD_LENGTH : integer := 230 --! User payload length (depends on FEC and DATARATE)
--! * *FEC5 / 5.12 Gbps*: 112bit
--! * *FEC12 / 5.12 Gbps*: 98bit
--! * *FEC5 / 10.24 Gbps*: 230bit
--! * *FEC12 / 10.24 Gbps*: 202bit
);
port(
TEST_BENCH_STATUS_O : out string(1 to 25) := " RESET ";
FECMONITOR_O : out integer ;
PRBSMONITOR_O : out integer
);
end tb_lpgbt10G;
--==============================================================================
-- architecture declaration
--==============================================================================
architecture tb of tb_lpgbt10G is
--! Function declaration
--! Constant declaration
constant c_CLOCK_SYS_PERIOD : time := 10.0 ns;
constant c_CLOCK_MGT_PERIOD : time := 3.125 ns;
-- PRBS gen/chk
constant c_PRBS_FRAME_WIDTH : integer := g_PAYLOAD_LENGTH + 4; -- +4 comes from EC and IC fields
constant c_PRBS_POLYNOMIAL : std_logic_vector(23 downto 0) := (23 => '1', 18=> '1', 0 => '1', others => '0'); -- PRBS-23 testing (x^7 + x^6 + 1)
-- lpGBT-FPGA expert parameters (values extracted from example design for KCU105)
constant c_multicyleDelay : integer := 3 ;
constant c_clockRatio : integer := 8 ;
constant c_mgtWordWidth : integer := 32;
constant c_allowedFalseHeader : integer := 5 ;
constant c_allowedFalseHeaderOverN : integer := 64;
constant c_requiredTrueHeader : integer := 32;
constant c_bitslip_mindly : integer := 2 ;
constant c_bitslip_waitdly : integer := 40;
-- Bitslip expert parameters for fixed latency applications - EBSM
constant c_resetOnEven : integer := 1; --! Reset on even bitslip (1: Enabled/ 0: disabled)
constant c_resetDuration : integer := 10; --! Reset duration (in clk_freeRunningClk_i periods)
--! Signal declaration
-------------------------------------------------- Common --------------------------------------------------
signal common_clk_sys : std_logic;
signal common_clk_mgt : std_logic;
-------------------------------------------------------------------------------------------------------------
---------------------------------------------- PRBS generator -----------------------------------------------
signal prbsgen_strobe_cntr : integer range 0 to 7;
signal prbsgen_strobe : std_logic; --! enable input
signal prbsgen_reset : std_logic; --! active high sync. reset
signal prbsgen_seed : std_logic_vector(c_PRBS_POLYNOMIAL'length-2 downto 0) := (others => '1'); --! Seed for polynomial
signal prbsgen_load : std_logic; --! Load seed
signal prbsgen_frame : std_logic_vector(c_PRBS_FRAME_WIDTH-1 downto 0); --! PRBS output data
signal prbsgen_data_valid : std_logic; --! PRBS data valid
-------------------------------------------------------------------------------------------------------------
------------------------------------------------ lpGBT-FE Tx ------------------------------------------------
signal Tx_reset : std_logic ;
signal Tx_tx_strobe : std_logic ;
signal Tx_tx_data : std_logic_vector(229 downto 0) := (others => '0');
signal Tx_tx_ec : std_logic_vector(1 downto 0) ;
signal Tx_tx_ic : std_logic_vector(1 downto 0) ;
signal Tx_tx_word : std_logic_vector(c_mgtWordWidth-1 downto 0) ;
signal Tx_scrambler_bypass : std_logic := '0' ;
signal Tx_interleaver_bypass : std_logic := '0' ;
signal Tx_tx_error : std_logic_vector(255 downto 0) := (others => '0');
-------------------------------------------------------------------------------------------------------------
--------------------------------- MGT Rx (High-level modelling for testing) ---------------------------------
signal channel_reset : std_logic;
signal channel_ready : std_logic;
signal channel_rx_data : std_logic_vector(2*c_mgtWordWidth-1 downto 0) := (others => '0');
signal channel_data : std_logic_vector(c_mgtWordWidth-1 downto 0) := (others => '0');
signal channel_bitslide_r : std_logic;
signal channel_bitslip_position : integer range 0 to c_mgtWordWidth-1 := 0;
signal channel_rx_frame_reset_phy : std_logic;
signal channel_rx_frame_reset_phy_r : std_logic;
-------------------------------------------------------------------------------------------------------------
---------------------------------------------- lpGBT-FPGA Rx ----------------------------------------------
-- Clock and reset
signal Rx_uplinkClkOutEn : std_logic; --! Clock enable to be USEd in the USEr's logic
signal Rx_uplinkRst_n : std_logic; --! Uplink reset SIGNAL (Rx ready from the transceiver)
-- Input
signal Rx_mgt_word : std_logic_vector((c_mgtWordWidth-1) downto 0); --! Input frame coming from the MGT
-- Data
signal Rx_USErData : std_logic_vector(229 downto 0); --! User output (decoded data). The payload size varies depENDing on the
--! datarate/FEC configuration:
--! * *FEC5 / 5.12 Gbps*: 112bit
--! * *FEC12 / 5.12 Gbps*: 98bit
--! * *FEC5 / 10.24 Gbps*: 230bit
--! * *FEC12 / 10.24 Gbps*: 202bit
signal Rx_EcData : std_logic_vector(1 downto 0); --! EC field value received from the LpGBT
signal Rx_IcData : std_logic_vector(1 downto 0); --! IC field value received from the LpGBT
-- Control
signal Rx_bypassInterleaver : std_logic := '0'; --! Bypass uplink interleaver (test purpose only)
signal Rx_bypassFECEncoder : std_logic := '0'; --! Bypass uplink FEC (test purpose only)
signal Rx_bypassScrambler : std_logic := '0'; --! Bypass uplink scrambler (test purpose only)
-- Transceiver control
signal Rx_mgt_bitslipCtrl : std_logic; --! Control the Bitslib/RxSlide PORT of the Mgt
-- Fixed-latency applications
signal Rx_rst_mgtctrler : std_logic; --! Rst the "reset on even" controller
signal Rx_rst_rstoneven : std_logic; --! Output reset asserted
-- Status
signal Rx_dataCorrected : std_logic_vector(229 downto 0); --! Flag allowing to know which bit(s) were toggled by the FEC
signal Rx_IcCorrected : std_logic_vector(1 downto 0); --! Flag allowing to know which bit(s) of the IC field were toggled by the FEC
signal Rx_EcCorrected : std_logic_vector(1 downto 0); --! Flag allowing to know which bit(s) of the EC field were toggled by the FEC
signal Rx_rdy : std_logic; --! Ready SIGNAL from the uplink decoder
-------------------------------------------------------------------------------------------------------------
---------------------------------------------- PRBS checker -----------------------------------------------
signal prbschk_reset : std_logic ;
signal prbschk_frame : std_logic_vector(c_PRBS_FRAME_WIDTH-1 downto 0);
signal prbschk_strobe : std_logic ;
signal prbschk_gen : std_logic_vector(c_PRBS_FRAME_WIDTH-1 downto 0);
signal prbschk_error : std_logic ;
signal prbschk_locked : std_logic ;
-------------------------------------------------------------------------------------------------------------
-- Test bench status and checkers
signal TEST_BENCH_STATUS : string(1 to 25) := " RESET ";
--! Component declaration
component prbs_gen is
generic (
g_PARAL_FACTOR : integer := 254 ; --! Size of parallel bus
g_PRBS_POLYNOMIAL : std_logic_vector := "11000001" --! Notation: x^7 + x^6 + 1 (PRBS-7)
);
port (
clk_i : in std_logic; --! clock input
en_i : in std_logic; --! enable input
reset_i : in std_logic; --! active high sync. reset
seed_i : in std_logic_vector(g_PRBS_POLYNOMIAL'length-2 downto 0); --! Seed for polynomial
load_i : in std_logic; --! Load seed
data_o : out std_logic_vector(g_PARAL_FACTOR-1 downto 0); --! PRBS output data
data_valid_o : out std_logic --! PRBS data valid output
);
end component prbs_gen;
component lpgbt_fe_tx is
generic(
g_MGT_WORD_WIDTH : integer := 32; -- Word width of MGT
g_DATA_RATE : integer := 2; -- 2=10G , 1=5G
g_FEC : integer := 1 -- 1=FEC5, 2=FEC12
);
-- all ports are synchronous to mgt_clock_i
port (
-- Clock / reset
reset_i : in std_logic ; --! active high sync input
mgt_clock_i : in std_logic ; --! mgt clock (320MHz)
-- User data
--! ___ 1-high / 7-low ___
tx_strobe_i : in std_logic ; --! ___/ \_____________________/ \_______________
tx_data_i : in std_logic_vector(229 downto 0) ; --! User frame input X FRAME0 X FRAME1
--! datarate/FEC configuration:
--! FEC5 / 5.12 Gbps => 112bit
--! FEC12 / 5.12 Gbps => 98bit
--! FEC5 / 10.24 Gbps => 230bit
--! FEC12 / 10.24 Gbps => 202bit
tx_ec_i : in std_logic_vector(1 downto 0) ;
tx_ic_i : in std_logic_vector(1 downto 0) ;
-- MGT
tx_word_o : out std_logic_vector(g_MGT_WORD_WIDTH-1 downto 0) ;
-- Debugging
scrambler_bypass_i : in std_logic; --! scrambler bypass
interleaver_bypass_i : in std_logic; --! interleaver bypass
tx_error_i : in std_logic_vector(255 downto 0) --! Debug error injection port
);
end component lpgbt_fe_tx;
component lpgbtfpga_uplink_fixed IS
GENERIC(
-- General configuration
DATARATE : integer RANGE 0 to 2; --! Datarate selection can be: DATARATE_10G24 or DATARATE_5G12
FEC : integer RANGE 0 to 2; --! FEC selection can be: FEC5 or FEC12
-- Expert parameters
c_multicyleDelay : integer RANGE 0 to 7 := 3; --! Multicycle delay: USEd to relax the timing constraints
c_clockRatio : integer; --! Clock ratio is mgt_USErclk / 40 (shall be an integer)
c_mgtWordWidth : integer; --! Bus size of the input word
c_allowedFalseHeader : integer; --! Number of false header allowed to avoid unlock on frame error
c_allowedFalseHeaderOverN : integer; --! Number of header checked to know wether the lock is lost or not
c_requiredTrueHeader : integer; --! Number of true header required to go in locked state
c_bitslip_mindly : integer := 1; --! Number of clock cycle required WHEN asserting the bitslip SIGNAL
c_bitslip_waitdly : integer := 40; --! Number of clock cycle required before being back in a stable state
-- Bitslip expert parameters for fixed latency applications - EBSM
c_resetOnEven : integer := 0; --! Reset on even bitslip (1: Enabled/ 0: disabled)
c_resetDuration : integer := 10 --! Reset duration (in clk_freeRunningClk_i periods)
);
PORT (
-- Clock and reset
clk_freeRunningClk_i : in std_logic;
uplinkClk_i : in std_logic; --! Input clock (Rx USEr clock from transceiver)
uplinkClkOutEn_o : out std_logic; --! Clock enable to be USEd in the USEr's logic
uplinkRst_n_i : in std_logic; --! Uplink reset SIGNAL (Rx ready from the transceiver)
-- Input
mgt_word_o : in std_logic_vector((c_mgtWordWidth-1) downto 0); --! Input frame coming from the MGT
-- Data
USErData_o : out std_logic_vector(229 downto 0); --! User output (decoded data). The payload size varies depENDing on the
--! datarate/FEC configuration:
--! * *FEC5 / 5.12 Gbps*: 112bit
--! * *FEC12 / 5.12 Gbps*: 98bit
--! * *FEC5 / 10.24 Gbps*: 230bit
--! * *FEC12 / 10.24 Gbps*: 202bit
EcData_o : out std_logic_vector(1 downto 0); --! EC field value received from the LpGBT
IcData_o : out std_logic_vector(1 downto 0); --! IC field value received from the LpGBT
-- Control
bypassInterleaver_i : in std_logic; --! Bypass uplink interleaver (test purpose only)
bypassFECEncoder_i : in std_logic; --! Bypass uplink FEC (test purpose only)
bypassScrambler_i : in std_logic; --! Bypass uplink scrambler (test purpose only)
-- Transceiver control
mgt_bitslipCtrl_o : out std_logic; --! Control the Bitslib/RxSlide PORT of the Mgt
-- Fixed-latency applications
rst_mgtctrler_i : in std_logic; --! Rst the "reset on even" controller
rst_rstoneven_o : out std_logic; --! Output reset asserted
-- Status
dataCorrected_o : out std_logic_vector(229 downto 0); --! Flag allowing to know which bit(s) were toggled by the FEC
IcCorrected_o : out std_logic_vector(1 downto 0); --! Flag allowing to know which bit(s) of the IC field were toggled by the FEC
EcCorrected_o : out std_logic_vector(1 downto 0); --! Flag allowing to know which bit(s) of the EC field were toggled by the FEC
rdy_o : out std_logic --! Ready SIGNAL from the uplink decoder
);
END component lpgbtfpga_uplink_fixed;
component prbs_chk is
generic (
g_GOOD_FRAME_TO_LOCK : integer := 15 ; --! Number of correct frames predicted for PRBS to go locked (g_GOOD_FRAME_TO_LOCK+2)
g_BAD_FRAME_TO_UNLOCK : integer := 5 ; --! Number of wrong received frames for PRBS to go unlocked (g_BAD_FRAME_TO_UNLOCK+2)
g_PARAL_FACTOR : integer := 254 ; --! Size of parallel bus: it is assumed in this implementation that the size of the parallel bus is bigger than the length of the polynomial
g_PRBS_POLYNOMIAL : std_logic_vector := "11000001" --! Notation: x^7 + x^6 + 1 (PRBS-7)
);
port (
clk_i : in std_logic; --! clock input
reset_i : in std_logic; --! active high sync. reset <--- N ---> ____ ____ ____ ____
en_i : in std_logic; --! enable input ______/ \_____/ \_____/ \_____/ \_____/ \_____/
data_i : in std_logic_vector(g_PARAL_FACTOR-1 downto 0); --! Input data X D1 X D2 X D3 X D4-error X D5 X
data_o : out std_logic_vector(g_PARAL_FACTOR-1 downto 0); --! PRBS output expected data X D0 X D1 X D2 X D3 X D4____X____ - Latency is 2N cycles
error_o : out std_logic; --! PRBS Frame error ______________________________________________________/ \ - Kept to one for the whole duration; Latency is 2N+1 cycles
locked_o : out std_logic --! PRBS locked <-------- 2N ---------> <-+1->
);
end component prbs_chk;
begin
--! ----------------------------------- Clock process -----------------------------------
p_clk_sys : process
begin
while (TEST_BENCH_STATUS /= " FINISHED ") loop
common_clk_sys <= '0';
wait for c_CLOCK_SYS_PERIOD/2;
common_clk_sys <= '1';
wait for c_CLOCK_SYS_PERIOD/2;
end loop;
wait;
end process;
p_clk_mgt : process
begin
while (TEST_BENCH_STATUS /= " FINISHED ") loop
common_clk_mgt <= '0';
wait for c_CLOCK_MGT_PERIOD/2;
common_clk_mgt <= '1';
wait for c_CLOCK_MGT_PERIOD/2;
end loop;
wait;
end process;
-----------------------------------------------------------------------------------------
--! --------------------------------- PRBS generator Tx ---------------------------------
p_prbsgen_strobe : process(common_clk_mgt)
begin
if(rising_edge(common_clk_mgt)) then
if(prbsgen_reset = '1') then
prbsgen_strobe_cntr <= 0;
prbsgen_strobe <= '0';
prbsgen_load <= '1';
else
prbsgen_load <= '0';
if(prbsgen_strobe_cntr = c_clockRatio-1) then
prbsgen_strobe_cntr <= 0;
prbsgen_strobe <= '1';
else
prbsgen_strobe_cntr <= prbsgen_strobe_cntr+1;
prbsgen_strobe <= '0';
end if;
end if;
end if;
end process;
cmp_prbs_gen : prbs_gen
generic map(
g_PARAL_FACTOR => c_PRBS_FRAME_WIDTH,
g_PRBS_POLYNOMIAL => c_PRBS_POLYNOMIAL
)
port map(
clk_i => common_clk_mgt,
en_i => prbsgen_strobe,
reset_i => prbsgen_reset ,
seed_i => prbsgen_seed ,
load_i => prbsgen_load ,
data_o => prbsgen_frame ,
data_valid_o => prbsgen_data_valid
);
-----------------------------------------------------------------------------------------
--! ------------------------------------ lpGBT-FE Tx ------------------------------------
Tx_reset <= prbsgen_reset;
Tx_tx_strobe <= prbsgen_data_valid;
--Tx_tx_data(Tx_tx_data'left downto g_PAYLOAD_LENGTH) <= (others => '0');
Tx_tx_data(g_PAYLOAD_LENGTH-1 downto 0) <= prbsgen_frame(g_PAYLOAD_LENGTH-1 downto 0);
Tx_tx_ec <= prbsgen_frame(g_PAYLOAD_LENGTH+1 downto g_PAYLOAD_LENGTH);
Tx_tx_ic <= prbsgen_frame(g_PAYLOAD_LENGTH+3 downto g_PAYLOAD_LENGTH+2);
cmp_lpgbt_fe_tx : lpgbt_fe_tx
generic map(
g_MGT_WORD_WIDTH => c_mgtWordWidth,
g_DATA_RATE => g_DATARATE ,
g_FEC => g_FEC
)
port map(
reset_i => Tx_reset ,
mgt_clock_i => common_clk_mgt ,
tx_strobe_i => Tx_tx_strobe ,
tx_data_i => Tx_tx_data ,
tx_ec_i => Tx_tx_ec ,
tx_ic_i => Tx_tx_ic ,
tx_word_o => Tx_tx_word ,
scrambler_bypass_i => Tx_scrambler_bypass ,
interleaver_bypass_i => Tx_interleaver_bypass,
tx_error_i => Tx_tx_error
);
-----------------------------------------------------------------------------------------
--! ------------------------ Rx MGT high-level model for testing -------------------------
channel_rx_data(2*c_mgtWordWidth-1 downto c_mgtWordWidth) <= Tx_tx_word(c_mgtWordWidth-1 downto 0) when rising_edge(common_clk_mgt);
channel_rx_data(c_mgtWordWidth-1 downto 0) <= channel_rx_data(2*c_mgtWordWidth-1 downto c_mgtWordWidth) when rising_edge(common_clk_mgt);
channel_bitslide_r <= Rx_mgt_bitslipCtrl when rising_edge(common_clk_mgt);
channel_rx_frame_reset_phy <= Rx_rst_rstoneven when rising_edge(common_clk_mgt);
channel_rx_frame_reset_phy_r <= channel_rx_frame_reset_phy when rising_edge(common_clk_mgt);
p_rxslide : process is
variable seed1 : positive;
variable seed2 : positive;
variable x : real;
begin
while (TEST_BENCH_STATUS /= " FINISHED ") loop
wait until rising_edge(common_clk_mgt);
if(channel_reset='1' or channel_rx_frame_reset_phy='1') then
uniform(seed1, seed2, x);
channel_ready <= '0';
channel_bitslip_position <= integer(floor(real(c_mgtWordWidth)*x));
elsif(channel_bitslide_r='0' and Rx_mgt_bitslipCtrl='1') then
channel_ready <= '1';
channel_bitslip_position <= (channel_bitslip_position+1) mod c_mgtWordWidth;
else
channel_ready <= '1';
end if;
end loop;
wait;
end process;
channel_data <= channel_rx_data(c_mgtWordWidth-1 + channel_bitslip_position downto channel_bitslip_position) when rising_edge(common_clk_mgt);
-----------------------------------------------------------------------------------------
--! ----------------------------------- lpGBT-FPGA Rx -----------------------------------
Rx_uplinkRst_n <= channel_ready;
Rx_mgt_word <= channel_data ;
cmp_lpgbtfpga_uplink_fixed : lpgbtfpga_uplink_fixed
generic map(
-- General configuration
DATARATE => g_DATARATE ,
FEC => g_FEC ,
-- Expert parameters
c_multicyleDelay => c_multicyleDelay ,
c_clockRatio => c_clockRatio ,
c_mgtWordWidth => c_mgtWordWidth ,
c_allowedFalseHeader => c_allowedFalseHeader ,
c_allowedFalseHeaderOverN => c_allowedFalseHeaderOverN,
c_requiredTrueHeader => c_requiredTrueHeader ,
c_bitslip_mindly => c_bitslip_mindly ,
c_bitslip_waitdly => c_bitslip_waitdly ,
-- Bitslip expert parameters for fixed latency applications - EBSM
c_resetOnEven => c_resetOnEven ,
c_resetDuration => c_resetDuration
)
port map(
-- Clock and reset
clk_freeRunningClk_i => common_clk_sys ,
uplinkClk_i => common_clk_mgt ,
uplinkClkOutEn_o => Rx_uplinkClkOutEn ,
uplinkRst_n_i => Rx_uplinkRst_n ,
-- Input
mgt_word_o => Rx_mgt_word ,
-- Data
USErData_o => Rx_USErData ,
EcData_o => Rx_EcData ,
IcData_o => Rx_IcData ,
-- Control
bypassInterleaver_i => Rx_bypassInterleaver,
bypassFECEncoder_i => Rx_bypassFECEncoder ,
bypassScrambler_i => Rx_bypassScrambler ,
-- Transceiver control
mgt_bitslipCtrl_o => Rx_mgt_bitslipCtrl ,
-- Fixed-latency applications
rst_mgtctrler_i => Rx_rst_mgtctrler,
rst_rstoneven_o => Rx_rst_rstoneven,
-- Status
dataCorrected_o => Rx_dataCorrected ,
IcCorrected_o => Rx_IcCorrected ,
EcCorrected_o => Rx_EcCorrected ,
rdy_o => Rx_rdy
);
-----------------------------------------------------------------------------------------
--! ---------------------------------- PRBS checker Rx ----------------------------------
prbschk_reset <= not Rx_rdy ;
prbschk_strobe <= Rx_uplinkClkOutEn ;
prbschk_frame <= Rx_IcData & Rx_EcData & Rx_USErData(g_PAYLOAD_LENGTH-1 downto 0) ;
cmp_prbs_chk : prbs_chk
generic map(
g_GOOD_FRAME_TO_LOCK => 15 ,
g_BAD_FRAME_TO_UNLOCK => 20 ,
g_PARAL_FACTOR => c_PRBS_FRAME_WIDTH,
g_PRBS_POLYNOMIAL => c_PRBS_POLYNOMIAL
)
port map(
clk_i => common_clk_mgt,
reset_i => prbschk_reset ,
en_i => prbschk_strobe,
data_i => prbschk_frame ,
data_o => prbschk_gen ,
error_o => prbschk_error ,
locked_o => prbschk_locked
);
-----------------------------------------------------------------------------------------
--! Stimulis -----------------------------------------------------------------
p_stimulis : process is
-- Inject burst error
procedure INJECT_BURST_ERROR(size_burst : integer) is
variable v_frame_width : integer := Tx_tx_error'length;
begin
if(g_DATARATE = DATARATE_10G24) then
v_frame_width := Tx_tx_error'length;
else
v_frame_width := Tx_tx_error'length/2;
end if;
for i in 0 to v_frame_width-size_burst loop
wait until rising_edge(Tx_tx_strobe);
Tx_tx_error <= (size_burst - 1 + i downto i => '1', others => '0');
wait until rising_edge(common_clk_mgt);
wait until rising_edge(Tx_tx_strobe);
Tx_tx_error <= (others => '0');
wait until rising_edge(common_clk_mgt);
wait until rising_edge(Tx_tx_strobe);
wait until rising_edge(common_clk_mgt);
end loop;
wait until rising_edge(Tx_tx_strobe);
Tx_tx_error <= (others => '0');
wait until rising_edge(common_clk_mgt);
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
end INJECT_BURST_ERROR;
procedure RESET_TEST(number_resets : integer; wait_locked_cycles : integer) is
variable seed1 : positive;
variable seed2 : positive;
variable x : real;
variable reset_wait : integer;
begin
for i in 0 to number_resets-1 loop
wait until rising_edge(common_clk_mgt);
uniform(seed1, seed2, x);
reset_wait := (integer(floor(real(c_mgtWordWidth)*x)) + 1);
channel_reset <= '1';
wait for reset_wait*c_CLOCK_SYS_PERIOD;
wait until rising_edge(common_clk_mgt);
-- Channel Reset release
channel_reset <= '0';
wait until rising_edge(prbschk_locked);
wait for wait_locked_cycles*c_CLOCK_SYS_PERIOD;
wait until rising_edge(common_clk_mgt);
channel_reset <= '1';
wait until falling_edge(prbschk_locked);
end loop;
end RESET_TEST;
begin
--! Basic test bench to observe waveforms
TEST_BENCH_STATUS <= " RESET ";
-- Tx reset and channel reset
prbsgen_reset <= '1';
channel_reset <= '1';
Rx_rst_mgtctrler <= '1';
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
-- Tx reset release
prbsgen_reset <= '0';
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
-- Channel Reset release
channel_reset <= '0';
Rx_rst_mgtctrler <= '0';
wait until rising_edge(prbschk_locked);
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
-- Inject some errors which should be always correctable for FEC5-10G (burst of 6 consecutive bits)
TEST_BENCH_STATUS <= " INJECT CORRECTABLE ERROR";
INJECT_BURST_ERROR(6);
TEST_BENCH_STATUS <= " RESET ERROR COUNTERS ";
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
-- Inject some errors which should not be always correctable for FEC5-10G (7 consecutive bits)
TEST_BENCH_STATUS <= "INJECT NCORRECTABLE ERROR";
INJECT_BURST_ERROR(7);
TEST_BENCH_STATUS <= " RESET ERROR COUNTERS ";
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
-- Bypass FEC and check
Tx_scrambler_bypass <= '0';
Tx_interleaver_bypass <= '0';
Rx_bypassInterleaver <= '0';
Rx_bypassFECEncoder <= '1';
Rx_bypassScrambler <= '0';
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
TEST_BENCH_STATUS <= " FEC BYPASS ";
INJECT_BURST_ERROR(1);
TEST_BENCH_STATUS <= " RESET ERROR COUNTERS ";
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
-- Bypass Scrambler
Tx_scrambler_bypass <= '1';
Tx_interleaver_bypass <= '0';
Rx_bypassInterleaver <= '0';
Rx_bypassFECEncoder <= '0';
Rx_bypassScrambler <= '1';
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
TEST_BENCH_STATUS <= " SCRAMBLER BYPASS ";
INJECT_BURST_ERROR(1);
TEST_BENCH_STATUS <= " RESET ERROR COUNTERS ";
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
-- Bypass Interleaver
Tx_scrambler_bypass <= '0';
Tx_interleaver_bypass <= '1';
Rx_bypassInterleaver <= '1';
Rx_bypassFECEncoder <= '0';
Rx_bypassScrambler <= '0';
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
TEST_BENCH_STATUS <= " INTERLEAVER BYPASS ";
INJECT_BURST_ERROR(1);
TEST_BENCH_STATUS <= " RESET ERROR COUNTERS ";
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
Tx_scrambler_bypass <= '0';
Tx_interleaver_bypass <= '0';
Rx_bypassInterleaver <= '0';
Rx_bypassFECEncoder <= '0';
Rx_bypassScrambler <= '0';
wait for 100*c_CLOCK_MGT_PERIOD;
wait until rising_edge(common_clk_mgt);
-- Reset test
TEST_BENCH_STATUS <= " RESET TEST ";
RESET_TEST(5, 1000);
TEST_BENCH_STATUS <= " FINISHED ";
wait;
end process;
TEST_BENCH_STATUS_O <= TEST_BENCH_STATUS;
------------------------------------------------------------------------------
--! Test Monitor -------------------------------------------------------------
p_monitor : process is
variable v_monitor_fec_corrected_cntr : integer;
variable v_monitor_prbs_error_cntr : integer;
begin
while(TEST_BENCH_STATUS /= " FINISHED ") loop
wait until rising_edge(common_clk_mgt);
if(TEST_BENCH_STATUS /= " RESET ERROR COUNTERS " and TEST_BENCH_STATUS /= " RESET ") then
if(prbschk_strobe='1' and prbschk_error='1') then
v_monitor_prbs_error_cntr := v_monitor_prbs_error_cntr+1; -- frame errors
end if;
if(Rx_uplinkClkOutEn='1') then
for i in 0 to g_PAYLOAD_LENGTH-1 loop
if(Rx_dataCorrected(i)='1') then
v_monitor_fec_corrected_cntr := v_monitor_fec_corrected_cntr+1;
end if;
end loop;
for i in 0 to Rx_EcCorrected'left loop
if(Rx_EcCorrected(i)='1') then
v_monitor_fec_corrected_cntr := v_monitor_fec_corrected_cntr+1;
end if;
end loop;
for i in 0 to Rx_IcCorrected'left loop
if(Rx_IcCorrected(i)='1') then
v_monitor_fec_corrected_cntr := v_monitor_fec_corrected_cntr+1;
end if;
end loop;
end if;
else
v_monitor_prbs_error_cntr := 0;
v_monitor_fec_corrected_cntr := 0;
end if;
FECMONITOR_O <= v_monitor_fec_corrected_cntr;
PRBSMONITOR_O <= v_monitor_prbs_error_cntr ;
end loop;
wait;
end process;
------------------------------------------------------------------------------
end architecture tb;
--==============================================================================
-- architecture end
--==============================================================================