From 7e911f269993105c07f1be841946fbe28b3820ec Mon Sep 17 00:00:00 2001 From: ROBBE Patrick <robbe@lal.in2p3.fr> Date: Sun, 27 Jan 2019 17:01:30 +0100 Subject: [PATCH] Add xvcr file --- Python/components/xcvr_comp.py | 988 +++++++++++++++++++++++++++++++++ 1 file changed, 988 insertions(+) create mode 100644 Python/components/xcvr_comp.py diff --git a/Python/components/xcvr_comp.py b/Python/components/xcvr_comp.py new file mode 100644 index 0000000..871fbed --- /dev/null +++ b/Python/components/xcvr_comp.py @@ -0,0 +1,988 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +""" + xcvr_comp.py -- module to handle the transceiver registers managed by the fpga + + Note: + This code will be running on FC + Author + JPC : 24/2/2018 + JPC : 22/05/2018 : Corrected bug in phy calibration + + + +""" +import time, sys +from lli import mem_multi as mem +from fpga_comp import Arria10 +from si534x_comp import Si534x +from eepromat24c_comp import EepromAT24C +from decimal import Decimal + + +class xcvr(object): + """ Class to manage registers of the arria10. + + The mapping of port registers per type of PLL is given as a class dictionnary + of lists of registers addresses. + + Args: + dev (int): + + """ + + add_xcvr = [0x00080000, 0x00090000, 0x000A0000, 0x000B0000, 0x000C0000, 0x000D0000, 0x000E0000, 0x000F0000, 0x00070000] + add_pll = [0x00088000, 0x00098000, 0x000A8000, 0x000B8000, 0x000C8000, 0x000D8000, 0x000E8000, 0x000F8000, 0x00078000] + + + def __init__(self, dev): + """ + Class initialization + + Args: + dev (int): board identifier + + type_pll = 0 :forced to fPLL + = 1 :forced to ATX_PLL + """ + self.dev = dev + self.type_pll = 0 # choose fPLL + + + def calibrate_pll(self, num_pll): + """ + Recalibrate the given ATX or fPLL + + Args: + num_pll (int) : PLL number + + Return + failed : True if calibration failed, False otherwise + + Raises: + ValueError: + for invalid name. + """ + if num_pll > 8: + #print "NUM PLL FORBIDDEN" + return False + pll_add = self.add_pll[num_pll] + timeout = time.time() + 2 # timeout = 2 second + + #### patch PLL direct mode ON + + #print ".patch PLL direct mode ON " + status, val = mem.read(self.dev, pll_add + 0x126*4) + #print val + new_val = val|0x01 +# print new_val + mem.write(self.dev, pll_add + 0x126*4, new_val) + print "..... Start calibrating PLL" + str(num_pll) + #### step 1 +# print ". request user acces " + mem.write(self.dev, pll_add+0x000*4, 0x2) # write 0x2 + #### step 2 +# print ". wait for reconfig_waitrequest to be deasserted " + bool_wait0 = True + while bool_wait0: + status, val = mem.read(self.dev, pll_add+0x280*4) + test_bit = val&0x04 + if test_bit == 0: + bool_wait0 = False +# print ". bus granted to user" + else: + if time.time() > timeout: +# print "********** TIMEOUT **********" + return False + #### step 3 +# print ". start calibration PLL " + status, val = mem.read(self.dev, pll_add + 0x100*4) + if self.type_pll == 0: + new_val = val|0x2 # FPLL PLL +# print ". Targetting PLL type = FPLL" + if self.type_pll == 1: + new_val = val|0x1 # ATX PLL +# print ". Targetting PLL type = ATX" + mem.write(self.dev, pll_add + 0x100*4, new_val) + #### step 4 +# print ". release bus to preSICE" + mem.write(self.dev, pll_add +0x000*4, 0x1) + #### step 5 +# print ". check reset of call_busy signal" + bool_call_busy1 = True + while bool_call_busy1: + status, val = mem.read(self.dev, pll_add +0x280*4) + test_bit = val&0x02 + if test_bit == 0: + bool_call_busy1 = False + print "..... Done " + else: + if time.time() > timeout: + print "..... TIMEOUT during calibration" + return False + ### patch PLL direct mode OFF +# print ".patch PLL direct mode OFF " + status, val = mem.read(self.dev, pll_add + 0x126*4) + new_val = val&0xfe + mem.write(self.dev, pll_add + 0x126*4, new_val) + ### check pll is locked + status, message = self.check_pll_locked(num_pll) + return status, message + + def calibrate_pll_all(self): + """ + Recalibrate all the ATX or fPLL + """ + nb_plls = self.get_number_of_links() / 6 + for pll in range(0, nb_plls): + self.calibrate_pll(pll) + + def check_pll_locked(self, num_pll): + """ + Check if ATX or fPLL is locked + + Args: + num_pll (int): pll number + + return: + status (bool): 1 if pll locked, 0 if not + message (str): explicit message + """ + if num_pll > 8: + #print "NUM PLL FORBIDDEN" + return False, "" + pll_add = self.add_pll[num_pll] + check_lock = False + timeout = time.time() + 2 # timeout = 2 second + #### Test PLL locked +# print ". check PLL" + str(num_pll) + " lock status" + bool_call_busy2 = True + while bool_call_busy2: + status, val = mem.read(self.dev, pll_add + 0x280*4)#0x280 + test_bit = val&0x01 + if test_bit == 1: + bool_call_busy2 = False + #print " PLL" + str(num_pll) + " is locked" + check_lock = True + #print + #print + return check_lock, "PLL" + str(num_pll) + " is locked" #renvoie 1 pour valider la Qprossbar + message + else: + if time.time() > timeout: +# print "********** PLL" + str(num_pll) + " TIMEOUT: PLL NOT LOCKED or BAD ADRESS PLL or UNUSED PLL **********" + return False, "PLL" + str(num_pll) + " is not locked :timeout" + + def check_pll_locked_all(self): + """ + Check if all ATX or fPLL are locked + + return: + status (bool): 1 if all pll are locked, 0 if not + """ + nb_plls = get_number_of_links()/6 + status = 1 + for pll in range(0, nb_plls): + if check_pll_locked(pll) == False: + status = 0 + return status + + + def calibrate_phy(self, num_phy, channel): + """ + Recalibrate the given phy. + + Args: + num_phy (int): phy number (0 to 8) + channel (int): channel number (0 to 5) + + Raises: + ValueError: + for invalid name. + """ + if num_phy > 7: + print "NUM GBT FORBIDDEN" + return False + gbt_add = self.add_xcvr[num_phy] + channel * 0x1000 + timeout = time.time() + 2 # timeout = 2 second + # print ".... Start calibration GBT" + str(num_phy) + ",Channel", + ### Step 1 + # print ". request user acces" + mem.write(self.dev, gbt_add + 0x000 * 4, 0x2) + ### Step 2 + # print ". wait for reconfig_waitrequest to be deasserted " + bool_wait1 = True + while bool_wait1: + status, val = mem.read(self.dev, gbt_add + 0x281 * 4) + test_bit = val & 0x04 + # print hex(test_bit) + if test_bit == 0: + bool_wait1 = False + # print ". bus granted to user" + else: + print ". busy" + if time.time() > timeout: + print "********** TIMEOUT GBT" + str(num_phy) + " **********" + return 0 + ### Step 3 + # print "Configure PMA Calibration" + # status, val = mem.read(self.dev, gbt_add + 0x100 * 4) + # pma_cal_val = val | 0x31 + # mem.write(self.dev, gbt_add + 0x100 * 4, pma_cal_val) + # status, val = mem.read(self.dev, gbt_add + 0x100 * 4) + self.rmw_phy(num_phy, channel, 0x100, 0x62, 0x22) + ### Step 4 new CDR bandwidth setting (not used) + ### Step 5 + # print ">>>> RX_cal_busy Disable" + # status, val = mem.read(self.dev, gbt_add + 0x281 * 4) + # val = val | 0xdf + # mem.write(self.dev, gbt_add + 0x281 * 4, val) + # status, val = mem.read(self.dev, gbt_add + 0x281 * 4) + # val = val & 0x20 + # mem.write(self.dev, gbt_add + 0x281 * 4, val) + # print ">>>> RX_cal_busy Enable" + # print ">>>> TX_cal_busy Disable" + # status, val = mem.read(self.dev, gbt_add + 0x281 * 4) + # val = val | 0xef + # mem.write(self.dev, gbt_add + 0x281 * 4, val) + # status, val = mem.read(self.dev, gbt_add + 0x281 * 4) + # val = val & 0x10 + # mem.write(self.dev, gbt_add + 0x281 * 4, val) + # print ">>>> TX_cal_busy Enable" + # ### Step 6 + # mem.write(self.dev, gbt_add + 0x000 * 4, 0x01) + ### Step 7 + self.rmw_phy(num_phy, channel, 0x281, 0x30, 0x30) + #self.rmw_phy(num_phy, channel, 0x000, 0xFF, 0x01) + # print ".Periodically check *cal_busy" + failed = True + while failed: + status, val = mem.read(self.dev, gbt_add + 0x281 * 4) + test_bit = val & 0x03 + if test_bit == 0: + failed = False + # print ".... Done" + else: + print ". busy" + if time.time() > timeout: + print "********** TIMEOUT GBT" + str(num_phy) + "**********" + break + return failed + + def calibrate_phy_all(self): + """ + Recalibrate all the phys. + + """ + nb_phy = self.get_number_of_links() + for num_phy in range(0, nb_phy/6): + print ".... Start calibration GBT", num_phy, "channel", + for channel in range (0, 6): + if self.calibrate_phy(num_phy, channel) == False: + print channel, + print + print ".... Done" + + + + def dump_phy_registers(self, num_phy): + """ + Read the phy register of all channels at address add on register reg. + + Args: + num_phy (int): phy number (0 to 8) + + Raises: + ValueError: + for invalid name. + + """ + add = self.add_xcvr[num_phy] + for reg in (0x200, 0x204, 0x205, 0x210, 0x211, 0x212, 0x213, 0x2E1, 0x2E2, 0x280): + print "adresse ", hex(reg), "=", + print hex(add + 4 * reg), + for channel in range(6): ## display same register for 6 channels + status, val = mem.read(self.dev, add + 4 * reg + channel * 0x1000) + print "%#04x" % val, ## display 2 characters in hexa + print + + def dump_prbs_registers(self, num_phy): + """ + Read the phy register of all channels at address add on register reg. + + Args: + num_phy (int): phy number (0 to 8) + + Raises: + ValueError: + for invalid name. + + """ + add = self.add_xcvr[num_phy] + for reg in (0x007, 0x008, 0x006, 0x110, 0x00B, 0x00C, 0x13F, 0x00A, 0x300): + print "adresse %#05x" % reg, "=", + print "%#04x" % (add + 4 * reg), + for channel in range(6): ## display same register for 6 channels + status, val = mem.read(self.dev, add + 4 * reg + channel * 0x1000) + print "%#04x" % val, ## display 2 characters in hexa + print + + def read_phy_register(self, num_phy, channel, reg): + """ + Read a phy register + + Args: + num_phy : phy number (0 to 8) + channel : channel number (0 to 5) + reg : register address (0x000 to 0x340) + + Returns + val : read value + + """ + add = self.add_xcvr[num_phy] + status, val = mem.read(self.dev, add + 4 * reg + channel * 0x1000) + return val + + def read_pll_register(self, num_phy, reg): + """ + Read a pll register + + Args: + num_phy : phy number (0 to 8) + reg : register address (0x000 to 0x340) + + Returns + val : read value + + """ + add = self.add_pll[num_phy] + status, val = mem.read(self.dev, add + 4 * reg) + return val + + def write_phy_register(self, num_phy, channel, reg, data): + """ + Write a phy register + + Args: + num_phy : phy number (0 to 8) + channel : channel number (0 to 5) + reg : register address (0x000 to 0x340) + data : data to write + + Return: + Val = value read after write + + """ + add = self.add_xcvr[num_phy] + status = mem.write(self.dev, add + 4 * reg + channel * 0x1000, data) + status, val = mem.read(self.dev, add + 4 * reg + channel * 0x1000) + #print "new value is %#04x" % val, ## display 2 characters in hexa + return val + + def write_pll_register(self, num_phy, reg, data): + """ + Write a pll register + + Args: + num_phy : phy number (0 to 8) to which the pll is attached + reg : register address (0x000 to 0x340) + data : data to write + + Return: + Val = value read after write + + """ + add = self.add_pll[num_phy] + status = mem.write(self.dev, add + 4 * reg, data) + status, val = mem.read(self.dev, add + 4 * reg) + #print "new value is %#04x" % val, ## display 2 characters in hexa + return val + + def rmw_phy(self, num_phy, channel, reg, mask, data): + """ + Read modify write a phy register + + Args: + num_phy : phy number (0 to 8) + channel : channel number (0 to 5) + reg : register address (0x000 to 0x340) + mask : each bit set to 1 is written, others are let in same state + data : data to write + + Return: + read_value : read value after write + + """ + val = self.read_phy_register(num_phy, channel, reg) + masked_data = data & mask + masked_val = val & ~mask + new_data = masked_val | masked_data + read_value = self.write_phy_register(num_phy, channel, reg, new_data) + #print "rmw of ", hex(data), "with mask ", hex(mask), "in register ", hex(reg), "initial value was ",hex(val),"masked data is" , hex(masked_data),", new written value is ", hex(new_data) + #print "read value is %#04x" % read_value + return read_value + + def rmw_pll(self, num_phy, channel, reg, mask, data): + """ + Read modify write a phy register + + Args: + num_phy : phy number (0 to 8) + channel : channel number (0 to 5) + reg : register address (0x000 to 0x340) + mask : each bit set to 1 is written, others are let in same state + data : data to write + + Return: + read_value : read value after write + + """ + val = self.read_pll_register(num_phy, channel, reg) + masked_data = data & mask + masked_val = val & ~mask + new_data = masked_val | masked_data + read_value = self.write_pll_register(num_phy, channel, reg, new_data) + #print "rmw of ", hex(data), "with mask ", hex(mask), "in register ", hex(reg), "initial value was ",hex(val),"masked data is" , hex(masked_data),", new written value is ", hex(new_data) + #print "read value is %#04x" % read_value + return read_value + + def read_mask(self, num_phy, channel, reg, mask): + """ + Read a phy register with a mask + + Args: + num_phy : phy number (0 to 8) + channel : channel number (0 to 5) + reg : register address (0x000 to 0x340) + mask : each bit set to 1 is read, other are ignored + + Return: + read_value : read value with mask + + """ + val = self.read_phy_register(num_phy, channel, reg) + masked_data = val & mask + while mask & 1 == 0 : + masked_data = masked_data >> 1 + mask = mask >> 1 + return hex(masked_data) + + def get_status(self, num_phy, channel): + """ + Get most interesting status values for a phy + + Args: + num_phy : phy number (0 to 8) + channel : channel number (0 to 5) + + """ + print "num_phy = ", num_phy, ", channel =", channel + print "test 16a should be 5", self.read_mask(num_phy, channel, 0x16a, 0xf0) + print "rx_is_lockedtodata =", self.read_mask(num_phy, channel, 0x280, 0x1) + print "rx_is_lockedtoref =", self.read_mask(num_phy, channel, 0x280, 0x2) + print "tx_cal_busy =", self.read_mask(num_phy, channel, 0x281, 0x1) + print "rx_cal_busy =", self.read_mask(num_phy, channel, 0x281, 0x2) + print "vod =", self.read_mask(num_phy, channel, 0x109, 0x1f) + return + + + def get_number_of_links(self): + """ + Reads the number of links implemented in the firmware + + Returns: + nb_links : number of links + """ + status, nb_links = mem.read(self.dev, 0x30000) + return nb_links & 0xFF + + def set_serial_loopback_all(self, loopback) : + """ + Set serial_loopback for all detected links + + Args: + loopback (int) : 1 to set internal loopback, 0 to set it off + """ + nb_phy = self.get_number_of_links() + for num_phy in range(0, nb_phy/6): + add = self.add_xcvr[num_phy] + for channel in range (0, 6): + if loopback == 1: + status = mem.write(self.dev, add + 4 * 0x2E1 + channel * 0x1000, 0x01) + else: + status = mem.write(self.dev, add + 4 * 0x2E1 + channel * 0x1000, 0x00) + + + def start_check_serial_loop(self, num_phy, channel): + """ + Launch a prbs in loop back mode and check errors + + Args: + num_phy (int) : phy number (0 to 8) + channel (int) : channel number (0 to 5) + loopback (int) : 1 to run the test in internal loopback, 0 to run it in external loopback + + """ + # set prbs31 generator pattern + self.rmw_phy(num_phy, channel, 0x07, 0xF0, 0x00) + self.rmw_phy(num_phy, channel, 0x08, 0x10, 0x10) + + # set prbs31 verifier pattern + self.rmw_phy(num_phy, channel, 0x0B, 0xF0, 0x00) + self.rmw_phy(num_phy, channel, 0x0C, 0x01, 0x01) + + # Set PRBS Generator + # PMA data output is prbs pattern + self.rmw_phy(num_phy, channel,0x06, 0x0F, 0x04) # enable PRBS9 in 64 bits mode, tx pma data sel = prbs pattern + # TX PCS PRBS Gen clock enable set to 1 + self.rmw_phy(num_phy, channel,0x06, 0x40,0x40) # enable Tx PRBS generator clock + # set serializer to 64-bit + self.rmw_phy(num_phy, channel, 0x110, 0x07, 0x03) # set mode = 64 bits + + # set Xn to not bounded" + self.rmw_phy(num_phy, channel, 0x111, 0x1F, 0x18) # set Xn to "not bonded" + + # Set PRBS Checker + # Route PRBS to data path: + # set rx_prbs_mode to 10g mode + self.rmw_phy(num_phy, channel, 0xB, 0x02, 0x02) # rx PRBS mode = 10G + # rx_prbs_force_signal_ok + self.rmw_phy(num_phy, channel, 0xC, 0x02, 0x02) # force signal_ok to PRBS + # prbs9_dwidth set to prbs9_64b + self.rmw_phy(num_phy, channel, 0xC, 0x08,0x00) # enable PRBS9 in 64 bits mode + # Set deser_factor to 64-bit + self.rmw_phy(num_phy, channel, 0x13F, 0x0F, 0x0E) # set deserialization factor to 64 bits + + # TX PCS PRBS Gen clock enable set to on + self.rmw_phy(num_phy, channel, 0xA, 0x80, 0x80) + + # Counter enable (enables both error and bit counters) + self.rmw_phy(num_phy, channel, 0x300, 0x01, 0x01) + + def start_check_serial_loop_all(self, loopback): + """ + Launch a prbs in loop back mode and check errors + + Args: + loopback (int) : 1 to run the test in internal loopback, 0 to run it in external loopback + + """ + #get number of links + nb_links = self.get_number_of_links() + print "number of links is", nb_links + # set loopback mode + self.set_serial_loopback_all(loopback) + for num_phy in range(0, nb_links/6): + for num_channel in range(0,6): + self.start_check_serial_loop(num_phy, num_channel) + + def check_serial_loopback(self, num_phy, channel): + """ + Check if the serial loop back mode is set + + Args: + num_phy (int) : phy number (0 to 8) + channel (int) : channel number (0 to 5) + + Returns: + 1 if true + 0 if false + """ + status = self.read_mask(num_phy, channel, 0x2E1, 0x01) + return status + + def check_status(self, num_phy, channel): + """ + Check status of prbs registers + + Args: + num_phy : phy number (0 to 8) + channel : channel number (0 to 5) + + """ + print "reg 0x007: ", hex(self.read_phy_register(0, 0, 0x07)) + print "reg 0x008: ", hex(self.read_phy_register(0, 0, 0x08)) + + # set prbs31 verifier pattern + print "reg 0x00B: ", hex(self.read_phy_register(0, 0, 0x0B)) + print "reg 0x00C: ", hex(self.read_phy_register(0, 0, 0x0C)) + + # SET GENERATOR + # PMA data output is prbs pattern + print "reg 0x006: ", hex(self.read_phy_register(0, 0, 0x06)) + # TX PCS PRBS Gen clock enable set to 1 + print "reg 0x006: ", hex(self.read_phy_register(0, 0, 0x06)) + # set serializer to 64-bit + print "reg 0x110: ", hex(self.read_phy_register(0, 0, 0x110)) + + # Xn not bounded + print "reg 0x111: ", hex(self.read_phy_register(0, 0, 0x111)) + + # Route PRBS to data path: + # set rx_prbs_mode to 10g mode + print "reg 0x00B: ", hex(self.read_phy_register(0, 0, 0xB)) + # rx_prbs_force_signal_ok + print "reg 0x00C: ", hex(self.read_phy_register(0, 0, 0xC)) + # prbs9_dwidth set to prbs9_64b + print "reg 0x00C: ", hex(self.read_phy_register(0, 0, 0xC)) + # Set deser_factor to 64-bit + print "reg 0x13F: ", hex(self.read_phy_register(0, 0, 0x13F)) + + # TX PCS PRBS Gen clock enable set to on + print "reg 0x00A: ", hex(self.read_phy_register(0, 0, 0xA)) + + # Counter enable (enables both error and bit counters) + print "reg 0x300: ", hex(self.read_phy_register(0, 0, 0x300)) + + def check_prbs_ready(self, num_phy, channel): + """ + Check if the prbs checker has had sufficient time to lock to the incoming pattern + + Args: + num_phy (int) : phy number (0 to 8) + channel (int) : channel number (0 to 5) + + Returns: + 1 if true + 0 if false + """ + status = self.read_phy_register(num_phy, channel, 0x300) >> 3 & 0x0001 + return status + + def check_prbs_ready_all(self): + """ + Check if all the prbs checkers had had sufficient time to lock to the incoming pattern + + Returns: + 1 if true + 0 if false + """ + global_status = 1 + nb_phy = self.get_number_of_links() + while global_status == 0: + global_status = 1 + for num_phy in range(0, nb_phy / 6): + for channel in range(0, 6): + status = self.read_phy_register(num_phy, channel, 0x300) >> 3 & 0x0001 + glogal_status = global_status and status + print num_phy, channel, status, global_status + return global_status + + def reset_prbs_counters(self, num_phy, channel): + """ + Reset the prbs counters + + Args: + num_phy (int) : phy number (0 to 8) + channel (int) : channel number (0 to 5) + + """ + self.rmw_phy(num_phy, channel, 0x300, 0x02, 0x02) + self.rmw_phy(num_phy, channel, 0x300, 0x02, 0x00) + + def reset_prbs_counters_all(self): + """ + Reset all the prbs counters + """ + nb_phy = self.get_number_of_links() + for num_phy in range(0, nb_phy / 6): + for channel in range(0, 6): + self.rmw_phy(num_phy, channel, 0x300, 0x02, 0x02) + self.rmw_phy(num_phy, channel, 0x300, 0x02, 0x00) + + def snapshot_counters(self, num_phy, channel): + """ + Makes a snapshot of the prbs counters + + Args: + num_phy (int) : phy number (0 to 8) + channel (int) : channel number (0 to 5) + + + """ + print "Takes a snapshot of registers", hex(self.rmw_phy(num_phy, channel, 0x300, 0x04, 0x04)), hex(self.rmw_phy(num_phy, channel, 0x300, 0x04, 0x00)) + + def snapshot_counters_all(self): + """ + Makes a snapshot of all the prbs counters + + """ + print "Takes a snapshot of prbs counters" + nb_phy = self.get_number_of_links() + for num_phy in range(0, nb_phy / 6): + for channel in range(0, 6): + self.rmw_phy(num_phy, channel, 0x300, 0x04, 0x04) + self.rmw_phy(num_phy, channel, 0x300, 0x04, 0x00) + + + def read_ber(self, num_phy, channel): + """ + Calculate the BER + + Args: + num_phy (int) : phy number (0 to 8) + channel (int) : channel number (0 to 5) + Returns: + Nb_bits (int) : number of bits transmitted + Nb_errors (int) : number of errors detected + + """ + Nb_errors = self.read_phy_register(num_phy, channel, 0x301) + \ + self.read_phy_register(num_phy, channel, 0x302) * 256 + \ + self.read_phy_register(num_phy, channel, 0x303) * 256 * 256 + \ + self.read_phy_register(num_phy, channel, 0x304) * 256 * 256 * 256 + \ + self.read_phy_register(num_phy, channel, 0x305) * 256 * 256 * 256 * 256 + \ + self.read_phy_register(num_phy, channel, 0x306) * 256 * 256 * 256 * 256 * 256 + \ + self.read_phy_register(num_phy, channel, 0x307) * 256 * 256 * 256 * 256 * 256 * 256 + Nb_words = self.read_phy_register(num_phy, channel, 0x30D) + \ + self.read_phy_register(num_phy, channel, 0x30E) * 256 + \ + self.read_phy_register(num_phy, channel, 0x30F) * 256 * 256 + \ + self.read_phy_register(num_phy, channel, 0x310) * 256 * 256 * 256 + \ + self.read_phy_register(num_phy, channel, 0x311) * 256 * 256 * 256 * 256 + \ + self.read_phy_register(num_phy, channel, 0x312) * 256 * 256 * 256 * 256 * 256 + \ + self.read_phy_register(num_phy, channel, 0x313) * 256 * 256 * 256 * 256 * 256 * 256 + tcs_pma_width = 20 + Nb_bits = tcs_pma_width * Nb_words + return Nb_bits, Nb_errors + + def read_ber_all(self): + """ + Calculate the BER for all channels + + Returns: + list_ber{{Nb_bits (int) : Nb_errors (int)} + where Nb_bits = Number of transmitted bits + Nb_errors = Number of errors detected + """ + list_nb_bits = [] + list_nb_errors = [] + nb_phy = self.get_number_of_links() + for num_phy in range(0, nb_phy / 6): + for channel in range(0, 6): + Nb_bits, Nb_errors = self.read_ber(num_phy, channel) + list_nb_bits.append(Nb_bits) + list_nb_errors.append(Nb_errors) + list_ber = zip(list_nb_bits, list_nb_errors) + # print list_ber + return list_ber + + + def tx_digital_reset(self, num_phy, channel, val): + """ + Digital reset of the transmitter + + Args: + num_phy (int): phy number (0 to 8) + channel (int): channel number (0 to 5) + val (int) : 1 to assert reset, 0 to clear reset + + """ + if val == 1: + self.rmw_phy(num_phy, channel, 0x2E2, 0xF8, 0xF8) + else: + self.rmw_phy(num_phy, channel, 0x2E2, 0xF8, 0xF0) + + + def rx_digital_reset(self, num_phy, channel, val): + """ + Digital reset of the receiver + + Args: + num_phy : phy number (0 to 8) + channel : channel number (0 to 5) + val : 1 to assert reset, 0 to clear reset + + """ + if val == 1: + self.rmw_phy(num_phy, channel, 0x2E2, 0xF2, 0xF2) + else: + self.rmw_phy(num_phy, channel, 0x2E2, 0xF2, 0xF0) + + + def tx_analog_reset(self, num_phy, channel, val): + """ + Digital reset of the transmitter + + Args: + num_phy : phy number (0 to 8) + channel : channel number (0 to 5) + val : 1 to assert reset, 0 to clear reset + + """ + if val == 1: + self.rmw_phy(num_phy, channel, 0x2E2, 0xF4, 0xF4) + else: + self.rmw_phy(num_phy, channel, 0x2E2, 0xF4, 0xF0) + + + def rx_analog_reset(self, num_phy, channel, val): + """ + Digital reset of the receiver + + Args: + num_phy : phy number (0 to 8) + channel : channel number (0 to 5) + val : 1 to assert reset, 0 to clear reset + + """ + if val == 1: + self.rmw_phy(num_phy, channel, 0x2E2, 0xF1, 0xF1) + else: + self.rmw_phy(num_phy, channel, 0x2E2, 0xF1, 0xF0) + + + + +def main(): + + fpga = Arria10(0) + trans = xcvr(0) + for phy in range(0, 8) : + trans.dump_phy_registers(phy) + print "=============================================================================================" + + fpga.clear_reset_gbt() + trans.calibrate_pll(0) + trans.calibrate_phy(0, 0) + time.sleep(0.1) + loopback = 1 + trans.set_serial_loopback_all(loopback) + trans.start_check_serial_loop(0, 0) + + trans.check_status(0,0) + print "counter status =", hex(trans.read_phy_register(0, 0, 0x300)) + wait = 0 + while wait == 0: + wait = trans.check_prbs_ready(0, 0) + print wait + time.sleep(1) + print "prbs done = " + trans.reset_prbs_counters(0, 0) + while 1: + trans. snapshot_counters(0, 0) + Nb_bits, Nb_errors = trans.read_ber(0,0) + print "Number of transmitted bits = %.4g" % Nb_bits, ", Nb of errors = %.4g" % Nb_errors, ", BER =", + if Nb_bits != 0: + print " %.4g" % (1. * Nb_errors/Nb_bits) + else: + print + time.sleep(1) + +def main_all(device): + + # Identifying the card + import addresses_comp as const + flash = EepromAT24C(device, const.EEPROM_FPGA_BUS, const.EEPROM_U64_ADD) + print flash.read_identification() + + # Program PLLs + devices = \ + {1: "SI5345_U23", + 2: "SI5345_U48", + 3: "SI5344_U54" + } + ports = \ + {1: [0, 1, 2, 3], + 2: [0, 1, 3, 4, 8], + 3: [0, 1] + } + files = \ + {1: "../data/Si5345-RevD-JIT1_40_jitter1_input0_40MHz-Registers.txt", + 2: "../data/Si5345-RevD-JIT2_40_jitter2_input0_40MHz-Registers.txt", + 3: "../data/Si5344-RevD-TFC_40-Registers.txt" + } + + dev = device # Creates a list of objects with the 3 PLLs + add = 0x68 + pll = [Si534x(dev, bus, add) for bus in devices.keys()] + + + for i in devices.keys(): # Tests the 3 PLLs + print "=========== Programming external PLL ", devices[i], "============" + # pll[i - 1].test(files[i], devices[i], ports[i]) # i-1 because list index starts with 0 + pll[i - 1].program_with_file(files[i], devices[i]) # i-1 because list index starts with 0 + print "..... wait to stabilize" + time.sleep(7) + pll[i-1].clear_lol_flg_bit() + status, val = pll[i - 1].read_loss_of_lock() # i-1 because list index starts with 0 + print devices[i], + if val == True: + print "Loss of lock\n" + else: + print "Locked\n" + + + print "\n=========== Checking PLLs ============" + print"... Loss of lock sticky bit = ", + for i in devices.keys(): # Check the stickybit for the 3 PPLLs + (status, loss_of_lock_flg) = pll[i-1].read_loss_of_lock_flg() + print loss_of_lock_flg, + print + time.sleep(2) + + # Calibrate all PLLs + print "\n=========== Calibrating fPLLs ============" + trans = xcvr(device) + trans.calibrate_pll_all() + + # Calibrate all PHYs + print "\n=========== Calibrating PHYs ============" + trans.calibrate_phy_all() + + # Clear reset to transceivers + print "\n=========== Clearing xcvr reset ============" + fpga = Arria10(device) + fpga.clear_reset_gbt() + print ".... Done" + + # Set internal loopback + print "\n=========== Setting loopback mode ============" + print ".... Internal loopback" + loopback = 1 + + + # Start test + print "\n=========== Starting PRBS test ============" + trans.start_check_serial_loop_all(loopback) + + # Check if all the prbs checkers had had sufficient time to lock to the incoming pattern + print "\n=========== PRBS test ============" + trans.check_prbs_ready_all() + print ".... PRBS checkers locked" + + # Reset error counters + print ".... Reset PRBS counters" + trans.reset_prbs_counters_all() + + print ".... Start test" + elapsed_time = 0 + while 1: + elapsed_time += 1 + print "transmitted bits = ", '%.2E' % Decimal(elapsed_time * 4800000000) + print"Loss of lock sticky bit = ", + for i in devices.keys(): + (status, loss_of_lock_flg) = pll[i-1].read_loss_of_lock_flg() + print loss_of_lock_flg, + print + trans.snapshot_counters_all() + channel = 0 + for link in trans.read_ber_all(): + if link[1] == 0: + print "Channel", '{:>2}'.format(channel), \ + ", bits = ", link[0], \ + ", errors =", '{:>6}'.format(link[1]), \ + ", BER = ", '%.2E' % (Decimal(1)/Decimal((elapsed_time * 4800000000))) + else: + print "Channel", '{:>2}'.format(channel), \ + ", bits = ", link[0], \ + ", errors =", '{:>6}'.format(link[1]), \ + ", >>>>>>>>>>>>>>>>>>>>>>>>> BER = ", '%.2E' % (Decimal(link[1])/Decimal((elapsed_time * 4800000000))) + channel += 1 + time.sleep(1) + + +if __name__ == "__main__": + if (len(sys.argv) > 1): + main_all(int(sys.argv[1])) + else : + main_all(0) -- GitLab