From 2e53313c41fcb799d34fcda5e745b22555419f86 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 17 Jun 2026 16:48:20 -0700 Subject: [PATCH] eth: Suport AN config reg exchange in AXI stream-BASE-X encode/decode logic Signed-off-by: Alex Forencich --- src/eth/rtl/taxi_axis_basex_rx_16.sv | 87 ++++++++++++++ src/eth/rtl/taxi_axis_basex_rx_8.sv | 109 ++++++++++++++++++ src/eth/rtl/taxi_axis_basex_tx_16.sv | 51 +++++++- src/eth/rtl/taxi_axis_basex_tx_8.sv | 51 +++++++- src/eth/rtl/taxi_eth_mac_phy_1g_basex_rx.sv | 20 ++++ src/eth/rtl/taxi_eth_mac_phy_1g_basex_tx.sv | 16 +++ src/eth/tb/taxi_axis_basex_rx_16/Makefile | 1 + .../test_taxi_axis_basex_rx_16.py | 41 ++++++- .../test_taxi_axis_basex_rx_16.sv | 17 +++ src/eth/tb/taxi_axis_basex_rx_8/Makefile | 1 + .../test_taxi_axis_basex_rx_8.py | 37 ++++++ .../test_taxi_axis_basex_rx_8.sv | 17 +++ src/eth/tb/taxi_axis_basex_tx_16/Makefile | 1 + .../test_taxi_axis_basex_tx_16.py | 41 +++++++ .../test_taxi_axis_basex_tx_16.sv | 13 +++ src/eth/tb/taxi_axis_basex_tx_8/Makefile | 1 + .../test_taxi_axis_basex_tx_8.py | 41 +++++++ .../test_taxi_axis_basex_tx_8.sv | 15 ++- 18 files changed, 548 insertions(+), 12 deletions(-) diff --git a/src/eth/rtl/taxi_axis_basex_rx_16.sv b/src/eth/rtl/taxi_axis_basex_rx_16.sv index 51d1433..093c5fc 100644 --- a/src/eth/rtl/taxi_axis_basex_rx_16.sv +++ b/src/eth/rtl/taxi_axis_basex_rx_16.sv @@ -20,6 +20,7 @@ module taxi_axis_basex_rx_16 # parameter DATA_W = 16, parameter CTRL_W = (DATA_W/8), parameter logic GBX_IF_EN = 1'b0, + parameter logic AN_EN = 1'b1, parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = 96 @@ -40,6 +41,15 @@ module taxi_axis_basex_rx_16 # */ taxi_axis_if.src m_axis_rx, + /* + * AN config register + */ + output wire logic [15:0] rx_an_cfg, + output wire logic rx_an_cfg_valid, + output wire logic rx_an_ability_match, + output wire logic rx_an_ack_match, + output wire logic rx_an_idle_match, + /* * PTP */ @@ -133,6 +143,9 @@ logic [DATA_W-1:0] input_data_d0_reg = '0; logic [DATA_W-1:0] input_data_d1_reg = '0; logic [DATA_W-1:0] input_data_d2_reg = '0; +logic input_k28p5_d0_reg = 1'b0; +logic input_i_d0_reg = 1'b0; +logic input_c_d0_reg = 1'b0; logic input_start_d0_reg = 1'b0; logic frame_oversize_reg = 1'b0, frame_oversize_next; @@ -152,6 +165,12 @@ logic m_axis_rx_tvalid_reg = 1'b0, m_axis_rx_tvalid_next; logic m_axis_rx_tlast_reg = 1'b0, m_axis_rx_tlast_next; logic m_axis_rx_tuser_reg = 1'b0, m_axis_rx_tuser_next; +logic [15:0] rx_an_cfg_reg = '0; +logic rx_an_cfg_valid_reg = 1'b0; +logic [1:0] an_ability_match_cnt_reg = '0; +logic [1:0] an_ack_match_cnt_reg = '0; +logic [1:0] an_idle_match_cnt_reg = '0; + logic start_packet_int_reg = 1'b0; logic [1:0] start_packet_reg = '0; logic frame_reg = 1'b0; @@ -202,6 +221,12 @@ if (PTP_TS_EN) begin assign m_axis_rx.tuser[1 +: PTP_TS_W] = ptp_ts_out_reg; end +assign rx_an_cfg = AN_EN ? rx_an_cfg_reg : '0; +assign rx_an_cfg_valid = AN_EN ? rx_an_cfg_valid_reg : 1'b0; +assign rx_an_ability_match = AN_EN ? &an_ability_match_cnt_reg : 1'b0; +assign rx_an_ack_match = AN_EN ? &an_ack_match_cnt_reg : 1'b0; +assign rx_an_idle_match = AN_EN ? &an_idle_match_cnt_reg : 1'b0; + assign rx_start_packet = start_packet_reg; assign stat_rx_byte = stat_rx_byte_reg; @@ -589,6 +614,8 @@ always_ff @(posedge clk) begin m_axis_rx_tlast_reg <= m_axis_rx_tlast_next; m_axis_rx_tuser_reg <= m_axis_rx_tuser_next; + rx_an_cfg_valid_reg <= 1'b0; + ptp_ts_out_reg <= ptp_ts_out_next; stat_rx_byte_reg <= stat_rx_byte_next; @@ -616,6 +643,9 @@ always_ff @(posedge clk) begin input_data_d1_reg <= input_data_d0_reg; input_data_d2_reg <= input_data_d1_reg; + input_k28p5_d0_reg <= 1'b0; + input_i_d0_reg <= 1'b0; + input_c_d0_reg <= 1'b0; input_start_d0_reg <= 1'b0; if (PTP_TS_EN && PTP_TS_FMT_TOD) begin @@ -629,6 +659,49 @@ always_ff @(posedge clk) begin /* verilator lint_on SELRANGE */ end + // /K28.5/ control character detection + if (encoded_rx_data_k[0] && encoded_rx_data[7:0] == K(28, 5)) begin + input_k28p5_d0_reg <= 1'b1; + end + + // idle symbol detection + if (encoded_rx_data_k == 2'b01 && (encoded_rx_data == CTRL_I1 || encoded_rx_data == CTRL_I2)) begin + input_i_d0_reg <= 1'b1; + end + + if (AN_EN && input_i_d0_reg) begin + an_ability_match_cnt_reg <= '0; + an_ack_match_cnt_reg <= '0; + if (!(&an_idle_match_cnt_reg)) begin + an_idle_match_cnt_reg <= an_idle_match_cnt_reg + 1; + end + end + + // config symbol detection + if (encoded_rx_data_k == 2'b01 && (encoded_rx_data == CTRL_C1 || encoded_rx_data == CTRL_C2)) begin + input_c_d0_reg <= 1'b1; + end + + if (AN_EN && input_c_d0_reg) begin + rx_an_cfg_reg <= encoded_rx_data; + rx_an_cfg_valid_reg <= encoded_rx_data_k == 2'b00; + if (((rx_an_cfg_reg ^ encoded_rx_data) & 16'h4000) == 0) begin + if (!(&an_ability_match_cnt_reg)) begin + an_ability_match_cnt_reg <= an_ability_match_cnt_reg + 1; + end + end else begin + an_ability_match_cnt_reg <= '0; + end + if (rx_an_cfg_reg[14] && rx_an_cfg_reg == encoded_rx_data) begin + if (!(&an_ack_match_cnt_reg)) begin + an_ack_match_cnt_reg <= an_ack_match_cnt_reg + 1; + end + end else begin + an_ack_match_cnt_reg <= '0; + end + an_idle_match_cnt_reg <= '0; + end + // start control character detection if (encoded_rx_data_k[0] && encoded_rx_data[7:0] == CTRL_S) begin input_start_d0_reg <= 1'b1; @@ -636,6 +709,12 @@ always_ff @(posedge clk) begin lanes_swapped_reg <= 1'b0; end + if (AN_EN && input_start_d0_reg) begin + an_ability_match_cnt_reg <= '0; + an_ack_match_cnt_reg <= '0; + an_idle_match_cnt_reg <= '0; + end + // SFD detection start_packet_int_reg <= 1'b0; if (in_pre_reg) begin @@ -684,6 +763,11 @@ always_ff @(posedge clk) begin m_axis_rx_tvalid_reg <= 1'b0; + rx_an_cfg_valid_reg <= 1'b0; + an_ability_match_cnt_reg <= '0; + an_ack_match_cnt_reg <= '0; + an_idle_match_cnt_reg <= '0; + start_packet_int_reg <= 1'b0; start_packet_reg <= '0; frame_reg <= 1'b0; @@ -704,6 +788,9 @@ always_ff @(posedge clk) begin stat_rx_err_framing_reg <= 1'b0; stat_rx_err_preamble_reg <= 1'b0; + input_k28p5_d0_reg <= 1'b0; + input_i_d0_reg <= 1'b0; + input_c_d0_reg <= 1'b0; input_start_d0_reg <= 1'b0; end end diff --git a/src/eth/rtl/taxi_axis_basex_rx_8.sv b/src/eth/rtl/taxi_axis_basex_rx_8.sv index 80a33dd..2e00e12 100644 --- a/src/eth/rtl/taxi_axis_basex_rx_8.sv +++ b/src/eth/rtl/taxi_axis_basex_rx_8.sv @@ -20,6 +20,7 @@ module taxi_axis_basex_rx_8 # parameter DATA_W = 8, parameter CTRL_W = (DATA_W/8), parameter logic GBX_IF_EN = 1'b0, + parameter logic AN_EN = 1'b1, parameter logic PTP_TS_EN = 1'b0, parameter PTP_TS_W = 96 ) @@ -39,6 +40,15 @@ module taxi_axis_basex_rx_8 # */ taxi_axis_if.src m_axis_rx, + /* + * AN config register + */ + output wire logic [15:0] rx_an_cfg, + output wire logic rx_an_cfg_valid, + output wire logic rx_an_ability_match, + output wire logic rx_an_ack_match, + output wire logic rx_an_idle_match, + /* * PTP */ @@ -130,6 +140,12 @@ logic [DATA_W-1:0] encoded_rx_data_d4_reg = '0; logic encoded_rx_data_k_d0_reg = 1'b0; +logic input_k28p5_d0_reg = 1'b0; +logic input_i_d0_reg = 1'b0; +logic input_c_d0_reg = 1'b0; +logic input_c_d1_reg = 1'b0; +logic input_start_d0_reg = 1'b0; + logic frame_error_reg = 1'b0, frame_error_next; logic pre_ok_reg = 1'b0, pre_ok_next; logic [3:0] hdr_ptr_reg = '0, hdr_ptr_next; @@ -146,6 +162,13 @@ logic m_axis_rx_tvalid_reg = 1'b0, m_axis_rx_tvalid_next; logic m_axis_rx_tlast_reg = 1'b0, m_axis_rx_tlast_next; logic m_axis_rx_tuser_reg = 1'b0, m_axis_rx_tuser_next; +logic [15:0] rx_an_cfg_reg = '0; +logic rx_an_cfg_valid_reg = 1'b0; +logic an_cfg_match_reg = 1'b0; +logic [1:0] an_ability_match_cnt_reg = '0; +logic [1:0] an_ack_match_cnt_reg = '0; +logic [1:0] an_idle_match_cnt_reg = '0; + logic start_packet_int_reg = 1'b0; logic start_packet_reg = 1'b0; @@ -182,6 +205,12 @@ if (PTP_TS_EN) begin assign m_axis_rx.tuser[1 +: PTP_TS_W] = ptp_ts_out_reg; end +assign rx_an_cfg = AN_EN ? rx_an_cfg_reg : '0; +assign rx_an_cfg_valid = AN_EN ? rx_an_cfg_valid_reg : 1'b0; +assign rx_an_ability_match = AN_EN ? &an_ability_match_cnt_reg : 1'b0; +assign rx_an_ack_match = AN_EN ? &an_ack_match_cnt_reg : 1'b0; +assign rx_an_idle_match = AN_EN ? &an_idle_match_cnt_reg : 1'b0; + assign rx_start_packet = start_packet_reg; assign stat_rx_byte = stat_rx_byte_reg; @@ -458,6 +487,8 @@ always_ff @(posedge clk) begin m_axis_rx_tlast_reg <= m_axis_rx_tlast_next; m_axis_rx_tuser_reg <= m_axis_rx_tuser_next; + rx_an_cfg_valid_reg <= 1'b0; + start_packet_int_reg <= 1'b0; start_packet_reg <= 1'b0; @@ -482,6 +513,73 @@ always_ff @(posedge clk) begin encoded_rx_data_k_d0_reg <= encoded_rx_data_k; + input_k28p5_d0_reg <= 1'b0; + input_i_d0_reg <= 1'b0; + input_c_d0_reg <= 1'b0; + input_c_d1_reg <= input_c_d0_reg; + input_start_d0_reg <= 1'b0; + + // /K28.5/ control character detection + if (encoded_rx_data_k && encoded_rx_data == K(28, 5)) begin + input_k28p5_d0_reg <= 1'b1; + end + + // idle symbol detection + if (input_k28p5_d0_reg && (encoded_rx_data == D(5,6) || encoded_rx_data == D(16,2))) begin + input_i_d0_reg <= 1'b1; + end + + if (AN_EN && input_i_d0_reg) begin + an_ability_match_cnt_reg <= '0; + an_ack_match_cnt_reg <= '0; + if (!(&an_idle_match_cnt_reg)) begin + an_idle_match_cnt_reg <= an_idle_match_cnt_reg + 1; + end + end + + // config symbol detection + if (input_k28p5_d0_reg && (encoded_rx_data == D(21,5) || encoded_rx_data == D(2,2))) begin + input_c_d0_reg <= 1'b1; + end + + if (AN_EN && input_c_d0_reg) begin + rx_an_cfg_reg[7:0] <= encoded_rx_data; + an_cfg_match_reg <= rx_an_cfg_reg[7:0] == encoded_rx_data; + input_c_d1_reg <= encoded_rx_data_k == 1'b0; + an_idle_match_cnt_reg <= '0; + end + + if (AN_EN && input_c_d1_reg) begin + rx_an_cfg_reg[15:8] <= encoded_rx_data; + rx_an_cfg_valid_reg <= encoded_rx_data_k == 1'b0; + if (an_cfg_match_reg && ((rx_an_cfg_reg[15:8] ^ encoded_rx_data) & 8'h40) == 0) begin + if (!(&an_ability_match_cnt_reg)) begin + an_ability_match_cnt_reg <= an_ability_match_cnt_reg + 1; + end + end else begin + an_ability_match_cnt_reg <= '0; + end + if (an_cfg_match_reg && rx_an_cfg_reg[14] && rx_an_cfg_reg[15:8] == encoded_rx_data) begin + if (!(&an_ack_match_cnt_reg)) begin + an_ack_match_cnt_reg <= an_ack_match_cnt_reg + 1; + end + end else begin + an_ack_match_cnt_reg <= '0; + end + an_idle_match_cnt_reg <= '0; + end + + // start control character detection + if (encoded_rx_data_k && encoded_rx_data == CTRL_S) begin + input_start_d0_reg <= 1'b1; + end + + if (AN_EN && input_start_d0_reg) begin + an_ability_match_cnt_reg <= '0; + an_ack_match_cnt_reg <= '0; + an_idle_match_cnt_reg <= '0; + end + if (reset_crc) begin crc_state_reg <= '1; end else if (update_crc) begin @@ -508,8 +606,19 @@ always_ff @(posedge clk) begin if (rst) begin state_reg <= STATE_IDLE; + input_k28p5_d0_reg <= 1'b0; + input_i_d0_reg <= 1'b0; + input_c_d0_reg <= 1'b0; + input_c_d1_reg <= 1'b0; + input_start_d0_reg <= 1'b0; + m_axis_rx_tvalid_reg <= 1'b0; + rx_an_cfg_valid_reg <= 1'b0; + an_ability_match_cnt_reg <= '0; + an_ack_match_cnt_reg <= '0; + an_idle_match_cnt_reg <= '0; + start_packet_int_reg <= 1'b0; start_packet_reg <= 1'b0; diff --git a/src/eth/rtl/taxi_axis_basex_tx_16.sv b/src/eth/rtl/taxi_axis_basex_tx_16.sv index 4775dd1..8a5284f 100644 --- a/src/eth/rtl/taxi_axis_basex_tx_16.sv +++ b/src/eth/rtl/taxi_axis_basex_tx_16.sv @@ -21,6 +21,7 @@ module taxi_axis_basex_tx_16 # parameter CTRL_W = (DATA_W/8), parameter logic GBX_IF_EN = 1'b0, parameter GBX_CNT = 1, + parameter logic AN_EN = 1'b1, parameter logic DIC_EN = 1'b1, parameter logic PTP_TS_EN = 1'b0, parameter PTP_TS_W = 96, @@ -48,6 +49,13 @@ module taxi_axis_basex_tx_16 # input wire logic tx_gbx_req_stall = '0, output wire logic [GBX_CNT-1:0] tx_gbx_sync, + /* + * AN config register + */ + input wire logic [15:0] tx_an_cfg = '0, + input wire logic tx_an_cfg_valid = 1'b0, + output wire logic tx_an_cfg_ready, + /* * PTP */ @@ -188,7 +196,8 @@ typedef enum logic [3:0] { STATE_TR, STATE_RR, STATE_ERR, - STATE_IFG + STATE_IFG, + STATE_AN } state_t; state_t state_reg = STATE_IDLE, state_next; @@ -214,10 +223,13 @@ logic frame_len_lim_check_reg = '0, frame_len_lim_check_next; logic [1:0] pre_cnt_reg = '0, pre_cnt_next; logic [7:0] ifg_cnt_reg = '0, ifg_cnt_next; logic deficit_idle_cnt_reg = 1'd0, deficit_idle_cnt_next; +logic an_phase_reg = 1'b0, an_phase_next; logic rd_reg = 1'b0, rd_next; logic s_axis_tx_tready_reg = 1'b0, s_axis_tx_tready_next; +logic tx_an_cfg_ready_reg = 1'b0, tx_an_cfg_ready_next; + logic [PTP_TS_W-1:0] m_axis_tx_cpl_ts_reg = '0, m_axis_tx_cpl_ts_next; logic [TX_TAG_W-1:0] m_axis_tx_cpl_tag_reg = '0, m_axis_tx_cpl_tag_next; logic m_axis_tx_cpl_valid_reg = 1'b0, m_axis_tx_cpl_valid_next; @@ -262,6 +274,8 @@ assign m_axis_tx_cpl.tid = m_axis_tx_cpl_tag_reg; assign m_axis_tx_cpl.tdest = '0; assign m_axis_tx_cpl.tuser = '0; +assign tx_an_cfg_ready = AN_EN ? tx_an_cfg_ready_reg : 1'b0; + assign tx_start_packet = {1'b0, start_packet_reg}; assign stat_tx_byte = stat_tx_byte_reg; @@ -362,19 +376,22 @@ always_comb begin pre_cnt_next = pre_cnt_reg; ifg_cnt_next = ifg_cnt_reg; deficit_idle_cnt_next = deficit_idle_cnt_reg; + an_phase_next = an_phase_reg; rd_next = rd_reg; s_axis_tx_tready_next = 1'b0; + m_axis_tx_cpl_ts_next = m_axis_tx_cpl_ts_reg; + m_axis_tx_cpl_tag_next = m_axis_tx_cpl_tag_reg; + m_axis_tx_cpl_valid_next = 1'b0; + + tx_an_cfg_ready_next = 1'b0; + s_tdata_next = s_tdata_reg; s_empty_next = s_empty_reg; crc_data_next = crc_data_reg; - m_axis_tx_cpl_ts_next = m_axis_tx_cpl_ts_reg; - m_axis_tx_cpl_tag_next = m_axis_tx_cpl_tag_reg; - m_axis_tx_cpl_valid_next = 1'b0; - if (start_packet_reg) begin if (PTP_TS_EN) begin m_axis_tx_cpl_ts_next = ptp_ts; @@ -495,6 +512,11 @@ always_comb begin encoded_tx_data_next = {{1{ETH_PRE}}, CTRL_S}; encoded_tx_data_k_next = 2'b01; state_next = STATE_PREAMBLE; + end else if (AN_EN && tx_an_cfg_valid) begin + // Config register + encoded_tx_data_next = an_phase_reg ? CTRL_C2 : CTRL_C1; + encoded_tx_data_k_next = 2'b01; + state_next = STATE_AN; end else begin ifg_cnt_next = 8'd0; deficit_idle_cnt_next = 1'd0; @@ -737,6 +759,19 @@ always_comb begin end end end + STATE_AN: begin + if (AN_EN) begin + // send config register + encoded_tx_data_next = tx_an_cfg; + encoded_tx_data_k_next = 2'b00; + + tx_an_cfg_ready_next = 1'b1; + + an_phase_next = !an_phase_reg; + + state_next = STATE_IDLE; + end + end default: begin // invalid state, return to idle state_next = STATE_IDLE; @@ -768,6 +803,7 @@ always_ff @(posedge clk) begin pre_cnt_reg <= pre_cnt_next; ifg_cnt_reg <= ifg_cnt_next; deficit_idle_cnt_reg <= deficit_idle_cnt_next; + an_phase_reg <= an_phase_next; rd_reg <= rd_next; s_tdata_reg <= s_tdata_next; @@ -781,6 +817,8 @@ always_ff @(posedge clk) begin m_axis_tx_cpl_tag_reg <= m_axis_tx_cpl_tag_next; m_axis_tx_cpl_valid_reg <= m_axis_tx_cpl_valid_next; + tx_an_cfg_ready_reg <= tx_an_cfg_ready_next; + start_packet_int_reg <= start_packet_int_next; start_packet_reg <= start_packet_next; @@ -822,12 +860,15 @@ always_ff @(posedge clk) begin frame_reg <= 1'b0; deficit_idle_cnt_reg <= 1'd0; + an_phase_reg <= 1'b0; rd_reg <= 1'b0; s_axis_tx_tready_reg <= 1'b0; m_axis_tx_cpl_valid_reg <= 1'b0; + tx_an_cfg_ready_reg <= 1'b0; + encoded_tx_data_reg <= '0; encoded_tx_data_k_reg <= '0; encoded_tx_data_dm_reg <= '0; diff --git a/src/eth/rtl/taxi_axis_basex_tx_8.sv b/src/eth/rtl/taxi_axis_basex_tx_8.sv index 2631981..ea78452 100644 --- a/src/eth/rtl/taxi_axis_basex_tx_8.sv +++ b/src/eth/rtl/taxi_axis_basex_tx_8.sv @@ -23,6 +23,7 @@ module taxi_axis_basex_tx_8 # parameter MIN_FRAME_LEN = 64, parameter logic GBX_IF_EN = 1'b0, parameter GBX_CNT = 1, + parameter logic AN_EN = 1'b1, parameter logic DIC_EN = 1'b1, parameter logic PTP_TS_EN = 1'b0, parameter PTP_TS_W = 96, @@ -50,6 +51,13 @@ module taxi_axis_basex_tx_8 # input wire logic tx_gbx_req_stall = '0, output wire logic [GBX_CNT-1:0] tx_gbx_sync, + /* + * AN config register + */ + input wire logic [15:0] tx_an_cfg = '0, + input wire logic tx_an_cfg_valid = 1'b0, + output wire logic tx_an_cfg_ready, + /* * PTP */ @@ -181,7 +189,8 @@ typedef enum logic [3:0] { STATE_FCS, STATE_T, STATE_R, - STATE_IFG + STATE_IFG, + STATE_AN } state_t; state_t state_reg = STATE_IDLE, state_next; @@ -206,6 +215,7 @@ logic [2:0] pre_cnt_reg = '0, pre_cnt_next; logic [7:0] ifg_cnt_reg = '0, ifg_cnt_next; logic deficit_idle_cnt_reg = 1'd0, deficit_idle_cnt_next; logic odd_reg = 1'b0, odd_next; +logic an_phase_reg = 1'b0, an_phase_next; logic rd_reg = 1'b0, rd_next; logic [DATA_W-1:0] encoded_tx_data_reg = '0, encoded_tx_data_next; @@ -221,6 +231,8 @@ logic [PTP_TS_W-1:0] m_axis_tx_cpl_ts_reg = '0, m_axis_tx_cpl_ts_next; logic [TX_TAG_W-1:0] m_axis_tx_cpl_tag_reg = '0, m_axis_tx_cpl_tag_next; logic m_axis_tx_cpl_valid_reg = 1'b0, m_axis_tx_cpl_valid_next; +logic tx_an_cfg_ready_reg = 1'b0, tx_an_cfg_ready_next; + logic start_packet_int_reg = 1'b0, start_packet_int_next; logic start_packet_reg = 1'b0, start_packet_next; @@ -257,6 +269,8 @@ assign m_axis_tx_cpl.tid = m_axis_tx_cpl_tag_reg; assign m_axis_tx_cpl.tdest = '0; assign m_axis_tx_cpl.tuser = '0; +assign tx_an_cfg_ready = AN_EN ? tx_an_cfg_ready_reg : 1'b0; + assign tx_start_packet = start_packet_reg; assign stat_tx_byte = stat_tx_byte_reg; assign stat_tx_pkt_len = stat_tx_pkt_len_reg; @@ -307,10 +321,13 @@ always_comb begin ifg_cnt_next = ifg_cnt_reg; deficit_idle_cnt_next = deficit_idle_cnt_reg; odd_next = odd_reg; + an_phase_next = an_phase_reg; rd_next = rd_reg; s_axis_tx_tready_next = 1'b0; + tx_an_cfg_ready_next = 1'b0; + s_tdata_next = s_tdata_reg; m_axis_tx_cpl_ts_next = m_axis_tx_cpl_ts_reg; @@ -438,6 +455,10 @@ always_comb begin encoded_tx_data_next = CTRL_S; encoded_tx_data_k_next = 1'b1; state_next = STATE_PREAMBLE; + end else if (AN_EN && odd_reg && tx_an_cfg_valid) begin + encoded_tx_data_next = an_phase_reg ? D(2,2) : D(21,5); + encoded_tx_data_k_next = 1'b0; + state_next = STATE_AN; end else begin state_next = STATE_IDLE; end @@ -643,6 +664,22 @@ always_comb begin end end end + STATE_AN: begin + if (AN_EN) begin + // send config register + if (!odd_reg) begin + encoded_tx_data_next = tx_an_cfg[7:0]; + encoded_tx_data_k_next = 1'b0; + state_next = STATE_AN; + end else begin + encoded_tx_data_next = tx_an_cfg[15:8]; + encoded_tx_data_k_next = 1'b0; + tx_an_cfg_ready_next = 1'b1; + an_phase_next = !an_phase_reg; + state_next = STATE_IDLE; + end + end + end default: begin // invalid state, return to idle state_next = STATE_IDLE; @@ -674,15 +711,18 @@ always_ff @(posedge clk) begin ifg_cnt_reg <= ifg_cnt_next; deficit_idle_cnt_reg <= deficit_idle_cnt_next; odd_reg <= odd_next; + an_phase_reg <= an_phase_next; rd_reg <= rd_next; + s_tdata_reg <= s_tdata_next; + + s_axis_tx_tready_reg <= s_axis_tx_tready_next; + m_axis_tx_cpl_ts_reg <= m_axis_tx_cpl_ts_next; m_axis_tx_cpl_tag_reg <= m_axis_tx_cpl_tag_next; m_axis_tx_cpl_valid_reg <= m_axis_tx_cpl_valid_next; - s_tdata_reg <= s_tdata_next; - - s_axis_tx_tready_reg <= s_axis_tx_tready_next; + tx_an_cfg_ready_reg <= tx_an_cfg_ready_next; start_packet_int_reg <= start_packet_int_next; start_packet_reg <= start_packet_next; @@ -722,12 +762,15 @@ always_ff @(posedge clk) begin frame_reg <= 1'b0; odd_reg <= 1'b0; + an_phase_reg <= 1'b0; rd_reg <= 1'b0; s_axis_tx_tready_reg <= 1'b0; m_axis_tx_cpl_valid_reg <= 1'b0; + tx_an_cfg_ready_reg <= 1'b0; + encoded_tx_data_valid_reg <= 1'b0; encoded_tx_data_k_reg <= 1'b0; encoded_tx_data_dm_reg <= 1'b0; diff --git a/src/eth/rtl/taxi_eth_mac_phy_1g_basex_rx.sv b/src/eth/rtl/taxi_eth_mac_phy_1g_basex_rx.sv index c0b8912..c322876 100644 --- a/src/eth/rtl/taxi_eth_mac_phy_1g_basex_rx.sv +++ b/src/eth/rtl/taxi_eth_mac_phy_1g_basex_rx.sv @@ -136,6 +136,7 @@ if (DATA_W == 16) begin .DATA_W(DATA_W), .CTRL_W(CTRL_W), .GBX_IF_EN(GBX_IF_EN), + .AN_EN(1'b0), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W) @@ -156,6 +157,15 @@ if (DATA_W == 16) begin */ .m_axis_rx(m_axis_rx), + /* + * AN config register + */ + .rx_an_cfg(), + .rx_an_cfg_valid(), + .rx_an_ability_match(), + .rx_an_ack_match(), + .rx_an_idle_match(), + /* * PTP */ @@ -194,6 +204,7 @@ end else begin .DATA_W(DATA_W), .CTRL_W(CTRL_W), .GBX_IF_EN(GBX_IF_EN), + .AN_EN(1'b0), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W) ) @@ -213,6 +224,15 @@ end else begin */ .m_axis_rx(m_axis_rx), + /* + * AN config register + */ + .rx_an_cfg(), + .rx_an_cfg_valid(), + .rx_an_ability_match(), + .rx_an_ack_match(), + .rx_an_idle_match(), + /* * PTP */ diff --git a/src/eth/rtl/taxi_eth_mac_phy_1g_basex_tx.sv b/src/eth/rtl/taxi_eth_mac_phy_1g_basex_tx.sv index 2b0ebf1..d8db389 100644 --- a/src/eth/rtl/taxi_eth_mac_phy_1g_basex_tx.sv +++ b/src/eth/rtl/taxi_eth_mac_phy_1g_basex_tx.sv @@ -142,6 +142,7 @@ if (DATA_W == 16) begin .CTRL_W(CTRL_W), .GBX_IF_EN(GBX_IF_EN), .GBX_CNT(1), + .AN_EN(1'b0), .DIC_EN(DIC_EN), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W), @@ -169,6 +170,13 @@ if (DATA_W == 16) begin .tx_gbx_req_stall(tx_gbx_req_stall), .tx_gbx_sync(tx_gbx_sync), + /* + * AN config register + */ + .tx_an_cfg('0), + .tx_an_cfg_valid(1'b0), + .tx_an_cfg_ready(), + /* * PTP */ @@ -205,6 +213,7 @@ end else begin .CTRL_W(CTRL_W), .GBX_IF_EN(GBX_IF_EN), .GBX_CNT(1), + .AN_EN(1'b0), .DIC_EN(DIC_EN), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W), @@ -232,6 +241,13 @@ end else begin .tx_gbx_req_stall(tx_gbx_req_stall), .tx_gbx_sync(tx_gbx_sync), + /* + * AN config register + */ + .tx_an_cfg('0), + .tx_an_cfg_valid(1'b0), + .tx_an_cfg_ready(), + /* * PTP */ diff --git a/src/eth/tb/taxi_axis_basex_rx_16/Makefile b/src/eth/tb/taxi_axis_basex_rx_16/Makefile index ef75f83..ddaa093 100644 --- a/src/eth/tb/taxi_axis_basex_rx_16/Makefile +++ b/src/eth/tb/taxi_axis_basex_rx_16/Makefile @@ -36,6 +36,7 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES))) # module parameters export PARAM_DATA_W := 16 export PARAM_GBX_IF_EN := 0 +export PARAM_AN_EN := 1 export PARAM_PTP_TS_EN := 1 export PARAM_PTP_TS_FMT_TOD := 1 diff --git a/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.py b/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.py index 4dc938f..d76a250 100644 --- a/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.py +++ b/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.py @@ -265,6 +265,38 @@ async def run_test_oversize(dut, gbx_cfg=None, ifg=12): await RisingEdge(dut.clk) +async def run_test_an(dut, gbx_cfg=None): + + tb = TB(dut, gbx_cfg) + + await tb.reset() + + for k in range(16): + an_cfg = 1 << k + + tb.source.set_an_cfg(an_cfg) + + for k in range(20): + await RisingEdge(dut.clk) + + assert int(dut.rx_an_cfg.value) == an_cfg + assert int(dut.rx_an_ability_match.value) + assert int(dut.rx_an_ack_match.value) == bool(an_cfg & 0x4000) + assert not int(dut.rx_an_idle_match.value) + + tb.source.set_an_cfg(None) + + for k in range(20): + await RisingEdge(dut.clk) + + assert not int(dut.rx_an_ability_match.value) + assert not int(dut.rx_an_ack_match.value) + assert int(dut.rx_an_idle_match.value) + + for k in range(10): + await RisingEdge(dut.clk) + + def size_list(): return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)] @@ -287,13 +319,17 @@ if getattr(cocotb, 'top', None) is not None: factory = TestFactory(run_test) factory.add_option("payload_lengths", [size_list]) factory.add_option("payload_data", [incrementing_payload]) - factory.add_option("ifg", list(range(0, 13))) + # factory.add_option("ifg", list(range(0, 13))) factory.add_option("pre_len", [8, 7]) factory.add_option("gbx_cfg", gbx_cfgs) factory.generate_tests() factory = TestFactory(run_test_oversize) - factory.add_option("ifg", list(range(0, 13))) + # factory.add_option("ifg", list(range(0, 13))) + factory.add_option("gbx_cfg", gbx_cfgs) + factory.generate_tests() + + factory = TestFactory(run_test_an) factory.add_option("gbx_cfg", gbx_cfgs) factory.generate_tests() @@ -338,6 +374,7 @@ def test_taxi_axis_basex_rx_16(request, gbx_en): parameters['DATA_W'] = 16 parameters['GBX_IF_EN'] = gbx_en + parameters['AN_EN'] = 1 parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 diff --git a/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.sv b/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.sv index 726d196..4477698 100644 --- a/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.sv +++ b/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.sv @@ -21,6 +21,7 @@ module test_taxi_axis_basex_rx_16 # parameter DATA_W = 16, parameter CTRL_W = DATA_W / 8, parameter logic GBX_IF_EN = 1'b0, + parameter logic AN_EN = 1'b1, parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64 @@ -39,6 +40,12 @@ logic encoded_rx_data_valid; taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(USER_W)) m_axis_rx(); +logic [15:0] rx_an_cfg; +logic rx_an_cfg_valid; +logic rx_an_ability_match; +logic rx_an_ack_match; +logic rx_an_idle_match; + logic [PTP_TS_W-1:0] ptp_ts; logic [15:0] cfg_rx_max_pkt_len; @@ -65,6 +72,7 @@ taxi_axis_basex_rx_16 #( .DATA_W(DATA_W), .CTRL_W(CTRL_W), .GBX_IF_EN(GBX_IF_EN), + .AN_EN(AN_EN), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W) ) @@ -84,6 +92,15 @@ uut ( */ .m_axis_rx(m_axis_rx), + /* + * AN config register + */ + .rx_an_cfg(rx_an_cfg), + .rx_an_cfg_valid(rx_an_cfg_valid), + .rx_an_ability_match(rx_an_ability_match), + .rx_an_ack_match(rx_an_ack_match), + .rx_an_idle_match(rx_an_idle_match), + /* * PTP */ diff --git a/src/eth/tb/taxi_axis_basex_rx_8/Makefile b/src/eth/tb/taxi_axis_basex_rx_8/Makefile index 029ba7a..6b153f1 100644 --- a/src/eth/tb/taxi_axis_basex_rx_8/Makefile +++ b/src/eth/tb/taxi_axis_basex_rx_8/Makefile @@ -36,6 +36,7 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES))) # module parameters export PARAM_DATA_W := 8 export PARAM_GBX_IF_EN := 0 +export PARAM_AN_EN := 1 export PARAM_PTP_TS_EN := 1 export PARAM_PTP_TS_FMT_TOD := 1 diff --git a/src/eth/tb/taxi_axis_basex_rx_8/test_taxi_axis_basex_rx_8.py b/src/eth/tb/taxi_axis_basex_rx_8/test_taxi_axis_basex_rx_8.py index ed6972a..1bfc97f 100644 --- a/src/eth/tb/taxi_axis_basex_rx_8/test_taxi_axis_basex_rx_8.py +++ b/src/eth/tb/taxi_axis_basex_rx_8/test_taxi_axis_basex_rx_8.py @@ -265,6 +265,38 @@ async def run_test_oversize(dut, gbx_cfg=None, ifg=12): await RisingEdge(dut.clk) +async def run_test_an(dut, gbx_cfg=None): + + tb = TB(dut, gbx_cfg) + + await tb.reset() + + for k in range(16): + an_cfg = 1 << k + + tb.source.set_an_cfg(an_cfg) + + for k in range(20): + await RisingEdge(dut.clk) + + assert int(dut.rx_an_cfg.value) == an_cfg + assert int(dut.rx_an_ability_match.value) + assert int(dut.rx_an_ack_match.value) == bool(an_cfg & 0x4000) + assert not int(dut.rx_an_idle_match.value) + + tb.source.set_an_cfg(None) + + for k in range(20): + await RisingEdge(dut.clk) + + assert not int(dut.rx_an_ability_match.value) + assert not int(dut.rx_an_ack_match.value) + assert int(dut.rx_an_idle_match.value) + + for k in range(10): + await RisingEdge(dut.clk) + + def size_list(): return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)] @@ -297,6 +329,10 @@ if getattr(cocotb, 'top', None) is not None: factory.add_option("gbx_cfg", gbx_cfgs) factory.generate_tests() + factory = TestFactory(run_test_an) + factory.add_option("gbx_cfg", gbx_cfgs) + factory.generate_tests() + # cocotb-test @@ -338,6 +374,7 @@ def test_taxi_axis_basex_rx_8(request, gbx_en): parameters['DATA_W'] = 8 parameters['GBX_IF_EN'] = gbx_en + parameters['AN_EN'] = 1 parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 diff --git a/src/eth/tb/taxi_axis_basex_rx_8/test_taxi_axis_basex_rx_8.sv b/src/eth/tb/taxi_axis_basex_rx_8/test_taxi_axis_basex_rx_8.sv index bd273dd..5b4d1bb 100644 --- a/src/eth/tb/taxi_axis_basex_rx_8/test_taxi_axis_basex_rx_8.sv +++ b/src/eth/tb/taxi_axis_basex_rx_8/test_taxi_axis_basex_rx_8.sv @@ -21,6 +21,7 @@ module test_taxi_axis_basex_rx_8 # parameter DATA_W = 8, parameter CTRL_W = DATA_W / 8, parameter logic GBX_IF_EN = 1'b0, + parameter logic AN_EN = 1'b1, parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64 @@ -39,6 +40,12 @@ logic encoded_rx_data_valid; taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(USER_W)) m_axis_rx(); +logic [15:0] rx_an_cfg; +logic rx_an_cfg_valid; +logic rx_an_ability_match; +logic rx_an_ack_match; +logic rx_an_idle_match; + logic [PTP_TS_W-1:0] ptp_ts; logic [15:0] cfg_rx_max_pkt_len; @@ -65,6 +72,7 @@ taxi_axis_basex_rx_8 #( .DATA_W(DATA_W), .CTRL_W(CTRL_W), .GBX_IF_EN(GBX_IF_EN), + .AN_EN(AN_EN), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W) ) @@ -84,6 +92,15 @@ uut ( */ .m_axis_rx(m_axis_rx), + /* + * AN config register + */ + .rx_an_cfg(rx_an_cfg), + .rx_an_cfg_valid(rx_an_cfg_valid), + .rx_an_ability_match(rx_an_ability_match), + .rx_an_ack_match(rx_an_ack_match), + .rx_an_idle_match(rx_an_idle_match), + /* * PTP */ diff --git a/src/eth/tb/taxi_axis_basex_tx_16/Makefile b/src/eth/tb/taxi_axis_basex_tx_16/Makefile index 6228254..d149d72 100644 --- a/src/eth/tb/taxi_axis_basex_tx_16/Makefile +++ b/src/eth/tb/taxi_axis_basex_tx_16/Makefile @@ -37,6 +37,7 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES))) export PARAM_DATA_W := 16 export PARAM_GBX_IF_EN := 0 export PARAM_GBX_CNT := 1 +export PARAM_AN_EN := 1 export PARAM_DIC_EN := 1 export PARAM_PTP_TS_EN := 1 export PARAM_PTP_TS_W := 96 diff --git a/src/eth/tb/taxi_axis_basex_tx_16/test_taxi_axis_basex_tx_16.py b/src/eth/tb/taxi_axis_basex_tx_16/test_taxi_axis_basex_tx_16.py index d07673e..1e1af65 100644 --- a/src/eth/tb/taxi_axis_basex_tx_16/test_taxi_axis_basex_tx_16.py +++ b/src/eth/tb/taxi_axis_basex_tx_16/test_taxi_axis_basex_tx_16.py @@ -67,6 +67,9 @@ class TB: self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk) self.tx_cpl_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_tx_cpl), dut.clk, dut.rst) + dut.tx_an_cfg.setimmediatevalue(0) + dut.tx_an_cfg_valid.setimmediatevalue(0) + dut.cfg_tx_max_pkt_len.setimmediatevalue(0) dut.cfg_tx_ifg.setimmediatevalue(0) dut.cfg_tx_enable.setimmediatevalue(0) @@ -378,6 +381,39 @@ async def run_test_oversize(dut, gbx_cfg=None, ifg=12): await RisingEdge(dut.clk) +async def run_test_an(dut, gbx_cfg=None): + + tb = TB(dut, gbx_cfg) + + await tb.reset() + + for k in range(16): + an_cfg = 1 << k + + dut.tx_an_cfg.value = an_cfg + dut.tx_an_cfg_valid.value = 1 + + for k in range(20): + await RisingEdge(dut.clk) + + assert tb.sink.get_an_cfg() == an_cfg + assert tb.sink.get_an_ability_match() + assert tb.sink.get_an_ack_match() == bool(an_cfg & 0x4000) + assert not tb.sink.get_an_idle_match() + + dut.tx_an_cfg_valid.value = 0 + + for k in range(20): + await RisingEdge(dut.clk) + + assert not tb.sink.get_an_ability_match() + assert not tb.sink.get_an_ack_match() + assert tb.sink.get_an_idle_match() + + for k in range(10): + await RisingEdge(dut.clk) + + def size_list(): return list(range(16, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)] @@ -415,6 +451,10 @@ if getattr(cocotb, 'top', None) is not None: factory.add_option("gbx_cfg", gbx_cfgs) factory.generate_tests() + factory = TestFactory(run_test_an) + factory.add_option("gbx_cfg", gbx_cfgs) + factory.generate_tests() + # cocotb-test @@ -459,6 +499,7 @@ def test_taxi_axis_basex_tx_16(request, gbx_en, dic_en): parameters['CTRL_W'] = parameters['DATA_W'] // 8 parameters['GBX_IF_EN'] = gbx_en parameters['GBX_CNT'] = 1 + parameters['AN_EN'] = 1 parameters['DIC_EN'] = dic_en parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_W'] = 96 diff --git a/src/eth/tb/taxi_axis_basex_tx_16/test_taxi_axis_basex_tx_16.sv b/src/eth/tb/taxi_axis_basex_tx_16/test_taxi_axis_basex_tx_16.sv index fe080a3..f611af4 100644 --- a/src/eth/tb/taxi_axis_basex_tx_16/test_taxi_axis_basex_tx_16.sv +++ b/src/eth/tb/taxi_axis_basex_tx_16/test_taxi_axis_basex_tx_16.sv @@ -22,6 +22,7 @@ module test_taxi_axis_basex_tx_16 # parameter CTRL_W = DATA_W / 8, parameter logic GBX_IF_EN = 1'b0, parameter GBX_CNT = 1, + parameter logic AN_EN = 1'b1, parameter logic DIC_EN = 1'b1, parameter logic PTP_TS_EN = 1'b0, parameter PTP_TS_W = 96, @@ -48,6 +49,10 @@ logic [GBX_CNT-1:0] tx_gbx_req_sync; logic tx_gbx_req_stall; logic [GBX_CNT-1:0] tx_gbx_sync; +logic [15:0] tx_an_cfg; +logic tx_an_cfg_valid; +logic tx_an_cfg_ready; + logic [PTP_TS_W-1:0] ptp_ts; logic [15:0] cfg_tx_max_pkt_len; @@ -72,6 +77,7 @@ taxi_axis_basex_tx_16 #( .CTRL_W(CTRL_W), .GBX_IF_EN(GBX_IF_EN), .GBX_CNT(GBX_CNT), + .AN_EN(AN_EN), .DIC_EN(DIC_EN), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W), @@ -99,6 +105,13 @@ uut ( .tx_gbx_req_stall(tx_gbx_req_stall), .tx_gbx_sync(tx_gbx_sync), + /* + * AN config register + */ + .tx_an_cfg(tx_an_cfg), + .tx_an_cfg_valid(tx_an_cfg_valid), + .tx_an_cfg_ready(tx_an_cfg_ready), + /* * PTP */ diff --git a/src/eth/tb/taxi_axis_basex_tx_8/Makefile b/src/eth/tb/taxi_axis_basex_tx_8/Makefile index 5ca8c40..2b2bd17 100644 --- a/src/eth/tb/taxi_axis_basex_tx_8/Makefile +++ b/src/eth/tb/taxi_axis_basex_tx_8/Makefile @@ -39,6 +39,7 @@ export PARAM_PADDING_EN := 1 export PARAM_MIN_FRAME_LEN := 64 export PARAM_GBX_IF_EN := 0 export PARAM_GBX_CNT := 1 +export PARAM_AN_EN := 1 export PARAM_DIC_EN := 1 export PARAM_PTP_TS_EN := 1 export PARAM_PTP_TS_FMT_TOD := 1 diff --git a/src/eth/tb/taxi_axis_basex_tx_8/test_taxi_axis_basex_tx_8.py b/src/eth/tb/taxi_axis_basex_tx_8/test_taxi_axis_basex_tx_8.py index e33c308..08adac8 100644 --- a/src/eth/tb/taxi_axis_basex_tx_8/test_taxi_axis_basex_tx_8.py +++ b/src/eth/tb/taxi_axis_basex_tx_8/test_taxi_axis_basex_tx_8.py @@ -67,6 +67,9 @@ class TB: self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk) self.tx_cpl_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_tx_cpl), dut.clk, dut.rst) + dut.tx_an_cfg.setimmediatevalue(0) + dut.tx_an_cfg_valid.setimmediatevalue(0) + dut.cfg_tx_max_pkt_len.setimmediatevalue(0) dut.cfg_tx_ifg.setimmediatevalue(0) dut.cfg_tx_enable.setimmediatevalue(0) @@ -378,6 +381,39 @@ async def run_test_oversize(dut, gbx_cfg=None, ifg=12): await RisingEdge(dut.clk) +async def run_test_an(dut, gbx_cfg=None): + + tb = TB(dut, gbx_cfg) + + await tb.reset() + + for k in range(16): + an_cfg = 1 << k + + dut.tx_an_cfg.value = an_cfg + dut.tx_an_cfg_valid.value = 1 + + for k in range(20): + await RisingEdge(dut.clk) + + assert tb.sink.get_an_cfg() == an_cfg + assert tb.sink.get_an_ability_match() + assert tb.sink.get_an_ack_match() == bool(an_cfg & 0x4000) + assert not tb.sink.get_an_idle_match() + + dut.tx_an_cfg_valid.value = 0 + + for k in range(20): + await RisingEdge(dut.clk) + + assert not tb.sink.get_an_ability_match() + assert not tb.sink.get_an_ack_match() + assert tb.sink.get_an_idle_match() + + for k in range(10): + await RisingEdge(dut.clk) + + def size_list(): return list(range(16, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)] @@ -415,6 +451,10 @@ if getattr(cocotb, 'top', None) is not None: factory.add_option("gbx_cfg", gbx_cfgs) factory.generate_tests() + factory = TestFactory(run_test_an) + factory.add_option("gbx_cfg", gbx_cfgs) + factory.generate_tests() + # cocotb-test @@ -461,6 +501,7 @@ def test_taxi_axis_basex_tx_8(request, gbx_en, dic_en): parameters['MIN_FRAME_LEN'] = 64 parameters['GBX_IF_EN'] = gbx_en parameters['GBX_CNT'] = 1 + parameters['AN_EN'] = 1 parameters['DIC_EN'] = dic_en parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_FMT_TOD'] = 1 diff --git a/src/eth/tb/taxi_axis_basex_tx_8/test_taxi_axis_basex_tx_8.sv b/src/eth/tb/taxi_axis_basex_tx_8/test_taxi_axis_basex_tx_8.sv index 9e2c8d3..0944226 100644 --- a/src/eth/tb/taxi_axis_basex_tx_8/test_taxi_axis_basex_tx_8.sv +++ b/src/eth/tb/taxi_axis_basex_tx_8/test_taxi_axis_basex_tx_8.sv @@ -24,6 +24,7 @@ module test_taxi_axis_basex_tx_8 # parameter MIN_FRAME_LEN = 64, parameter logic GBX_IF_EN = 1'b0, parameter GBX_CNT = 1, + parameter logic AN_EN = 1'b1, parameter logic DIC_EN = 1'b1, parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_FMT_TOD = 1'b1, @@ -51,6 +52,10 @@ logic [GBX_CNT-1:0] tx_gbx_req_sync; logic tx_gbx_req_stall; logic [GBX_CNT-1:0] tx_gbx_sync; +logic [15:0] tx_an_cfg; +logic tx_an_cfg_valid; +logic tx_an_cfg_ready; + logic [PTP_TS_W-1:0] ptp_ts; logic [15:0] cfg_tx_max_pkt_len; @@ -77,7 +82,8 @@ taxi_axis_basex_tx_8 #( .MIN_FRAME_LEN(MIN_FRAME_LEN), .GBX_IF_EN(GBX_IF_EN), .GBX_CNT(GBX_CNT), - // .DIC_EN(DIC_EN), + .AN_EN(AN_EN), + .DIC_EN(DIC_EN), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W), .TX_CPL_CTRL_IN_TUSER(TX_CPL_CTRL_IN_TUSER) @@ -104,6 +110,13 @@ uut ( .tx_gbx_req_stall(tx_gbx_req_stall), .tx_gbx_sync(tx_gbx_sync), + /* + * AN config register + */ + .tx_an_cfg(tx_an_cfg), + .tx_an_cfg_valid(tx_an_cfg_valid), + .tx_an_cfg_ready(tx_an_cfg_ready), + /* * PTP */