From 9d117478501a403273567b041725df64ffddae61 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 7 Jul 2026 00:24:47 -0700 Subject: [PATCH] eth: Fix AN tests Signed-off-by: Alex Forencich --- .../test_taxi_eth_mac_1g_basex_us.py | 25 +++++++++++------ .../test_taxi_eth_mac_phy_1g_basex.py | 25 +++++++++++------ .../test_taxi_eth_mac_phy_1g_basex_fifo.py | 25 +++++++++++------ .../test_taxi_eth_phy_1g_basex.py | 28 +++++++++++++------ 4 files changed, 70 insertions(+), 33 deletions(-) diff --git a/src/eth/tb/taxi_eth_mac_1g_basex_us/test_taxi_eth_mac_1g_basex_us.py b/src/eth/tb/taxi_eth_mac_1g_basex_us/test_taxi_eth_mac_1g_basex_us.py index 6129a49..60a2fa3 100644 --- a/src/eth/tb/taxi_eth_mac_1g_basex_us/test_taxi_eth_mac_1g_basex_us.py +++ b/src/eth/tb/taxi_eth_mac_1g_basex_us/test_taxi_eth_mac_1g_basex_us.py @@ -817,14 +817,13 @@ async def run_basex_an(tb, port=0, cfg=0x0020, sgmii=False): while True: await RisingEdge(dut.tx_clk[port]) lp_cfg_ack = tb.serdes_sinks[port].get_an_cfg() - if tb.serdes_sinks[port].get_an_ack_match(): - if lp_cfg | 0x4000 == lp_cfg_ack: - break + if tb.serdes_sinks[port].get_an_ack_match() and lp_cfg_ack: + break elif tb.serdes_sinks[port].get_an_ability_match() and lp_cfg_ack is not None and lp_cfg_ack == 0: break if lp_cfg | 0x4000 != lp_cfg_ack: - tb.log.warning("AN inconsistent, restarting") + tb.log.warning("AN inconsistent, restarting (0x%04x != 0x%04x)", lp_cfg | 0x4000, lp_cfg_ack) continue if lp_cfg_ack == 0: @@ -841,9 +840,21 @@ async def run_basex_an(tb, port=0, cfg=0x0020, sgmii=False): while True: await RisingEdge(dut.tx_clk[port]) + lp_cfg_ack2 = tb.serdes_sinks[port].get_an_cfg() if tb.serdes_sinks[port].get_an_idle_match(): break + elif tb.serdes_sinks[port].get_an_ability_match() and lp_cfg_ack2 is not None and (lp_cfg_ack2 == 0 or lp_cfg_ack != lp_cfg_ack2): + break + if lp_cfg_ack2 is not None and lp_cfg_ack != lp_cfg_ack2: + tb.log.warning("AN inconsistent, restarting (0x%04x != 0x%04x)", lp_cfg_ack, lp_cfg_ack2) + continue + + if lp_cfg_ack2 == 0: + tb.log.warning("AN restart requested") + continue + + tb.log.info("AN done") return lp_cfg_ack tb.log.warning("AN timed out") @@ -883,8 +894,6 @@ async def run_test_an(dut, port=0, sgmii_en=False, sgmii_auto=False): for x in range(16): cfg1 = 0x000A | ((x & 3) << 5) | ((x & 3) << 7) | ((x & 3) << 12) cfg2 = 0x000C | (((x >> 2) & 3) << 5) | (((x >> 2) & 3) << 7) | (((x >> 2) & 3) << 12) - cfg1 = 0x002A - cfg2 = 0x0020 dut.an_adv_ability_basex[port].value = cfg2 lp_cfg = await run_basex_an(tb, port, cfg1, False) @@ -906,11 +915,11 @@ async def run_test_an(dut, port=0, sgmii_en=False, sgmii_auto=False): # both ends support symmetric pause assert bool(dut.an_res_tx_pause[port].value) assert bool(dut.an_res_rx_pause[port].value) - elif ((cfg1 >> 7) & 3) & 2 == 3 and ((cfg2 >> 7) & 3) & 2 == 2: + elif ((cfg1 >> 7) & 3) == 2 and ((cfg2 >> 7) & 3) == 3: # asymmetric towards local assert not bool(dut.an_res_tx_pause[port].value) assert bool(dut.an_res_rx_pause[port].value) - elif ((cfg1 >> 7) & 3) & 2 == 2 and ((cfg2 >> 7) & 3) & 2 == 3: + elif ((cfg1 >> 7) & 3) == 3 and ((cfg2 >> 7) & 3) == 2: # asymmetric towards partner assert bool(dut.an_res_tx_pause[port].value) assert not bool(dut.an_res_rx_pause[port].value) diff --git a/src/eth/tb/taxi_eth_mac_phy_1g_basex/test_taxi_eth_mac_phy_1g_basex.py b/src/eth/tb/taxi_eth_mac_phy_1g_basex/test_taxi_eth_mac_phy_1g_basex.py index eaf4969..5adcaa0 100644 --- a/src/eth/tb/taxi_eth_mac_phy_1g_basex/test_taxi_eth_mac_phy_1g_basex.py +++ b/src/eth/tb/taxi_eth_mac_phy_1g_basex/test_taxi_eth_mac_phy_1g_basex.py @@ -746,14 +746,13 @@ async def run_basex_an(tb, cfg, sgmii=False): while True: await RisingEdge(dut.tx_clk) lp_cfg_ack = tb.serdes_sink.get_an_cfg() - if tb.serdes_sink.get_an_ack_match(): - if lp_cfg | 0x4000 == lp_cfg_ack: - break + if tb.serdes_sink.get_an_ack_match() and lp_cfg_ack is not None: + break elif tb.serdes_sink.get_an_ability_match() and lp_cfg_ack is not None and lp_cfg_ack == 0: break if lp_cfg | 0x4000 != lp_cfg_ack: - tb.log.warning("AN inconsistent, restarting") + tb.log.warning("AN inconsistent, restarting (0x%04x != 0x%04x)", lp_cfg | 0x4000, lp_cfg_ack) continue if lp_cfg_ack == 0: @@ -770,9 +769,21 @@ async def run_basex_an(tb, cfg, sgmii=False): while True: await RisingEdge(dut.tx_clk) + lp_cfg_ack2 = tb.serdes_sink.get_an_cfg() if tb.serdes_sink.get_an_idle_match(): break + elif tb.serdes_sink.get_an_ability_match() and lp_cfg_ack2 is not None and (lp_cfg_ack2 == 0 or lp_cfg_ack != lp_cfg_ack2): + break + if lp_cfg_ack2 is not None and lp_cfg_ack != lp_cfg_ack2: + tb.log.warning("AN inconsistent, restarting (0x%04x != 0x%04x)", lp_cfg_ack, lp_cfg_ack2) + continue + + if lp_cfg_ack2 == 0: + tb.log.warning("AN restart requested") + continue + + tb.log.info("AN done") return lp_cfg_ack tb.log.warning("AN timed out") @@ -804,8 +815,6 @@ async def run_test_an(dut, gbx_cfg=None, sgmii_en=False, sgmii_auto=False): for x in range(16): cfg1 = 0x000A | ((x & 3) << 5) | ((x & 3) << 7) | ((x & 3) << 12) cfg2 = 0x000C | (((x >> 2) & 3) << 5) | (((x >> 2) & 3) << 7) | (((x >> 2) & 3) << 12) - cfg1 = 0x002A - cfg2 = 0x0020 dut.an_adv_ability_basex.value = cfg2 lp_cfg = await run_basex_an(tb, cfg1, False) @@ -827,11 +836,11 @@ async def run_test_an(dut, gbx_cfg=None, sgmii_en=False, sgmii_auto=False): # both ends support symmetric pause assert bool(dut.an_res_tx_pause.value) assert bool(dut.an_res_rx_pause.value) - elif ((cfg1 >> 7) & 3) & 2 == 3 and ((cfg2 >> 7) & 3) & 2 == 2: + elif ((cfg1 >> 7) & 3) == 2 and ((cfg2 >> 7) & 3) == 3: # asymmetric towards local assert not bool(dut.an_res_tx_pause.value) assert bool(dut.an_res_rx_pause.value) - elif ((cfg1 >> 7) & 3) & 2 == 2 and ((cfg2 >> 7) & 3) & 2 == 3: + elif ((cfg1 >> 7) & 3) == 3 and ((cfg2 >> 7) & 3) == 2: # asymmetric towards partner assert bool(dut.an_res_tx_pause.value) assert not bool(dut.an_res_rx_pause.value) diff --git a/src/eth/tb/taxi_eth_mac_phy_1g_basex_fifo/test_taxi_eth_mac_phy_1g_basex_fifo.py b/src/eth/tb/taxi_eth_mac_phy_1g_basex_fifo/test_taxi_eth_mac_phy_1g_basex_fifo.py index e20195e..7baa109 100644 --- a/src/eth/tb/taxi_eth_mac_phy_1g_basex_fifo/test_taxi_eth_mac_phy_1g_basex_fifo.py +++ b/src/eth/tb/taxi_eth_mac_phy_1g_basex_fifo/test_taxi_eth_mac_phy_1g_basex_fifo.py @@ -305,14 +305,13 @@ async def run_basex_an(tb, cfg, sgmii=False): while True: await RisingEdge(dut.tx_clk) lp_cfg_ack = tb.serdes_sink.get_an_cfg() - if tb.serdes_sink.get_an_ack_match(): - if lp_cfg | 0x4000 == lp_cfg_ack: - break + if tb.serdes_sink.get_an_ack_match() and lp_cfg_ack is not None: + break elif tb.serdes_sink.get_an_ability_match() and lp_cfg_ack is not None and lp_cfg_ack == 0: break if lp_cfg | 0x4000 != lp_cfg_ack: - tb.log.warning("AN inconsistent, restarting") + tb.log.warning("AN inconsistent, restarting (0x%04x != 0x%04x)", lp_cfg | 0x4000, lp_cfg_ack) continue if lp_cfg_ack == 0: @@ -329,9 +328,21 @@ async def run_basex_an(tb, cfg, sgmii=False): while True: await RisingEdge(dut.tx_clk) + lp_cfg_ack2 = tb.serdes_sink.get_an_cfg() if tb.serdes_sink.get_an_idle_match(): break + elif tb.serdes_sink.get_an_ability_match() and lp_cfg_ack2 is not None and (lp_cfg_ack2 == 0 or lp_cfg_ack != lp_cfg_ack2): + break + if lp_cfg_ack2 is not None and lp_cfg_ack != lp_cfg_ack2: + tb.log.warning("AN inconsistent, restarting (0x%04x != 0x%04x)", lp_cfg_ack, lp_cfg_ack2) + continue + + if lp_cfg_ack2 == 0: + tb.log.warning("AN restart requested") + continue + + tb.log.info("AN done") return lp_cfg_ack tb.log.warning("AN timed out") @@ -363,8 +374,6 @@ async def run_test_an(dut, gbx_cfg=None, sgmii_en=False, sgmii_auto=False): for x in range(16): cfg1 = 0x000A | ((x & 3) << 5) | ((x & 3) << 7) | ((x & 3) << 12) cfg2 = 0x000C | (((x >> 2) & 3) << 5) | (((x >> 2) & 3) << 7) | (((x >> 2) & 3) << 12) - cfg1 = 0x002A - cfg2 = 0x0020 dut.an_adv_ability_basex.value = cfg2 lp_cfg = await run_basex_an(tb, cfg1, False) @@ -386,11 +395,11 @@ async def run_test_an(dut, gbx_cfg=None, sgmii_en=False, sgmii_auto=False): # both ends support symmetric pause assert bool(dut.an_res_tx_pause.value) assert bool(dut.an_res_rx_pause.value) - elif ((cfg1 >> 7) & 3) & 2 == 3 and ((cfg2 >> 7) & 3) & 2 == 2: + elif ((cfg1 >> 7) & 3) == 2 and ((cfg2 >> 7) & 3) == 3: # asymmetric towards local assert not bool(dut.an_res_tx_pause.value) assert bool(dut.an_res_rx_pause.value) - elif ((cfg1 >> 7) & 3) & 2 == 2 and ((cfg2 >> 7) & 3) & 2 == 3: + elif ((cfg1 >> 7) & 3) == 3 and ((cfg2 >> 7) & 3) == 2: # asymmetric towards partner assert bool(dut.an_res_tx_pause.value) assert not bool(dut.an_res_rx_pause.value) diff --git a/src/eth/tb/taxi_eth_phy_1g_basex/test_taxi_eth_phy_1g_basex.py b/src/eth/tb/taxi_eth_phy_1g_basex/test_taxi_eth_phy_1g_basex.py index a38ec4e..66dc045 100644 --- a/src/eth/tb/taxi_eth_phy_1g_basex/test_taxi_eth_phy_1g_basex.py +++ b/src/eth/tb/taxi_eth_phy_1g_basex/test_taxi_eth_phy_1g_basex.py @@ -197,14 +197,13 @@ async def run_basex_an(tb, cfg, sgmii=False): while True: await RisingEdge(dut.tx_clk) lp_cfg_ack = tb.serdes_sink.get_an_cfg() - if tb.serdes_sink.get_an_ack_match(): - if lp_cfg | 0x4000 == lp_cfg_ack: - break + if tb.serdes_sink.get_an_ack_match() and lp_cfg_ack is not None: + break elif tb.serdes_sink.get_an_ability_match() and lp_cfg_ack is not None and lp_cfg_ack == 0: break if lp_cfg | 0x4000 != lp_cfg_ack: - tb.log.warning("AN inconsistent, restarting") + tb.log.warning("AN inconsistent, restarting (0x%04x != 0x%04x)", lp_cfg | 0x4000, lp_cfg_ack) continue if lp_cfg_ack == 0: @@ -221,9 +220,21 @@ async def run_basex_an(tb, cfg, sgmii=False): while True: await RisingEdge(dut.tx_clk) + lp_cfg_ack2 = tb.serdes_sink.get_an_cfg() if tb.serdes_sink.get_an_idle_match(): break + elif tb.serdes_sink.get_an_ability_match() and lp_cfg_ack2 is not None and (lp_cfg_ack2 == 0 or lp_cfg_ack != lp_cfg_ack2): + break + if lp_cfg_ack2 is not None and lp_cfg_ack != lp_cfg_ack2: + tb.log.warning("AN inconsistent, restarting (0x%04x != 0x%04x)", lp_cfg_ack, lp_cfg_ack2) + continue + + if lp_cfg_ack2 == 0: + tb.log.warning("AN restart requested") + continue + + tb.log.info("AN done") return lp_cfg_ack tb.log.warning("AN timed out") @@ -255,8 +266,6 @@ async def run_test_an(dut, sgmii_en=False, sgmii_auto=False): for x in range(16): cfg1 = 0x000A | ((x & 3) << 5) | ((x & 3) << 7) | ((x & 3) << 12) cfg2 = 0x000C | (((x >> 2) & 3) << 5) | (((x >> 2) & 3) << 7) | (((x >> 2) & 3) << 12) - cfg1 = 0x002A - cfg2 = 0x0020 dut.an_adv_ability_basex.value = cfg2 lp_cfg = await run_basex_an(tb, cfg1, False) @@ -278,11 +287,11 @@ async def run_test_an(dut, sgmii_en=False, sgmii_auto=False): # both ends support symmetric pause assert bool(dut.an_res_tx_pause.value) assert bool(dut.an_res_rx_pause.value) - elif ((cfg1 >> 7) & 3) & 2 == 3 and ((cfg2 >> 7) & 3) & 2 == 2: + elif ((cfg1 >> 7) & 3) == 2 and ((cfg2 >> 7) & 3) == 3: # asymmetric towards local assert not bool(dut.an_res_tx_pause.value) assert bool(dut.an_res_rx_pause.value) - elif ((cfg1 >> 7) & 3) & 2 == 2 and ((cfg2 >> 7) & 3) & 2 == 3: + elif ((cfg1 >> 7) & 3) == 3 and ((cfg2 >> 7) & 3) == 2: # asymmetric towards partner assert bool(dut.an_res_tx_pause.value) assert not bool(dut.an_res_rx_pause.value) @@ -365,7 +374,8 @@ if getattr(cocotb, 'top', None) is not None: if cocotb.top.AN_EN.value: for test in [run_test_an]: factory = TestFactory(test) - factory.add_option(("sgmii_en", "sgmii_auto"), [(False, False), (True, False), (False, True)]) + factory.add_option(("sgmii_en", "sgmii_auto"), + [(False, False), (True, False), (False, True)]) factory.generate_tests()