diff --git a/boards/uniboard2b/designs/unb2b_jesd/src/vhdl/unb2b_jesd.vhd b/boards/uniboard2b/designs/unb2b_jesd/src/vhdl/unb2b_jesd.vhd index 53edf7f7716f2d3ffb993a24d602d8c8da21ef1e..8a9c73c57cf06601bb8f2b3b8ff36b0faf98be44 100644 --- a/boards/uniboard2b/designs/unb2b_jesd/src/vhdl/unb2b_jesd.vhd +++ b/boards/uniboard2b/designs/unb2b_jesd/src/vhdl/unb2b_jesd.vhd @@ -87,8 +87,9 @@ ARCHITECTURE str OF unb2b_jesd IS CONSTANT c_fw_version : t_unb2_board_fw_version := (1, 1); CONSTANT c_mm_clk_freq : NATURAL := c_unb2_board_mm_clk_freq_100M; + signal CLK : STD_LOGIC; + --signal PPS : STD_LOGIC; signal jesd204_rx_sysref_n : STD_LOGIC; - signal CLK : STD_LOGIC := '0'; -- System SIGNAL cs_sim : STD_LOGIC; @@ -100,6 +101,7 @@ ARCHITECTURE str OF unb2b_jesd IS SIGNAL st_rst : STD_LOGIC; SIGNAL st_clk : STD_LOGIC; + SIGNAL st_pps : STD_LOGIC; -- PIOs SIGNAL pout_wdi : STD_LOGIC; @@ -200,7 +202,8 @@ BEGIN g_eth_clk_freq => c_unb2_board_eth_clk_freq_125M, g_aux => c_unb2_board_aux, g_factory_image => g_factory_image, - g_protect_addr_range => g_protect_addr_range + g_protect_addr_range => g_protect_addr_range, + g_dp_clk_use_pll => FALSE ) PORT MAP ( -- Clock an reset signals @@ -214,7 +217,7 @@ BEGIN dp_rst => st_rst, dp_clk => st_clk, - dp_pps => OPEN, + dp_pps => st_pps, dp_rst_in => st_rst, dp_clk_in => st_clk, @@ -392,10 +395,12 @@ BEGIN jesd204_rx_link_valid => jesd204_rx_link_valid, jesd204_rx_link_ready => jesd204_rx_link_ready, jesd204_rx_sysref => jesd204_rx_sysref_n, - jesd204_device_clk => jesd204_device_clk + jesd204_device_clk => st_clk ); QSFP_LED(0) <= pll_locked; + CLK <= jesd204_device_clk; + --PPS <= jesd204_rx_sysref; jesd204_rx_sysref_n <= NOT jesd204_rx_sysref; gen_jesd_mon_in : FOR i IN 0 TO 1-1 GENERATE @@ -412,23 +417,23 @@ BEGIN g_technology => g_technology, g_nof_streams => 1, g_data_w => 32, - g_buf_nof_data => 8192, - g_buf_use_sync => FALSE, + g_buf_nof_data => 16384, --8192, + g_buf_use_sync => TRUE, -- when TRUE start filling the buffer at the in_sync, else after the last word was read g_use_rx_seq => FALSE ) PORT MAP ( mm_rst => mm_rst, mm_clk => mm_clk, dp_rst => mm_rst, - dp_clk => jesd204_device_clk, + dp_clk => st_clk, ram_data_buf_mosi => ram_diag_data_buf_jesd_mosi, ram_data_buf_miso => ram_diag_data_buf_jesd_miso, reg_data_buf_mosi => reg_diag_data_buf_jesd_mosi, reg_data_buf_miso => reg_diag_data_buf_jesd_miso, - in_sosi_arr => diag_data_buf_snk_in_arr - --in_sync => jesd204_rx_sysref_n + in_sosi_arr => diag_data_buf_snk_in_arr, + in_sync => st_pps ); END str; diff --git a/boards/uniboard2b/designs/unb2b_jesd/tb/python/util_unb2_jesd.py b/boards/uniboard2b/designs/unb2b_jesd/tb/python/util_unb2_jesd.py new file mode 100644 index 0000000000000000000000000000000000000000..31bf0f5e6d659e3cc3e4b4db67d8085920084b02 --- /dev/null +++ b/boards/uniboard2b/designs/unb2b_jesd/tb/python/util_unb2_jesd.py @@ -0,0 +1,400 @@ +#! /usr/bin/env python +############################################################################### +# +# Copyright (C) 2014 +# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +# +# This program is free software: 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. +# +# This program 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 this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################### + +"""Test case for util_unb2_jesd + +Quickly get started, try this: python util_unb2_jesd.py --unb 1 --fn 0 --seq JESD + +Usage: + + --rep = number of intervals that diagnostics results are verified + --sim targets a running simulation. + +Description: + This test case tests: + - system info + - read sensors + - read ppsh + - write to wdi to force reload from bank 0 + - flash access: write image to bank 1 + - remote update: start image in bank 1 + - link test between ports on the same FPGA (same XO) + - link test between ports on different Uniboards (XO drift) + - stable link after image restart + +""" + +############################################################################### +# System imports +import sys +import signal +import random +import test_case +import node_io +import pi_system_info +import pi_unb2_sens +import pi_unb2_pmbus +import pi_unb2_i2c_hmc +import pi_unb_fpga_sens +import pi_ppsh +import pi_wdi +import pi_epcs +import pi_remu +import pi_eth +import pi_bsn_monitor +import pi_diag_block_gen +import pi_diag_data_buffer +import pi_debug_wave +import matplotlib +matplotlib.use('tkagg') # to make X11 forwarding work +import matplotlib.pyplot as plt +import numpy as np + +from tools import * +from common import * +from pi_common import * + + + +def sign_extend(value, bits): + sign_bit = 1 << (bits - 1) + return (value & (sign_bit - 1)) - (value & sign_bit) + +def test_JESD(tc,io,cmd): + tc.append_log(3, '>>>') + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + tc.append_log(3, '>>>') + + tc.set_section_id('Read - ') + instanceName = 'JESD' + blocksize = 16384 #8196 + Db = pi_diag_data_buffer.PiDiagDataBuffer(tc,io,nofStreams=1,ramSizePerStream=blocksize,instanceName=instanceName) + + ppsh = pi_ppsh.PiPpsh(tc, io) + while tc.repeat != 0: + ppsh.wait_until_pps(vLevel=6) + print 'PPS...' + + db_ram = [] + samples = [] + samplesB = [] + toggle = 0 + databuf = Db.read_data_buffer(streamNr=0,vLevel=5) + for d in databuf[0]: + # is 32 bit and has 2 14-bit samples which are interleaved in time + msb=sign_extend(((d>>18) & 0xffff),14) + lsb=sign_extend(((d>>2) & 0xffff),14) + if toggle==0: + samples.append(np.int16(msb)) + else: + samples.append(np.int16(lsb)) + toggle+=1 + toggle&=1 + + plt.plot(samples[:100]) + plt.show() + + + + +def test_info(tc,io,cmd): + tc.set_section_id('Read System Info - ') + tc.append_log(3, '>>>') + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + tc.append_log(3, '>>>') + + info = pi_system_info.PiSystemInfo(tc, io) + info.read_system_info() + tc.append_log(3, '') + info.read_use_phy() + tc.append_log(3, '') + design_name = info.read_design_name() + tc.append_log(1, '>>> design_name=%s' % design_name) + tc.append_log(3, '') + info.read_stamps() + tc.append_log(3, '') + info.read_design_note() + + expected_design_name = tc.gpString + if expected_design_name != '': + tc.set_section_id('Verify System Info - ') + compared=True + for name in design_name: + if (name != expected_design_name): + tc.set_result('FAILED') + compared=False + tc.append_log(2, '>>> design_name mismatch!! (%s != %s)' % (name,expected_design_name)) + tc.append_log(1, '>>> Verify design_name == %s: %s' % (expected_design_name,compared)) + + + +def read_regmap(tc,io,cmd): + tc.set_section_id('Update REGMAP - ') + info = pi_system_info.PiSystemInfo(tc, io) + tc.append_log(1, '>>> reading REGMAPs') + info.make_register_info() + tc.append_log(1, '>>> reload NodeIO class') + return node_io.NodeIO(tc.nodeImages, tc.base_ip) + + + +def test_sensors(tc,io,cmd): + tc.set_section_id('Read sensors - ') + tc.append_log(3, '>>>') + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + tc.append_log(3, '>>>') + + sens = pi_unb2_sens.PiUnbSens(tc, io) + pmbus = pi_unb2_pmbus.PiUnbSens(tc, io) + + sens.read_unb_sensors() + tc.append_log(3, '') + + pmbus.read_unb_sensors() + tc.append_log(3, '') + + fpga_sens = pi_unb_fpga_sens.PiUnbFpgaSens(tc, io) + fpga_sens.read_fpga_temperature() + + # Calculate floating point value according PMBus lineair +def calc_lin_3bytes(data,mode): + expo = (mode & 0x1F) + if expo > 2**4: + expo = expo - 2**5 + output = (data[1]*256 + data[0]) * 2**expo + return output + + +def test_ppsh(tc,io,cmd): + tc.set_section_id('Read PPSH capture count - ') + tc.append_log(3, '>>>') + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + tc.append_log(3, '>>>') + + Ppsh = pi_ppsh.PiPpsh(tc, io) + Ppsh.read_ppsh_capture_cnt() + tc.append_log(3, '') + + + +def test_wdi(tc,io,cmd): + tc.set_section_id('Reset to image in bank 0 using WDI - ') + tc.append_log(3, '>>>') + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + tc.append_log(3, '>>>') + + Wdi = pi_wdi.PiWdi(tc, io) + Wdi.write_wdi_override() + tc.append_log(3, '') + tc.append_log(3, '>>> Booting...') + tc.sleep(5.0) + + +def test_remu(tc,io,cmd): + tc.set_section_id('REMU start image in bank 1 - ') + tc.append_log(3, '>>>') + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + tc.append_log(3, '>>>') + + dummy_tc = test_case.Testcase('Dummy TB - ', '',logfilename='REMU-log') + dummy_tc.set_result('PASSED') + + Remu = pi_remu.PiRemu(dummy_tc, io) + try: + Remu.write_user_reconfigure() + except: + pass # ignoring FAILED + + if dummy_tc.get_result() == 'FAILED': + tc.append_log(1, 'Result=%s but ignoring this' % dummy_tc.get_result()) + + tc.append_log(3, '>>> Booting...') + tc.sleep(5.0) + tc.append_log(3, '') + + +def test_eth(tc,io,cmd): + tc.set_section_id('ETH status - ') + tc.append_log(3, '>>>') + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + tc.append_log(3, '>>>') + + eth = pi_eth.PiEth(tc, io) + hdr=eth.read_hdr(0) + eth.disassemble_hdr(hdr) + tc.append_log(3, '') + + +def test_flash(tc,io,cmd): + tc.set_section_id('Flash write to bank 1 - ') + tc.append_log(3, '>>>') + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + tc.append_log(3, '>>>') + + Epcs = pi_epcs.PiEpcs(tc, io) + path_to_rbf = instanceName = tc.gpString + Epcs.write_ver_raw_binary_file("user", path_to_rbf) + tc.append_log(3, '') + +def test_factory_flash(tc,io,cmd): + tc.set_section_id('Factory Flash write to bank 0 - ') + tc.append_log(3, '>>>') + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + tc.append_log(3, '>>>') + + Epcs = pi_epcs.PiEpcs(tc, io) + path_to_rbf = instanceName = tc.gpString + Epcs.write_ver_raw_binary_file("factory", path_to_rbf) + tc.append_log(3, '') + +def sleep(tc,io,cmd): + tc.set_section_id('%s - ' % cmd) + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + if cmd == 'sleep1': + tc.sleep(1.0) + elif cmd == 'sleep5': + tc.sleep(5.0) + +def show_help(tc,io,cmd): + tc.set_section_id('%s - ' % cmd) + tc.append_log(1, '>>> %s' % help_text(tc,io,cmd)) + + +# Avaliable commands +Cmd = dict() +Cmd['REGMAP'] = (read_regmap, 'using pi_system_info to read register info (access PIO_SYSTEM_INFO) and store REGMAPs','') +Cmd['INFO'] = (test_info, 'using pi_system_info to read system info (access PIO_SYSTEM_INFO)','(-s for expected design_name)') +Cmd['FLASH'] = (test_flash, 'using pi_epcs to program/verify flash','(-s for .rbf file)') +Cmd['FACFLASH']= (test_factory_flash,'using pi_epcs to program/verify factory flash','(-s for .rbf file)') +Cmd['SENSORS'] = (test_sensors, 'using pi_unb_sens to readout sensors (access REG_UNB_SENS)','') +Cmd['PPSH'] = (test_ppsh, 'using pi_ppsh to read PPSH capture count (access PIO_PPS)','') +Cmd['ETH'] = (test_eth, 'using pi_eth to read eth status','') +Cmd['REMU'] = (test_remu, 'using pi_remu to load user image (access REG_REMU)','') +Cmd['WDI'] = (test_wdi, 'using pi_wdi to reset to image in bank 0 (access REG_WDI)','') +Cmd['JESD'] = (test_JESD, 'using DB (pi_diag_data_buffer.py)','') +Cmd['sleep1'] = (sleep, 'Sleep 1 second','') +Cmd['sleep5'] = (sleep, 'Sleep 5 seconds','') +Cmd['example'] = (show_help, 'show several example commands','') +Cmd['help'] = (show_help, 'show help on commands','') + + +def help_text(tc,io,cmd): + str='' + if cmd == 'help': + tc.append_log(0, '\n') + tc.append_log(0, '>>> Help:') + tc.append_log(0, 'Usage: %s <nodes> <command sequence> [-v..] [--rep ...]' % sys.argv[0]) + tc.append_log(0, '') + tc.append_log(0, ' <nodes>: use: --unb N --fn N --bn N (N is a number or vector) or:') + tc.append_log(0, ' <nodes>: use: --gn N (N is a number or vector)') + tc.append_log(0, ' <command sequence>: use: --seq <command(s) separated by ",">:') + tc.append_log(0, '') + for cmd in sorted(Cmd): + tc.append_log(0, ' . %s\t%s %s' % (cmd,Cmd[cmd][1],Cmd[cmd][2])) + tc.append_log(0, '') + tc.append_log(0, ' [-vN]: verbose level N (default=5): %s' % tc.verbose_levels()) + tc.append_log(0, ' [--rep N]: N=number of repeats, where -1 is forever, non-stop') + help_text(tc,io,'example') + elif cmd == 'example': + tc.append_log(0, '') + tc.append_log(0, '>>> Examples:') + tc.append_log(0, '') + tc.append_log(0, 'Getting INFO from all nodes on 1 Uniboard: %s --gn 0:7 --seq INFO' % sys.argv[0]) + tc.append_log(0, '') + tc.append_log(0, '[reset, load user img] sequence: --seq REGMAP,WDI,REGMAP,REMU,REGMAP,INFO') + tc.append_log(0, '[flash+start user img] sequence: --seq FLASH,WDI,REGMAP,REMU,REGMAP,INFO -s file.rbf') + tc.append_log(0, '[re-read info,sensors] sequence: --seq INFO,PPSH,SENSORS --rep -1 -s expected_design_name') + tc.append_log(0, '[reset to factory] sequence: --seq WDI,REGMAP') + tc.append_log(0, '[program user image] sequence: --seq FLASH -s file.rbf') + tc.append_log(0, '[load user image] sequence: --seq REMU,REGMAP') + tc.append_log(0, '[modelsim BG-DB test] arguments: --unb 0 --fn 0 --seq BGDB --sim -r 0:2') + tc.append_log(0, '\n') + else: + str = Cmd[cmd][1] + return str + + +def signal_handler(signal, frame): + print('You pressed Ctrl+C!') + tc.repeat=0 + + +################################################################################################################## +# Main +# +# Create a test case object +tc = test_case.Testcase('TB - ', '') +tc.set_result('PASSED') +dgnName = tc.gpString +tc.append_log(3, '>>>') +tc.append_log(0, '>>> Title : Test bench (%s) on nodes %s, %s' % (sys.argv[0],tc.unb_nodes_string(''),dgnName)) +tc.append_log(0, '>>> Commandline : %s' % " ".join(sys.argv)) +tc.append_log(3, '>>>') + + +# Create access object for nodes +io = node_io.NodeIO(tc.nodeImages, tc.base_ip) +#io.setNofRetries(0) +signal.signal(signal.SIGINT, signal_handler) + +################################################################################################################## +# Run tests +if tc.repeat<2: tc.repeat=2 + +while tc.repeat != 0: # -1 for non-stop + tc.repeat -= 1 + tc.next_run() + tc.append_log(3, '') + + try: + for cmd in tc.sequence: + tc.set_section_id('Next command: %s ' % cmd) + tc.append_log(1, '>>> Testrun %d (@%.02fs) - ' % (tc.get_nof_runs(),tc.get_run_time())) + + if cmd == 'REGMAP': # reload node_io: + io = Cmd[cmd][0](tc,io,cmd) + else: + Cmd[cmd][0](tc,io,cmd) + + + except KeyError: + print 'Unknown command:',cmd + cmd='help' + Cmd[cmd][0](tc,io,cmd) + except: + print 'Catched error:',sys.exc_info()[0] + + + +################################################################################################################## +# End +tc.set_section_id('') +tc.append_log(3, '') +tc.append_log(3, '>>>') +tc.append_log(0, '>>> Test bench result: %s' % tc.get_result()) +tc.append_log(0, '>>> Number of runs=%d' % tc.get_nof_runs()) +tc.append_log(0, '>>> Number of errors=%d' % tc.get_nof_errors()) +tc.append_log(0, '>>> Runtime=%f seconds (%f hours)' % (tc.get_run_time(),tc.get_run_time()/3600)) +tc.append_log(3, '>>>') + +sys.exit(tc.get_result()) +