10G/25G Ethernet Subsystem(4.1) IP理解和使用 Versal新版本IP
首先新建子系统IP到Block Design:



右键IP,打开example design,然后右键xxv_ethernet_0_exdes_support.bd点击Generate Output Products,这一步是为了产生仿真所需的文件,然后就可以仿真了

仿真大概56us的时候,就就开始产生信号了,

我们现在开始分析一下工程的原理,
我们主要需要关注的是如何应用,也就是说,我们需要理解顶层的链接方法,还有产生测试数据并比对的实现原理:
xxv_ethernet_0_exdes代码功能分析:
`timescale 1fs / 1fs
(* DowngradeIPIdentifiedWarnings="yes" *) // 降低IP核识别警告级别
module xxv_ethernet_0_exdes (
// 高速收发器差分接口
input  wire [1-1:0] gt_rxp_in,   // GT差分正输入(1通道)
input  wire [1-1:0] gt_rxn_in,   // GT差分负输入(1通道)
output wire [1-1:0] gt_txp_out,  // GT差分正输出(1通道)
output wire [1-1:0] gt_txn_out,  // GT差分负输出(1通道)
// 控制信号
input wire restart_tx_rx_0,       // 收发器重启控制(触发复位序列)
input wire send_continous_pkts_0, // 连续数据包发送使能(测试模式)
// 状态指示
output wire rx_gt_locked_led_0,   // GT时钟恢复锁定状态指示
output wire rx_block_lock_led_0,  // 核心数据块锁定状态指示
output wire [4:0] completion_status, // 初始化完成状态码(0=成功)
output wire stat_reg_compare,     // 寄存器配置校验结果
// 系统信号
input sys_reset,    // 全局异步复位(高有效)
input gt_refclk_p,  // GT参考时钟正端(高速时钟输入)
input gt_refclk_n,  // GT参考时钟负端
input dclk          // 数字逻辑时钟(用于控制逻辑)
);
parameter PKT_NUM = 20;  // 测试模式数据包发送数量(影响性能测试)
// 用户接口就绪信号(bit0=TX就绪,bit1=RX就绪)
wire [31:0] ub_ready;
//// AXI4-Lite配置接口(寄存器访问)
wire        s_axi_aclk_0;  // AXI-Lite接口时钟(通常连接到dclk)
wire        s_axi_aresetn_0;  // AXI-Lite异步复位(低有效)
// 写地址通道信号
wire [31:0] s_axi_awaddr_0;  // 写地址总线(32位地址)
wire        s_axi_awvalid_0;  // 写地址有效指示
wire        s_axi_awready_0;  // 写地址就绪响应
// 写数据通道信号
wire [31:0] s_axi_wdata_0;  // 写数据总线(32位数据)
wire [ 3:0] s_axi_wstrb_0;  // 字节使能信号(4位,每位对应1字节)
wire        s_axi_wvalid_0;  // 写数据有效指示
wire        s_axi_wready_0;  // 写数据就绪响应
// 写响应通道信号
wire [ 1:0] s_axi_bresp_0;  // 写响应状态(00=OKAY)
wire        s_axi_bvalid_0;  // 写响应有效指示
wire        s_axi_bready_0;  // 写响应接收就绪
// 读地址通道信号
wire [31:0] s_axi_araddr_0;  // 读地址总线(32位地址)
wire        s_axi_arvalid_0;  // 读地址有效指示
wire        s_axi_arready_0;  // 读地址就绪响应
// 读数据通道信号
wire [31:0] s_axi_rdata_0;  // 读数据总线(32位数据)
wire [ 1:0] s_axi_rresp_0;  // 读响应状态(00=OKAY)
wire        s_axi_rvalid_0;  // 读数据有效指示
wire        s_axi_rready_0;  // 读数据接收就绪
// 性能监控时钟(用于统计计数器)
wire        pm_tick_0;
wire        stat_reg_compare_0;  // 寄存器配置校验结果(硬件校验)
wire        gt_loopback_out_0;  // GT环回模式状态指示
wire        block_lock_led_0;  // 数据通路块锁定状态
wire        rx_core_clk_0;  // 接收核心时钟(来自GT恢复时钟)
wire        rx_clk_out_0;  // 接收时钟输出(连接到外部时钟网络)
wire        tx_clk_out_0;  // 发送时钟输出(连接到外部时钟网络)
// 时钟连接(使用接收时钟作为核心时钟)
assign rx_core_clk_0 = rx_clk_out_0;
//// 接收模块信号
wire        rx_reset_0;  // 接收模块复位(同步到rx_core_clk)
wire        user_rx_reset_0;  // 用户域接收复位(跨时钟域同步后)
wire        rxrecclkout_0;  // 恢复时钟输出(来自GT的恢复时钟)
//// 接收AXIS接口(64位数据路径)
wire        rx_axis_tvalid_0;  // 接收数据有效指示
wire [63:0] rx_axis_tdata_0;  // 接收数据总线(64位数据)
wire        rx_axis_tlast_0;  // 帧结束标志(TLAST有效时)
wire [ 7:0] rx_axis_tkeep_0;  // 字节有效指示(8位,每位对应8字节)
wire        rx_axis_tuser_0;  // 用户信号(携带错误标志等)
wire [55:0] rx_preambleout_0;  // 接收前导码输出(可选功能)
//// 接收状态统计信号(文档表24、41)
wire        stat_rx_block_lock_0;  // 数据块锁定状态(PCS层对齐)
// 帧错误检测
wire        stat_rx_framing_err_valid_0;  // 帧对齐错误有效指示
wire        stat_rx_framing_err_0;  // 帧对齐错误标志
// 物理层状态
wire        stat_rx_hi_ber_0;  // 高误码率告警(BER超过阈值)
wire        stat_rx_valid_ctrl_code_0;  // 有效控制字符检测
wire        stat_rx_bad_code_0;  // 无效控制字符检测
// 数据包统计(文档表89-90)
wire [ 1:0] stat_rx_total_packets_0;  // 总接收包数(递增计数)
wire        stat_rx_total_good_packets_0;  // 有效包数(无错误)
wire [ 3:0] stat_rx_total_bytes_0;  // 总字节数(低4位)
wire [13:0] stat_rx_total_good_bytes_0;  // 有效字节数(高14位)
// 数据包尺寸统计
wire        stat_rx_packet_small_0;  // 过小包(<64字节)
wire        stat_rx_jabber_0;  // 过长包(>1518字节)
wire        stat_rx_packet_large_0;  // 大包(>1518字节)
wire        stat_rx_oversize_0;  // 超长包(>1518字节)
wire        stat_rx_undersize_0;  // 过小包(<64字节)
wire        stat_rx_toolong_0;  // 超长包(>9216字节)
wire        stat_rx_fragment_0;  // 碎片包(<64字节且FCS错误)
wire        stat_rx_packet_64_bytes_0;  // 64字节包
wire        stat_rx_packet_65_127_bytes_0;  // 65-127字节包
wire        stat_rx_packet_128_255_bytes_0;  // 128-255字节包
wire        stat_rx_packet_256_511_bytes_0;  // 256-511字节包
wire        stat_rx_packet_512_1023_bytes_0;  // 512-1023字节包
wire        stat_rx_packet_1024_1518_bytes_0;  // 1024-1518字节包
wire        stat_rx_packet_1519_1522_bytes_0;  // 1519-1522字节包(VLAN)
wire        stat_rx_packet_1523_1548_bytes_0;  // 1523-1548字节包
// FCS错误统计
wire [ 1:0] stat_rx_bad_fcs_0;  // FCS错误包计数
wire        stat_rx_packet_bad_fcs_0;  // FCS错误包标志
wire [ 1:0] stat_rx_stomped_fcs_0;  // 被覆盖的FCS错误
// 大尺寸包统计
wire        stat_rx_packet_1549_2047_bytes_0;  // 1549-2047字节包
wire        stat_rx_packet_2048_4095_bytes_0;  // 2048-4095字节包
wire        stat_rx_packet_4096_8191_bytes_0;  // 4096-8191字节包
wire        stat_rx_packet_8192_9215_bytes_0;  // 8192-9215字节包(Jumbo帧)
// 数据包类型统计
wire        stat_rx_unicast_0;  // 单播包
wire        stat_rx_multicast_0;  // 组播包
wire        stat_rx_broadcast_0;  // 广播包
wire        stat_rx_vlan_0;  // VLAN标记包
wire        stat_rx_inrangeerr_0;  // 长度/类型字段越界
// 物理层错误
wire        stat_rx_bad_preamble_0;  // 前导码错误
wire        stat_rx_bad_sfd_0;  // 帧起始定界符错误
wire        stat_rx_got_signal_os_0;  // 信号有序集检测
wire        stat_rx_test_pattern_mismatch_0;  // 测试模式匹配错误
wire        stat_rx_truncated_0;  // 截断包(接收缓冲溢出)
wire        stat_rx_local_fault_0;  // 本地故障状态(PCS层)
wire        stat_rx_remote_fault_0;  // 远端故障状态(来自链路伙伴)
wire        stat_rx_internal_local_fault_0;  // 内部本地故障
wire        stat_rx_received_local_fault_0;  // 接收到的本地故障
wire        stat_rx_status_0;  // 接收状态汇总
//// 发送模块信号
wire        tx_reset_0;  // 发送模块复位(同步到tx_clk_out)
wire        user_tx_reset_0;  // 用户域发送复位(跨时钟域同步后)
//// 发送AXIS接口(64位数据路径)
wire        tx_axis_tready_0;  // 发送就绪指示(背压信号)
wire        tx_axis_tvalid_0;  // 发送数据有效指示
wire [63:0] tx_axis_tdata_0;  // 发送数据总线(64位数据)
wire        tx_axis_tlast_0;  // 帧结束标志
wire [ 7:0] tx_axis_tkeep_0;  // 字节有效指示(8位)
wire        tx_axis_tuser_0;  // 用户信号(携带错误注入等)
wire        tx_unfout_0;  // 未完成帧输出(异常终止标志)
wire [55:0] tx_preamblein_0;  // 自定义前导码输入
//// 发送控制信号(文档表23)
wire        ctl_tx_send_lfi_0;  // 发送本地故障指示(LFI优先级最高)
wire        ctl_tx_send_rfi_0;  // 发送远端故障指示(RFI)
wire        ctl_tx_send_idle_0;  // 发送空闲字符(链路维护)
//// 发送状态统计
wire        stat_tx_total_packets_0;  // 总发送包数
wire [ 3:0] stat_tx_total_bytes_0;  // 总发送字节数(低4位)
wire        stat_tx_total_good_packets_0;  // 有效发送包数
wire [13:0] stat_tx_total_good_bytes_0;  // 有效发送字节数(高14位)
// 数据包尺寸统计(与接收侧对应)
wire        stat_tx_packet_64_bytes_0;
wire        stat_tx_packet_65_127_bytes_0;
wire        stat_tx_packet_128_255_bytes_0;
wire        stat_tx_packet_256_511_bytes_0;
wire        stat_tx_packet_512_1023_bytes_0;
wire        stat_tx_packet_1024_1518_bytes_0;
wire        stat_tx_packet_1519_1522_bytes_0;
wire        stat_tx_packet_1523_1548_bytes_0;
wire        stat_tx_packet_small_0;
wire        stat_tx_packet_large_0;
wire        stat_tx_packet_1549_2047_bytes_0;
wire        stat_tx_packet_2048_4095_bytes_0;
wire        stat_tx_packet_4096_8191_bytes_0;
wire        stat_tx_packet_8192_9215_bytes_0;
// 数据包类型统计
wire        stat_tx_unicast_0;
wire        stat_tx_multicast_0;
wire        stat_tx_broadcast_0;
wire        stat_tx_vlan_0;
// 发送错误统计
wire        stat_tx_bad_fcs_0;  // FCS错误包
wire        stat_tx_frame_error_0;  // 帧格式错误
wire        stat_tx_local_fault_0;  // 本地故障状态
// GT状态信号
wire        gtpowergood_out_0;  // GT电源就绪指示
wire [ 2:0] txoutclksel_in_0;  // 发送时钟选择(固定101)
wire [ 2:0] rxoutclksel_in_0;  // 接收时钟选择(固定101)
assign txoutclksel_in_0 = 3'b101;  // GT向导推荐配置
assign rxoutclksel_in_0 = 3'b101;
// 状态指示逻辑(组合逻辑)
assign rx_block_lock_led_0 = block_lock_led_0 & stat_rx_status_0;
// 用户寄存器接口
wire [31:0] user_reg0_0;  // 用户自定义寄存器0
wire        qpllreset_in_0;  // QPLL复位控制(默认禁用)
assign qpllreset_in_0 = 1'b0;
// 内部信号
wire [4:0] completion_status_0;  // 初始化状态码
wire       gt_refclk_out;  // GT参考时钟缓冲输出
wire [3:0] gt_txn_out_int_0;  // GT差分输出内部信号
wire [3:0] gt_txp_out_int_0;
// 差分信号连接(单通道模式)
assign gt_txn_out = gt_txn_out_int_0[0];
assign gt_txp_out = gt_txp_out_int_0[0];
// 复位同步逻辑(文档图20、21)
wire user_rx_reset_int_0;  // 用户域RX复位请求
wire user_tx_reset_int_0;  // 用户域TX复位请求
wire rx_resetdone_out_0;  // RX复位完成指示
wire tx_resetdone_out_0;  // TX复位完成指示
// RX复位同步器(跨时钟域)
xxv_ethernet_0_cdc_sync_2stage #(
.WIDTH(1)
) i_xxv_ethernet_0_user_rx_reset_syncer (
.clk       (rx_core_clk_0),        // 目标时钟域:接收核心时钟
.signal_in (user_rx_reset_int_0),  // 源信号(异步复位)
.signal_out(user_rx_reset_0)       // 同步后的复位信号
);
// TX复位同步器(跨时钟域)
xxv_ethernet_0_cdc_sync_2stage #(
.WIDTH(1)
) i_xxv_ethernet_0_user_tx_reset_syncer (
.clk       (tx_clk_out_0),         // 目标时钟域:发送时钟
.signal_in (user_tx_reset_int_0),  // 源信号(异步复位)
.signal_out(user_tx_reset_0)       // 同步后的复位信号
);
// 复位逻辑(依赖复位完成信号)
assign user_rx_reset_int_0 = ~rx_resetdone_out_0;  // 复位未完成时保持复位
assign user_tx_reset_int_0 = ~rx_resetdone_out_0;
// 核心支持模块实例化(包含GT、PCS、MAC)
xxv_ethernet_0_exdes_support_wrapper i_xxv_ethernet_0_exdes_support_wrapper (
.gpo_0(ub_ready),
.xxv_ethernet_0_core_diff_gt_ref_clock_clk_n(gt_refclk_n),
.xxv_ethernet_0_core_diff_gt_ref_clock_clk_p(gt_refclk_p),
.axis_rx_0_0_tdata(rx_axis_tdata_0),
.axis_rx_0_0_tkeep(rx_axis_tkeep_0),
.axis_rx_0_0_tlast(rx_axis_tlast_0),
.axis_rx_0_0_tuser(rx_axis_tuser_0),
.axis_rx_0_0_tvalid(rx_axis_tvalid_0),
.axis_tx_0_0_tdata(tx_axis_tdata_0),
.axis_tx_0_0_tkeep(tx_axis_tkeep_0),
.axis_tx_0_0_tlast(tx_axis_tlast_0),
.axis_tx_0_0_tready(tx_axis_tready_0),
.axis_tx_0_0_tuser(tx_axis_tuser_0),
.axis_tx_0_0_tvalid(tx_axis_tvalid_0),
.s_axi_0_0_araddr(s_axi_araddr_0),
.s_axi_0_0_arready(s_axi_arready_0),
.s_axi_0_0_arvalid(s_axi_arvalid_0),
.s_axi_0_0_awaddr(s_axi_awaddr_0),
.s_axi_0_0_awready(s_axi_awready_0),
.s_axi_0_0_awvalid(s_axi_awvalid_0),
.s_axi_0_0_bready(s_axi_bready_0),
.s_axi_0_0_bresp(s_axi_bresp_0),
.s_axi_0_0_bvalid(s_axi_bvalid_0),
.s_axi_0_0_rdata(s_axi_rdata_0),
.s_axi_0_0_rready(s_axi_rready_0),
.s_axi_0_0_rresp(s_axi_rresp_0),
.s_axi_0_0_rvalid(s_axi_rvalid_0),
.s_axi_0_0_wdata(s_axi_wdata_0),
.s_axi_0_0_wready(s_axi_wready_0),
.s_axi_0_0_wstrb(s_axi_wstrb_0),
.s_axi_0_0_wvalid(s_axi_wvalid_0),
.s_axi_aclk_0_0(s_axi_aclk_0),
.s_axi_aresetn_0_0(s_axi_aresetn_0),
.pm_tick_0_0(pm_tick_0),
.user_reg0_0_0(user_reg0_0),
.ctl_tx_0_0_ctl_tx_send_idle(ctl_tx_send_idle_0),
.ctl_tx_0_0_ctl_tx_send_lfi(ctl_tx_send_lfi_0),
.ctl_tx_0_0_ctl_tx_send_rfi(ctl_tx_send_rfi_0),
.gt_rxn_in_0({3'b0, gt_rxn_in}),
.gt_rxp_in_0({3'b0, gt_rxp_in}),
.gt_txn_out_0(gt_txn_out_int_0),
.gt_txp_out_0(gt_txp_out_int_0),
.rx_resetdone_out_0_0(rx_resetdone_out_0),
.tx_resetdone_out_0_0(tx_resetdone_out_0),
.rx_core_clk_0(rx_clk_out_0),
.rx_reset_0(user_rx_reset_0),
.rx_serdes_clk_0(rx_clk_out_0),
.rx_usrclk_out_0(rx_clk_out_0),
.rx_preambleout_0_0                        (rx_preambleout_0),
.tx_preamblein_0                           (tx_preamblein_0),
.tx_unfout_0                               (tx_unfout_0),
.stat_rx_0_0_stat_rx_block_lock            (stat_rx_block_lock_0),
.stat_rx_0_0_stat_rx_framing_err           (stat_rx_framing_err_0),
.stat_rx_0_0_stat_rx_framing_err_valid     (stat_rx_framing_err_valid_0),
.stat_rx_0_0_stat_rx_hi_ber                (stat_rx_hi_ber_0),
.stat_rx_0_0_stat_rx_valid_ctrl_code       (stat_rx_valid_ctrl_code_0),
.stat_rx_0_0_stat_rx_bad_code              (stat_rx_bad_code_0),
.stat_rx_0_0_stat_rx_local_fault           (stat_rx_local_fault_0),
.stat_rx_status_0_0                        (stat_rx_status_0),
.stat_rx_0_0_stat_rx_bad_fcs               (stat_rx_bad_fcs_0),
.stat_rx_0_0_stat_rx_bad_preamble          (stat_rx_bad_preamble_0),
.stat_rx_0_0_stat_rx_bad_sfd               (stat_rx_bad_sfd_0),
.stat_rx_0_0_stat_rx_fragment              (stat_rx_fragment_0),
.stat_rx_0_0_stat_rx_got_signal_os         (stat_rx_got_signal_os_0),
.stat_rx_0_0_stat_rx_internal_local_fault  (stat_rx_internal_local_fault_0),
.stat_rx_0_0_stat_rx_jabber                (stat_rx_jabber_0),
.stat_rx_0_0_stat_rx_oversize              (stat_rx_oversize_0),
.stat_rx_0_0_stat_rx_packet_1024_1518_bytes(stat_rx_packet_1024_1518_bytes_0),
.stat_rx_0_0_stat_rx_packet_128_255_bytes  (stat_rx_packet_128_255_bytes_0),
.stat_rx_0_0_stat_rx_packet_1519_1522_bytes(stat_rx_packet_1519_1522_bytes_0),
.stat_rx_0_0_stat_rx_packet_1523_1548_bytes(stat_rx_packet_1523_1548_bytes_0),
.stat_rx_0_0_stat_rx_packet_1549_2047_bytes(stat_rx_packet_1549_2047_bytes_0),
.stat_rx_0_0_stat_rx_packet_2048_4095_bytes(stat_rx_packet_2048_4095_bytes_0),
.stat_rx_0_0_stat_rx_packet_256_511_bytes  (stat_rx_packet_256_511_bytes_0),
.stat_rx_0_0_stat_rx_packet_4096_8191_bytes(stat_rx_packet_4096_8191_bytes_0),
.stat_rx_0_0_stat_rx_packet_512_1023_bytes (stat_rx_packet_512_1023_bytes_0),
.stat_rx_0_0_stat_rx_packet_64_bytes       (stat_rx_packet_64_bytes_0),
.stat_rx_0_0_stat_rx_packet_65_127_bytes   (stat_rx_packet_65_127_bytes_0),
.stat_rx_0_0_stat_rx_packet_8192_9215_bytes(stat_rx_packet_8192_9215_bytes_0),
.stat_rx_0_0_stat_rx_packet_bad_fcs        (stat_rx_packet_bad_fcs_0),
.stat_rx_0_0_stat_rx_packet_large          (stat_rx_packet_large_0),
.stat_rx_0_0_stat_rx_packet_small          (stat_rx_packet_small_0),
.stat_rx_0_0_stat_rx_received_local_fault  (stat_rx_received_local_fault_0),
.stat_rx_0_0_stat_rx_remote_fault          (stat_rx_remote_fault_0),
.stat_rx_0_0_stat_rx_stomped_fcs           (stat_rx_stomped_fcs_0),
.stat_rx_0_0_stat_rx_test_pattern_mismatch (stat_rx_test_pattern_mismatch_0),
.stat_rx_0_0_stat_rx_toolong               (stat_rx_toolong_0),
.stat_rx_0_0_stat_rx_total_bytes           (stat_rx_total_bytes_0),
.stat_rx_0_0_stat_rx_total_good_bytes      (stat_rx_total_good_bytes_0),
.stat_rx_0_0_stat_rx_total_good_packets    (stat_rx_total_good_packets_0),
.stat_rx_0_0_stat_rx_total_packets         (stat_rx_total_packets_0),
.stat_rx_0_0_stat_rx_truncated             (stat_rx_truncated_0),
.stat_rx_0_0_stat_rx_undersize             (stat_rx_undersize_0),
.stat_rx_0_0_stat_rx_vlan                  (stat_rx_vlan_0),
.stat_rx_0_0_stat_rx_unicast               (stat_rx_unicast_0),
.stat_rx_0_0_stat_rx_multicast             (stat_rx_multicast_0),
.stat_rx_0_0_stat_rx_broadcast             (stat_rx_broadcast_0),
.stat_rx_0_0_stat_rx_inrangeerr            (stat_rx_inrangeerr_0),
.stat_tx_0_0_stat_tx_bad_fcs               (stat_tx_bad_fcs_0),
.stat_tx_0_0_stat_tx_frame_error           (stat_tx_frame_error_0),
.stat_tx_0_0_stat_tx_packet_1024_1518_bytes(stat_tx_packet_1024_1518_bytes_0),
.stat_tx_0_0_stat_tx_packet_128_255_bytes  (stat_tx_packet_128_255_bytes_0),
.stat_tx_0_0_stat_tx_packet_1519_1522_bytes(stat_tx_packet_1519_1522_bytes_0),
.stat_tx_0_0_stat_tx_packet_1523_1548_bytes(stat_tx_packet_1523_1548_bytes_0),
.stat_tx_0_0_stat_tx_packet_1549_2047_bytes(stat_tx_packet_1549_2047_bytes_0),
.stat_tx_0_0_stat_tx_packet_2048_4095_bytes(stat_tx_packet_2048_4095_bytes_0),
.stat_tx_0_0_stat_tx_packet_256_511_bytes  (stat_tx_packet_256_511_bytes_0),
.stat_tx_0_0_stat_tx_packet_4096_8191_bytes(stat_tx_packet_4096_8191_bytes_0),
.stat_tx_0_0_stat_tx_packet_512_1023_bytes (stat_tx_packet_512_1023_bytes_0),
.stat_tx_0_0_stat_tx_packet_64_bytes       (stat_tx_packet_64_bytes_0),
.stat_tx_0_0_stat_tx_packet_65_127_bytes   (stat_tx_packet_65_127_bytes_0),
.stat_tx_0_0_stat_tx_packet_8192_9215_bytes(stat_tx_packet_8192_9215_bytes_0),
.stat_tx_0_0_stat_tx_packet_large          (stat_tx_packet_large_0),
.stat_tx_0_0_stat_tx_packet_small          (stat_tx_packet_small_0),
.stat_tx_0_0_stat_tx_total_bytes           (stat_tx_total_bytes_0),
.stat_tx_0_0_stat_tx_total_good_bytes      (stat_tx_total_good_bytes_0),
.stat_tx_0_0_stat_tx_total_good_packets    (stat_tx_total_good_packets_0),
.stat_tx_0_0_stat_tx_total_packets         (stat_tx_total_packets_0),
.stat_tx_0_0_stat_tx_vlan                  (stat_tx_vlan_0),
.stat_tx_0_0_stat_tx_unicast               (stat_tx_unicast_0),
.stat_tx_0_0_stat_tx_multicast             (stat_tx_multicast_0),
.stat_tx_0_0_stat_tx_broadcast             (stat_tx_broadcast_0),
.stat_tx_0_0_stat_tx_local_fault(stat_tx_local_fault_0),
.tx_core_clk_0                  (tx_clk_out_0),
.tx_usrclk_out_0                (tx_clk_out_0),
.tx_reset_0                     (user_tx_reset_0),
.rx_serdes_reset_0_0            (user_rx_reset_0),
.apb3clk_quad                   (dclk),
.gtwiz_reset_clk_freerun_in_0_0 (dclk)
);
// 数据包生成监控模块(测试功能)
xxv_ethernet_0_pkt_gen_mon #(
.PKT_NUM(PKT_NUM)
) i_xxv_ethernet_0_pkt_gen_mon_0 (
.gen_clk(tx_clk_out_0),
.mon_clk(rx_core_clk_0),
.dclk(dclk),
.sys_reset(sys_reset),
.ub_ready(ub_ready),
.restart_tx_rx(restart_tx_rx_0 | user_tx_reset_0),
.send_continuous_pkts(send_continous_pkts_0),
//// User Interface signals
.completion_status(completion_status_0),
.stat_reg_compare(stat_reg_compare_0),
//// AXI4 Lite Interface Signals
.s_axi_aclk(s_axi_aclk_0),
.s_axi_aresetn(s_axi_aresetn_0),
.s_axi_awaddr(s_axi_awaddr_0),
.s_axi_awvalid(s_axi_awvalid_0),
.s_axi_awready(s_axi_awready_0),
.s_axi_wdata(s_axi_wdata_0),
.s_axi_wstrb(s_axi_wstrb_0),
.s_axi_wvalid(s_axi_wvalid_0),
.s_axi_wready(s_axi_wready_0),
.s_axi_bresp(s_axi_bresp_0),
.s_axi_bvalid(s_axi_bvalid_0),
.s_axi_bready(s_axi_bready_0),
.s_axi_araddr(s_axi_araddr_0),
.s_axi_arvalid(s_axi_arvalid_0),
.s_axi_arready(s_axi_arready_0),
.s_axi_rdata(s_axi_rdata_0),
.s_axi_rresp(s_axi_rresp_0),
.s_axi_rvalid(s_axi_rvalid_0),
.s_axi_rready(s_axi_rready_0),
.pm_tick(pm_tick_0),
//// RX Signals
.rx_reset(rx_reset_0),
.user_rx_reset(user_rx_reset_0),
.rx_axis_tvalid(rx_axis_tvalid_0),
.rx_axis_tdata (rx_axis_tdata_0),
.rx_axis_tlast (rx_axis_tlast_0),
.rx_axis_tkeep (rx_axis_tkeep_0),
.rx_axis_tuser (rx_axis_tuser_0),
.rx_preambleout(rx_preambleout_0),
//// RX Control Signals
//// RX Stats Signals
.stat_rx_block_lock(stat_rx_block_lock_0),
.stat_rx_framing_err_valid(stat_rx_framing_err_valid_0),
.stat_rx_framing_err(stat_rx_framing_err_0),
.stat_rx_hi_ber(stat_rx_hi_ber_0),
.stat_rx_valid_ctrl_code(stat_rx_valid_ctrl_code_0),
.stat_rx_bad_code(stat_rx_bad_code_0),
.stat_rx_total_packets(stat_rx_total_packets_0),
.stat_rx_total_good_packets(stat_rx_total_good_packets_0),
.stat_rx_total_bytes(stat_rx_total_bytes_0),
.stat_rx_total_good_bytes(stat_rx_total_good_bytes_0),
.stat_rx_packet_small(stat_rx_packet_small_0),
.stat_rx_jabber(stat_rx_jabber_0),
.stat_rx_packet_large(stat_rx_packet_large_0),
.stat_rx_oversize(stat_rx_oversize_0),
.stat_rx_undersize(stat_rx_undersize_0),
.stat_rx_toolong(stat_rx_toolong_0),
.stat_rx_fragment(stat_rx_fragment_0),
.stat_rx_packet_64_bytes(stat_rx_packet_64_bytes_0),
.stat_rx_packet_65_127_bytes(stat_rx_packet_65_127_bytes_0),
.stat_rx_packet_128_255_bytes(stat_rx_packet_128_255_bytes_0),
.stat_rx_packet_256_511_bytes(stat_rx_packet_256_511_bytes_0),
.stat_rx_packet_512_1023_bytes(stat_rx_packet_512_1023_bytes_0),
.stat_rx_packet_1024_1518_bytes(stat_rx_packet_1024_1518_bytes_0),
.stat_rx_packet_1519_1522_bytes(stat_rx_packet_1519_1522_bytes_0),
.stat_rx_packet_1523_1548_bytes(stat_rx_packet_1523_1548_bytes_0),
.stat_rx_bad_fcs(stat_rx_bad_fcs_0),
.stat_rx_packet_bad_fcs(stat_rx_packet_bad_fcs_0),
.stat_rx_stomped_fcs(stat_rx_stomped_fcs_0),
.stat_rx_packet_1549_2047_bytes(stat_rx_packet_1549_2047_bytes_0),
.stat_rx_packet_2048_4095_bytes(stat_rx_packet_2048_4095_bytes_0),
.stat_rx_packet_4096_8191_bytes(stat_rx_packet_4096_8191_bytes_0),
.stat_rx_packet_8192_9215_bytes(stat_rx_packet_8192_9215_bytes_0),
.stat_rx_unicast(stat_rx_unicast_0),
.stat_rx_multicast(stat_rx_multicast_0),
.stat_rx_broadcast(stat_rx_broadcast_0),
.stat_rx_vlan(stat_rx_vlan_0),
.stat_rx_inrangeerr(stat_rx_inrangeerr_0),
.stat_rx_bad_preamble(stat_rx_bad_preamble_0),
.stat_rx_bad_sfd(stat_rx_bad_sfd_0),
.stat_rx_got_signal_os(stat_rx_got_signal_os_0),
.stat_rx_test_pattern_mismatch(stat_rx_test_pattern_mismatch_0),
.stat_rx_truncated(stat_rx_truncated_0),
.stat_rx_local_fault(stat_rx_local_fault_0),
.stat_rx_remote_fault(stat_rx_remote_fault_0),
.stat_rx_internal_local_fault(stat_rx_internal_local_fault_0),
.stat_rx_received_local_fault(stat_rx_received_local_fault_0),
.tx_reset(tx_reset_0),
.user_tx_reset(user_tx_reset_0),
//// TX AXIS Signals
.tx_axis_tready(tx_axis_tready_0),
.tx_axis_tvalid(tx_axis_tvalid_0),
.tx_axis_tdata(tx_axis_tdata_0),
.tx_axis_tlast(tx_axis_tlast_0),
.tx_axis_tkeep(tx_axis_tkeep_0),
.tx_axis_tuser(tx_axis_tuser_0),
.tx_unfout(tx_unfout_0),
.tx_preamblein(tx_preamblein_0),
//// TX Control Signals
.ctl_tx_send_lfi(ctl_tx_send_lfi_0),
.ctl_tx_send_rfi(ctl_tx_send_rfi_0),
.ctl_tx_send_idle(ctl_tx_send_idle_0),
//// TX Stats Signals
.stat_tx_total_packets(stat_tx_total_packets_0),
.stat_tx_total_bytes(stat_tx_total_bytes_0),
.stat_tx_total_good_packets(stat_tx_total_good_packets_0),
.stat_tx_total_good_bytes(stat_tx_total_good_bytes_0),
.stat_tx_packet_64_bytes(stat_tx_packet_64_bytes_0),
.stat_tx_packet_65_127_bytes(stat_tx_packet_65_127_bytes_0),
.stat_tx_packet_128_255_bytes(stat_tx_packet_128_255_bytes_0),
.stat_tx_packet_256_511_bytes(stat_tx_packet_256_511_bytes_0),
.stat_tx_packet_512_1023_bytes(stat_tx_packet_512_1023_bytes_0),
.stat_tx_packet_1024_1518_bytes(stat_tx_packet_1024_1518_bytes_0),
.stat_tx_packet_1519_1522_bytes(stat_tx_packet_1519_1522_bytes_0),
.stat_tx_packet_1523_1548_bytes(stat_tx_packet_1523_1548_bytes_0),
.stat_tx_packet_small(stat_tx_packet_small_0),
.stat_tx_packet_large(stat_tx_packet_large_0),
.stat_tx_packet_1549_2047_bytes(stat_tx_packet_1549_2047_bytes_0),
.stat_tx_packet_2048_4095_bytes(stat_tx_packet_2048_4095_bytes_0),
.stat_tx_packet_4096_8191_bytes(stat_tx_packet_4096_8191_bytes_0),
.stat_tx_packet_8192_9215_bytes(stat_tx_packet_8192_9215_bytes_0),
.stat_tx_unicast(stat_tx_unicast_0),
.stat_tx_multicast(stat_tx_multicast_0),
.stat_tx_broadcast(stat_tx_broadcast_0),
.stat_tx_vlan(stat_tx_vlan_0),
.stat_tx_bad_fcs(stat_tx_bad_fcs_0),
.stat_tx_frame_error(stat_tx_frame_error_0),
.stat_tx_local_fault(stat_tx_local_fault_0),
.rx_gt_locked_led(rx_gt_locked_led_0),
.rx_block_lock_led(block_lock_led_0)
);
// 状态信号输出
assign completion_status = completion_status_0;
assign stat_reg_compare  = stat_reg_compare_0;
endmodulexxv_ethernet_0_pkt_gen_mon代码功能分析:
        核心架构
- 以太网数据包生成器/监视器(xxv_ethernet_0_pkt_gen_mon) 
- 包含AXI-Lite控制接口和AXI-Stream数据接口 
- 采用多级状态机(S0-S7)控制初始化和数据传输流程 
- case(state) S0: state <= ok_to_start ? S1 : S0; // 等待启动条件 S1: begin // 初始化定时器 common_timer <= cvt_us(32'd10_000); state <= S2; end S2: state <= (|common_timer) ? S2 : S3; // 等待10ms稳定 S3: begin // 触发系统复位 sys_reset <= 1'b1; state <= S4; end S4: state <= (|common_timer) ? S4 : S5; // 保持复位3周期 S5: begin // 检查链路状态 if(~&stat_rx_block_lock) completion_status <= NO_LANE_SYNC; state <= S6; end //后续状态处理数据包生成与校验 //我们如果要修改,可以从这里开始 
- 时钟域同步 :cdc_sync模块处理跨时钟域信号 
- xxv_ethernet_0_user_cdc_sync i_xxv_ethernet_0_core_cdc_sync_block_lock_syncer ( .clk(gen_clk), .signal_in(stat_rx_block_lock), .signal_out(stat_rx_block_lock_sync) ) 功能 :通过三级同步器处理跨时钟域信号(如stat_rx_block_lock) 实现 :使用异步寄存器链(ASYNC_REG)消除亚稳态 关键参数 :同步延迟3个时钟周期 
- PRBS生成 :用于产生伪随机测试数据流 
- // 在pkt_len_gen模块中 CRC <= {CRC, ^(CRC_POLYNOMIAL & {CRC,1'b0})} 算法 :基于多项式0x104C11DB7的32位CRC生成 数据流 : 通过LFSR生成伪随机序列 每个时钟周期生成64位数据 支持固定/随机长度(64-9000字节)
- CRC校验 :32位CRC计算模块(多项式0x104C11DB7) 
- 包长度生成 :支持固定/随机长度(64-9000字节) 
- 错误检测 :数据比对模块(cmpr)验证传输完整性 
主要功能模块
数据流流程
        
关键参数
目的MAC:FF:FF:FF:FF:FF:FF(广播地址) 源MAC:14:FE:B5:DD:9A:82 以太网类型:0x0600(Xerox NS IDP)
其中的状态机模块我添加了注释:
module xxv_ethernet_0_example_fsm_axis #( parameter VL_LANES_PER_GENERATOR = 1 // 每个生成器使用的通道数 ) ( input wire dclk, // 数字逻辑时钟(驱动状态机) input wire fsm_reset, // 状态机全局复位(高有效) input wire send_continuous_pkts,// 连续发送数据包使能 input wire [VL_LANES_PER_GENERATOR-1:0] stat_rx_block_lock, // 接收块锁定状态 input wire [VL_LANES_PER_GENERATOR-1:0] stat_rx_synced, // 通道同步状态 input wire stat_rx_aligned, // 多通道对齐状态 input wire stat_rx_status, // 接收状态有效指示 input wire tx_timeout, // 发送超时错误 input wire tx_done, // 发送完成标志 input wire ok_to_start, // 启动测试许可信号 input wire [47:0] rx_packet_count, // 接收数据包计数 input wire [63:0] rx_total_bytes, // 接收总字节数 input wire rx_errors, // 接收协议错误 input wire rx_data_errors, // 接收数据位错误 input wire [47:0] tx_sent_count,// 发送数据包计数 input wire [63:0] tx_total_bytes,// 发送总字节数 output reg sys_reset, // 系统复位输出 output reg pktgen_enable, // 数据包生成器使能 output reg [4:0] completion_status // 测试完成状态码 ); // 仿真加速模式配置 `ifdef SIM_SPEED_UP parameter [31:0] STARTUP_TIME = 32'd5000; // 仿真模式启动时间(5000时钟周期) `else parameter [31:0] STARTUP_TIME = 32'd50_000; // 硬件模式启动时间(50,000时钟周期) `endif // 状态机参数定义 parameter GENERATOR_COUNT = 1; // 数据生成器数量 parameter [4:0] NO_START = 5'h1F, // 未启动状态 TEST_START = 5'd0, // 测试启动 SUCCESSFUL_COMPLETION = 5'd1, // 成功完成 NO_BLOCK_LOCK = 5'd2, // 未获得块锁定 PARTIAL_BLOCK_LOCK = 5'd3,// 部分块锁定 INCONSISTENT_BLOCK_LOCK = 5'd4, // 块锁定不一致 NO_LANE_SYNC = 5'd5, // 通道未同步 PARTIAL_LANE_SYNC = 5'd6, // 部分通道同步 INCONSISTENT_LANE_SYNC = 5'd7, // 通道同步不一致 NO_ALIGN_OR_STATUS = 5'd8, // 未对齐或状态丢失 LOSS_OF_STATUS = 5'd9, // 状态丢失 TX_TIMED_OUT = 5'd10, // 发送超时 NO_DATA_SENT = 5'd11, // 未发送数据 SENT_COUNT_MISMATCH = 5'd12, // 发送计数不匹配 BYTE_COUNT_MISMATCH = 5'd13, // 字节数不匹配 LBUS_PROTOCOL = 5'd14, // 协议错误 BIT_ERRORS_IN_DATA = 5'd15; // 数据位错误 // 状态编码定义(格雷码编码) localparam [4:0] S0 = 5'b00000, // 初始化等待 S1 = 5'b00001, // 系统启动延时 S2 = 5'b00011, // 延时等待 S3 = 5'b00010, // 触发系统复位 S4 = 5'b00110, // 复位保持 S5 = 5'b00111, // 复位释放 S6 = 5'b00101, // 块锁定检测 S7 = 5'b00100, // 全通道块锁定检查 S8 = 5'b01100, // 通道同步检测 S9 = 5'b01101, // 全通道同步检查 S10 = 5'b01111, // 对齐状态检查 S11 = 5'b01110, // 稳定性等待 S12 = 5'b01010, // 状态监控阶段 S13 = 5'b01011, // 数据传输阶段 S14 = 5'b01001, // 测试完成检查 S15 = 5'b01000, // 最终状态 S16 = 5'b11000, // 复位恢复延时 S17 = 5'b11001; // 主等待周期 // 内部信号 reg [4:0] state ; // 当前状态寄存器 reg [31:0] common_timer; // 通用定时器 reg rx_packet_count_mismatch; // 数据包计数不匹配标志 reg rx_byte_count_mismatch; // 字节数不匹配标志 reg rx_non_zero_error_count; // 接收错误标志 reg tx_zero_sent; // 未发送数据标志 // 跨时钟域同步信号 wire send_continuous_pkts_sync; xxv_ethernet_0_user_cdc_sync i_xxv_ethernet_0_core_send_continuous_pkts_syncer ( .clk(dclk), // 目标时钟域 .signal_in(send_continuous_pkts), // 原始信号 .signal_out(send_continuous_pkts_sync) // 同步后信号 ); // 状态机逻辑 always @( posedge dclk ) begin if ( fsm_reset ) begin // 复位初始化 common_timer <= 0; state <= S0; sys_reset <= 1'b0; pktgen_enable <= 1'b0; completion_status <= NO_START; rx_packet_count_mismatch <= 0; rx_byte_count_mismatch <= 0; rx_non_zero_error_count <= 0; tx_zero_sent <= 0; end else begin // 主状态机逻辑 common_timer <= |common_timer ? common_timer - 1 : common_timer; rx_non_zero_error_count <= rx_data_errors; rx_packet_count_mismatch <= 0; rx_byte_count_mismatch <= 0; tx_zero_sent <= 0; // 检查所有生成器通道的数据一致性 for ( integer i = 0; i < GENERATOR_COUNT; i=i+1 ) begin if ( tx_total_bytes[(64 * i)+:64] != rx_total_bytes[(64 * i)+:64] ) rx_byte_count_mismatch <= 1'b1; if ( tx_sent_count[(48 * i)+:48] != rx_packet_count[(48 * i)+:48] ) rx_packet_count_mismatch <= 1'b1; if ( ~|tx_sent_count[(48 * i)+:48] ) tx_zero_sent <= 1'b1; end // 状态转移逻辑 case ( state ) // S0: 等待启动许可 S0: state <= ok_to_start ? S1 : S0; // S1: 启动延时配置 S1: begin `ifdef SIM_SPEED_UP common_timer <= cvt_us(32'd100); // 仿真模式100us延时 `else common_timer <= cvt_us(32'd10_000); // 硬件模式10ms延时 `endif completion_status <= TEST_START; state <= S2; end // S2: 延时等待 S2: state <= (|common_timer) ? S2 : S3; // S3: 触发系统复位 S3: begin common_timer <= 3; sys_reset <= 1'b1; state <= S4; end // S4: 保持复位状态 S4: state <= (|common_timer) ? S4 : S5; // S5: 释放复位 S5: begin common_timer <= cvt_us(5); // 5us复位恢复时间 sys_reset <= 1'b0; state <= S16; end // S16: 复位恢复延时 S16: state <= (|common_timer) ? S16 : S17; // S17: 主等待周期配置 S17: begin common_timer <= cvt_us(STARTUP_TIME); // 主等待周期 state <= S6; end // S6: 检查块锁定状态 S6: if(|common_timer) state <= |stat_rx_block_lock ? S7 : S6; else begin state <= S15; completion_status <= NO_BLOCK_LOCK; end // S7: 检查全通道块锁定 S7: if(|common_timer) state <= &stat_rx_block_lock ? S8 : S7; else begin state <= S15; completion_status <= PARTIAL_BLOCK_LOCK; end // S8: 检查通道同步状态 S8: if(|common_timer) begin if( ~&stat_rx_block_lock ) begin state <= S15; completion_status <= INCONSISTENT_BLOCK_LOCK; end else state <= |stat_rx_synced ? S9 : S8; end else begin state <= S15; completion_status <= NO_LANE_SYNC; end // S9: 检查全通道同步 S9: if(|common_timer) begin if( ~&stat_rx_block_lock ) begin state <= S15; completion_status <= INCONSISTENT_BLOCK_LOCK; end else state <= &stat_rx_synced ? S10 : S9; end else begin state <= S15; completion_status <= PARTIAL_LANE_SYNC; end // S10: 检查对齐和状态 S10: if(|common_timer) begin if( ~&stat_rx_block_lock ) begin state <= S15; completion_status <= INCONSISTENT_BLOCK_LOCK; end else if( ~&stat_rx_synced ) begin state <= S15; completion_status <= INCONSISTENT_LANE_SYNC; end else state <= (stat_rx_aligned && stat_rx_status) ? S11 : S10; end else begin state <= S15; completion_status <= NO_ALIGN_OR_STATUS; end // S11: 稳定性等待配置 S11: begin state <= S12; `ifdef SIM_SPEED_UP common_timer <= cvt_us(32'd50); // 仿真模式50us `else common_timer <= cvt_us(32'd1_000); // 硬件模式1ms `endif end // S12: 状态监控阶段 S12: if(|common_timer) begin if( ~&stat_rx_block_lock || ~&stat_rx_synced || ~stat_rx_aligned || ~stat_rx_status ) begin state <= S15; completion_status <= LOSS_OF_STATUS; end end else begin state <= S13; pktgen_enable <= 1'b1; // 启动数据包生成 `ifdef SIM_SPEED_UP common_timer <= cvt_us(32'd200); `else common_timer <= cvt_us(32'd10_000); `endif end // S13: 数据传输阶段 S13: if(|common_timer) begin if( ~&stat_rx_block_lock || ~&stat_rx_synced || ~stat_rx_aligned || ~stat_rx_status ) begin state <= S15; completion_status <= LOSS_OF_STATUS; end if(send_continuous_pkts_sync) begin `ifdef SIM_SPEED_UP common_timer <= cvt_us(32'd50); `else common_timer <= cvt_us(32'd1_000); `endif end end else state <= S14; // S14: 测试完成检查 S14: begin state <= S15; completion_status <= SUCCESSFUL_COMPLETION; if(tx_timeout || ~tx_done) completion_status <= TX_TIMED_OUT; else if(rx_packet_count_mismatch) completion_status <= SENT_COUNT_MISMATCH; else if(rx_byte_count_mismatch) completion_status <= BYTE_COUNT_MISMATCH; else if(rx_errors) completion_status <= LBUS_PROTOCOL; else if(rx_non_zero_error_count) completion_status <= BIT_ERRORS_IN_DATA; else if(tx_zero_sent) completion_status <= NO_DATA_SENT; end // S15: 最终状态 S15: state <= S15; endcase end end // 微秒转时钟周期函数 function [31:0] cvt_us( input [31:0] d ); // 假设时钟频率为156.25MHz(周期6.4ns) // 计算公式:d(us) * 156.25MHz = d * 156.25 ≈ (d * 300)/4 cvt_us = ( ( d * 300 ) + 3 ) / 4 ; endfunction endmodule
- 第一个方法是直接修改状态机,把生成代码和接收代码的部分删除,改成自己的代码。 
- 我倾向于:第二个方法是将本模块修改成【复位+初始化】功能的模块,AXI4 Stream接口的数据暴露给其他程序进行处理。 
- 原模块 - xxv_ethernet_0_pkt_gen_mon包含:
- AXI4 Lite接口(配置寄存器) 
- RX/TX LBUS数据通路( - rx_axis_*和- tx_axis_*信号)
- 状态机控制初始化流程( - stat_rx_block_lock同步、超时检测等)
- 数据包生成器( - xxv_ethernet_0_axis_traffic_gen_mon)
- CDC同步逻辑(跨时钟域信号处理) 
- 关键逻辑依赖 
- 初始化流程依赖 - stat_rx_block_lock信号同步
- AXI4 Lite接口通过 - xxv_ethernet_0_axi4_lite_user_if实现寄存器访问
- 数据通路逻辑通过 - xxv_ethernet_0_axis_traffic_gen_mon驱动TX/RX信号
最后AXI配置模块的内容如下:
`timescale 1fs/1fs
(* DowngradeIPIdentifiedWarnings="yes" *)
module xxv_ethernet_0_axi4_lite_user_if
   (
    // 输入信号
    input  wire            rx_gt_locked,          // GT收发器锁定状态
    input  wire            rx_gt_locked_led,      // GT锁定LED指示
    input  wire            stat_rx_aligned,       // RX对齐状态
    input  [4:0]           completion_status,     // 完成状态标志
    // 输出控制信号
    output reg             restart,               // 重启信号
    output reg             stat_reg_compare,      // 统计寄存器比较结果
    // AXI4-Lite时钟与复位
    input                  s_axi_aclk,            // AXI时钟
    input                  s_axi_sreset,          // AXI复位
    input                  s_axi_pm_tick,         // PM时钟节拍
    // AXI写地址通道
    output  [31:0]         s_axi_awaddr,
    output                 s_axi_awvalid,
    input                  s_axi_awready,
    // AXI写数据通道
    output  [31:0]         s_axi_wdata,
    output  [3:0]          s_axi_wstrb,
    output                 s_axi_wvalid,
    input                  s_axi_wready,
    // AXI写响应通道
    input   [1:0]          s_axi_bresp,
    input                  s_axi_bvalid,
    output                 s_axi_bready,
    // AXI读地址通道
    output  [31:0]         s_axi_araddr,
    output                 s_axi_arvalid,
    input                  s_axi_arready,
    // AXI读数据通道
    input   [31:0]         s_axi_rdata,
    input   [1:0]          s_axi_rresp,
    input                  s_axi_rvalid,
    output                 s_axi_rready
    );
    // 状态定义
    parameter STATE_AXI_IDLE            = 0;     // 空闲状态
    parameter STATE_GT_LOCKED           = 1;     // GT锁定状态
    parameter STATE_AXI_VERSION_READ    = 2;     // 版本寄存器读取
    parameter STATE_WAIT_RX_ALIGNED     = 3;     // 等待RX对齐
    parameter STATE_AXI_WR              = 4;     // AXI写操作
    parameter STATE_WAIT_SANITY_DONE    = 5;     // 等待自检完成
    parameter STATE_AXI_RD_WR           = 6;     // AXI读写操作
    parameter STATE_READ_STATS          = 7;     // 统计寄存器读取
    parameter STATE_READ_DONE           = 8;     // 读取完成
    parameter STATE_TEST_DONE           = 9;     // 测试完成
    parameter STATE_INVALID_AXI_RD_WR   = 10;    // 非法AXI操作
    parameter STATE_GT_RESET_ALL        = 11;    // 全局GT复位
    // 寄存器地址映射
    parameter  ADDR_GT_RESET_REG        = 32'h00000000; // GT复位寄存器
    parameter  ADDR_RESET_REG           = 32'h00000004; // 全局复位寄存器
    parameter  ADDR_MODE_REG            = 32'h00000008; // 模式配置寄存器
    parameter  ADDR_CONFIG_TX_REG1      = 32'h0000000C; // TX配置寄存器1
    parameter  ADDR_CONFIG_RX_REG1      = 32'h00000014; // RX配置寄存器1
    parameter  ADDR_CORE_VERSION_REG    = 32'h00000024; // 核心版本寄存器
    parameter  ADDR_TICK_REG            = 32'h00000020; // PM节拍寄存器
    // TX统计寄存器地址
    parameter  ADDR_STAT_TX_TOTAL_PACKETS_LSB   = 32'h00000700;
    parameter  ADDR_STAT_TX_TOTAL_PACKETS_MSB   = 32'h00000704;
    parameter  ADDR_STAT_TX_TOTAL_GOOD_PACKETS_LSB = 32'h00000708;
    parameter  ADDR_STAT_TX_TOTAL_GOOD_PACKETS_MSB = 32'h0000070C;
    parameter  ADDR_STAT_TX_TOTAL_BYTES_LSB     = 32'h00000710;
    parameter  ADDR_STAT_TX_TOTAL_BYTES_MSB     = 32'h00000714;
    parameter  ADDR_STAT_TX_TOTAL_GOOD_BYTES_LSB  = 32'h00000718;
    parameter  ADDR_STAT_TX_TOTAL_GOOD_BYTES_MSB  = 32'h0000071C;
    // RX统计寄存器地址
    parameter  ADDR_STAT_RX_TOTAL_PACKETS_LSB   = 32'h00000808;
    parameter  ADDR_STAT_RX_TOTAL_PACKETS_MSB   = 32'h0000080C;
    parameter  ADDR_STAT_RX_TOTAL_GOOD_PACKETS_LSB = 32'h00000810;
    parameter  ADDR_STAT_RX_TOTAL_GOOD_PACKETS_MSB = 32'h00000814;
    parameter  ADDR_STAT_RX_TOTAL_BYTES_LSB     = 32'h00000818;
    parameter  ADDR_STAT_RX_TOTAL_BYTES_MSB     = 32'h0000081C;
    parameter  ADDR_STAT_RX_TOTAL_GOOD_BYTES_LSB  = 32'h00000820;
    parameter  ADDR_STAT_RX_TOTAL_GOOD_BYTES_MSB  = 32'h00000824;
    // 状态寄存器
    reg  [3:0]     axi_user_prestate;    // 当前状态
    reg  [31:0]    axi_wr_data;          // AXI写数据
    reg  [31:0]    axi_read_data;        // AXI读数据
    wire [31:0]    axi_rd_data;          // 读数据总线
    reg  [31:0]    axi_wr_addr, axi_rd_addr; // 读写地址
    reg  [3:0]     axi_wr_strobe;        // 写选通信号
    reg            axi_wr_data_valid;    // 写数据有效
    reg            axi_wr_addr_valid;    // 写地址有效
    reg            axi_rd_addr_valid;    // 读地址有效
    reg            axi_rd_req;           // 读请求
    reg            axi_wr_req;           // 写请求
    wire           axi_wr_ack;           // 写响应
    wire           axi_rd_ack;           // 读响应
    wire           axi_wr_err;           // 写错误
    wire           axi_rd_err;           // 读错误
    reg  [7:0]     rd_wr_cntr;           // 读写计数器
    // 统计计数器
    reg  [47:0]    tx_total_pkt;         // TX总包数
    reg  [47:0]    tx_total_bytes;       // TX总字节数
    reg  [47:0]    tx_total_good_pkts;   // TX有效包数
    reg  [47:0]    tx_total_good_bytes;  // TX有效字节数
    reg  [47:0]    rx_total_pkt;         // RX总包数
    reg  [47:0]    rx_total_bytes;       // RX总字节数
    reg  [47:0]    rx_total_good_pkts;   // RX有效包数
    reg  [47:0]    rx_total_good_bytes;  // RX有效字节数
    // 控制信号
    reg            init_rx_aligned;      // RX对齐初始化
    reg            init_stat_read;       // 统计读初始化
    reg            init_sanity_done;     // 自检完成标志
    wire           stat_rx_aligned_sync; // 同步后的RX对齐信号
    wire           gt_locked_sync;       // 同步后的GT锁定信号
    reg            reset_all;            // 全局复位信号
    wire           posedge_rx_gt_locked_led; // GT锁定LED上升沿检测
    reg            rx_gt_locked_led_1d;  // GT锁定LED延迟寄存器
    // CDC同步模块实例化(用于跨时钟域信号同步)
    xxv_ethernet_0_cdc_sync_axi i_xxv_ethernet_0_cdc_sync_rx_gt_locked_led
    (
     .clk              (s_axi_aclk),
     .signal_in        (rx_gt_locked_led), 
     .signal_out       (rx_gt_locked_led_sync)
    );
    // GT锁定LED信号同步寄存器
    always @(posedge s_axi_aclk) begin
        if (s_axi_sreset)
            rx_gt_locked_led_1d <= 1'b0;
        else
            rx_gt_locked_led_1d <= rx_gt_locked_led_sync;
    end
    // 检测GT锁定LED的上升沿
    assign posedge_rx_gt_locked_led = rx_gt_locked_led_sync & ~rx_gt_locked_led_1d;
    // 主状态机逻辑
    always @(posedge s_axi_aclk) begin
        if (s_axi_sreset) begin
            // 复位所有寄存器和状态
            axi_user_prestate <= STATE_AXI_IDLE;
            // ...(其他复位逻辑,此处省略)
        end else begin
            case (axi_user_prestate)
                // 空闲状态:等待GT锁定
                STATE_AXI_IDLE: begin
                    if (gt_locked_sync)
                        axi_user_prestate <= STATE_GT_RESET_ALL;
                    else
                        axi_user_prestate <= STATE_AXI_IDLE;
                end
                // GT锁定状态:准备读取版本寄存器
                STATE_GT_LOCKED: begin
                    if (!gt_locked_sync)
                        axi_user_prestate <= STATE_AXI_IDLE;
                    else 
                        axi_user_prestate <= STATE_AXI_VERSION_READ;
                end
                // 读取核心版本寄存器
                STATE_AXI_VERSION_READ: begin
                    case (rd_wr_cntr)
                        0: begin
                            $display("开始读取核心版本寄存器...");
                            axi_rd_addr <= ADDR_CORE_VERSION_REG;
                            axi_rd_addr_valid <= 1'b1;
                            axi_rd_req <= 1'b1;
                        end
                        1: begin
                            $display("核心版本: %d.%0d", axi_read_data[7:0], axi_read_data[15:8]);
                            axi_user_prestate <= STATE_AXI_WR;
                        end
                    endcase
                end
                // AXI写操作状态(配置寄存器)
                STATE_AXI_WR: begin
                    case (rd_wr_cntr)
                        0: begin
                            // 配置模式寄存器(内部环回模式)
                            axi_wr_addr <= ADDR_MODE_REG;
                            axi_wr_data <= 32'hC000_0000;
                        end
                        1: begin
                            // 配置RX控制寄存器
                            axi_wr_addr <= ADDR_CONFIG_RX_REG1;
                            axi_wr_data <= 32'h0000_0033;
                        end
                        2: begin
                            // 配置TX控制寄存器
                            axi_wr_addr <= ADDR_CONFIG_TX_REG1;
                            axi_wr_data <= 32'h0000_3003;
                        end
                        3: begin
                            // GT复位操作
                            axi_wr_addr <= ADDR_GT_RESET_REG;
                            if (!gt_all_reset_once_only)
                                axi_wr_data <= 32'h0000_0001; // 复位
                            else
                                axi_wr_data <= 32'h0000_0000; // 释放复位
                        end
                        // ...(其他写操作步骤)
                    endcase
                end
                // 读取统计寄存器状态
                STATE_READ_STATS: begin
                    case (rd_wr_cntr)
                        0: begin
                            if (pm_tick_r)
                                axi_rd_addr <= ADDR_STAT_TX_TOTAL_PACKETS_LSB;
                            else
                                // 配置PM节拍寄存器
                                axi_wr_addr <= ADDR_TICK_REG;
                        end
                        // 依次读取所有统计寄存器(TX和RX)
                        1: axi_rd_addr <= ADDR_STAT_TX_TOTAL_PACKETS_LSB;
                        2: tx_total_pkt[31:0] <= axi_read_data;
                        // ...(其他统计寄存器读取步骤)
                        16: rx_total_good_bytes[31:0] <= axi_read_data;
                    endcase
                end
                // 读取完成状态:比较统计值
                STATE_READ_DONE: begin
                    $display("统计结果比较...");
                    if ((tx_total_pkt == rx_total_pkt) && 
                        (tx_total_good_pkts == rx_total_good_pkts) &&
                        (tx_total_bytes == rx_total_bytes) &&
                        (tx_total_good_bytes == rx_total_good_bytes))
                        stat_reg_compare <= 1'b1;
                    else 
                        stat_reg_compare <= 1'b0;
                    axi_user_prestate <= STATE_TEST_DONE;
                end
                // 全局GT复位状态
                STATE_GT_RESET_ALL: begin
                    if (!gt_all_reset_once_only)
                        axi_wr_data <= 32'h0000_0001; // 触发复位
                    else
                        axi_wr_data <= 32'h0000_0000; // 释放复位
                    // 等待GT锁定后进入下一状态
                    if (rx_gt_locked_led_sync)
                        axi_user_prestate <= STATE_GT_LOCKED;
                end
                // 错误处理状态
                STATE_INVALID_AXI_RD_WR: begin
                    $display("AXI读写错误,需要系统复位...");
                end
                // 默认状态处理
                default: axi_user_prestate <= STATE_AXI_IDLE;
            endcase
        end
    end
    // AXI读写接口实例化
    xxv_ethernet_0_axi4_lite_rd_wr_if i_xxv_ethernet_0_axi4_lite_rd_wr_if
    (
        // 连接AXI总线信号(此处省略具体连接)
    );
    // CDC同步模块实例化(用于GT锁定和RX对齐信号)
    xxv_ethernet_0_cdc_sync_axi i_xxv_ethernet_0_cdc_sync_gt_locked
    (
        .clk(s_axi_aclk),
        .signal_in(rx_gt_locked),
        .signal_out(gt_locked_sync)
    );
    xxv_ethernet_0_cdc_sync_axi i_xxv_ethernet_0_cdc_sync_stat_rx_aligned
    (
        .clk(s_axi_aclk),
        .signal_in(stat_rx_aligned),
        .signal_out(stat_rx_aligned_sync)
    );
    // PM节拍信号直接连接
    assign pm_tick_r = s_axi_pm_tick;
endmodule
// AXI4-Lite读写接口模块
module xxv_ethernet_0_axi4_lite_rd_wr_if
(
    // AXI时钟与复位
    input  wire                    axi_aclk,
    input  wire                    axi_sreset,
    // 用户侧读写请求
    input  wire                    usr_write_req,
    input  wire                    usr_read_req,
    // AXI写响应通道
    input  wire [1:0]              axi_bresp,
    input  wire                    axi_bvalid,
    output wire                    axi_bready,
    // AXI读数据通道
    input  wire [31:0]             axi_rdata,
    input  wire [1:0]              axi_rresp,
    input  wire                    axi_rvalid,
    output wire                    axi_rready,
    // AXI读地址通道
    output wire [31:0]             axi_araddr,
    output wire                    axi_arvalid,
    input  wire                    axi_arready,
    // AXI写地址通道
    output wire [31:0]             axi_awaddr,
    output wire                    axi_awvalid,
    input  wire                    axi_awready,
    // AXI写数据通道
    output wire [31:0]             axi_wdata,
    output wire [3:0]              axi_wstrb,
    output wire                    axi_wvalid,
    input  wire                    axi_wready,
    // 用户侧读数据返回
    output wire [31:0]             usr_rdata,
    // 用户侧读写响应
    output wire                    usr_wrack,
    output wire                    usr_rdack,
    output wire                    usr_wrerr,
    output wire                    usr_rderr
);
    // 状态定义
    parameter IDLE_STATE  = 0;
    parameter WRITE_STATE = 1;
    parameter READ_STATE  = 2;
    parameter ACK_STATE   = 3;
    // 状态寄存器
    reg [2:0] pstate;
    // 内部寄存器(用于缓存AXI信号)
    reg [31:0] axi_awaddr_r;
    reg        axi_awvalid_r;
    reg [31:0] axi_wdata_r;
    reg [3:0]  axi_wstrb_r;
    reg        axi_wvalid_r;
    reg [31:0] usr_araddr_r;
    reg        axi_arvalid_r;
    // 读写响应信号
    reg        usr_wrack_r;
    reg        usr_rdack_r;
    reg        usr_wrerr_r;
    reg        usr_rderr_r;
    // 输出信号连接
    assign axi_awaddr   = axi_awaddr_r;
    assign axi_awvalid  = axi_awvalid_r;
    assign axi_wdata    = axi_wdata_r;
    assign axi_wstrb    = axi_wstrb_r;
    assign axi_wvalid   = axi_wvalid_r;
    assign usr_rdata    = axi_rdata;
    assign axi_araddr   = usr_araddr_r;
    assign axi_arvalid  = axi_arvalid_r;
    assign usr_wrack    = usr_wrack_r;
    assign usr_rdack    = usr_rdack_r;
    assign usr_wrerr    = usr_wrerr_r;
    assign usr_rderr    = usr_rderr_r;
    // AXI写响应就绪信号生成
    always @(posedge axi_aclk) begin
        if (axi_sreset)
            axi_bready_r <= 1'b0;
        else
            axi_bready_r <= (~axi_bready_r) & axi_bvalid;
    end
    // AXI读数据就绪信号生成
    always @(posedge axi_aclk) begin
        if (axi_sreset)
            axi_rready_r <= 1'b0;
        else
            axi_rready_r <= (~axi_rready_r) & axi_rvalid;
    end
    // 状态机逻辑
    always @(posedge axi_aclk) begin
        if (axi_sreset) begin
            pstate <= IDLE_STATE;
            // 复位所有信号
        end else begin
            case (pstate)
                IDLE_STATE: begin
                    if (usr_read_req)
                        pstate <= READ_STATE;
                    else if (usr_write_req)
                        pstate <= WRITE_STATE;
                end
                WRITE_STATE: begin
                    if (axi_bvalid & axi_bready_r) begin
                        pstate <= ACK_STATE;
                        usr_wrack_r <= 1'b1;
                        usr_wrerr_r <= (axi_bresp == 2'b10); // 检测写错误
                    end
                end
                READ_STATE: begin
                    if (axi_rvalid & axi_rready_r) begin
                        pstate <= ACK_STATE;
                        usr_rdack_r <= 1'b1;
                        usr_rderr_r <= (axi_rresp == 2'b10); // 检测读错误
                    end
                end
                ACK_STATE: begin
                    pstate <= IDLE_STATE;
                    // 清除响应信号
                end
            endcase
        end
    end
endmodule
// 跨时钟域同步模块
module xxv_ethernet_0_cdc_sync_axi (
    input clk,
    input signal_in,
    output wire signal_out
);
    reg s_out_d2_cdc_to;
    reg s_out_d3;
    // 使用两级触发器同步信号
    always @(posedge clk) begin
        s_out_d2_cdc_to <= signal_in; // 第一级同步
        s_out_d3 <= s_out_d2_cdc_to;  // 第二级同步
    end
    assign signal_out = s_out_d3; // 输出同步后的信号
endmodule修改步骤
1、删除xxv_ethernet_0_axis_traffic_gen_mon、xxv_ethernet_0_traf_data_chk、xxv_ethernet_0_traf_chk1、xxv_ethernet_0_buf、xxv_ethernet_0_pkt_len_gen、xxv_ethernet_0_pktprbs_gen、xxv_ethernet_0_example_fsm_axis模块和调用。
2、简化状态机逻辑 目标 :初始化完成后直接进入空闲状态,不再触发数据传输。
// 原状态机(部分) case (state) S0: state <= S1; S1: state <= S2; ... S12: if (|common_timer) begin if (~&stat_rx_block_lock || ~&stat_rx_synced) begin state <= S15; // 错误处理 end end else begin state <= S13; // 原进入数据传输状态 end ... // 修改后(跳过数据传输状态) case (state) S0: state <= S1; S1: state <= S2; ... S12: if (|common_timer) begin if (~&stat_rx_block_lock || ~&stat_rx_synced) begin state <= S15; // 保留错误处理 end end else begin state <= S15; // 直接进入完成状态 completion_status <= SUCCESSFUL_COMPLETION; end ...
3、移除LBUS接口(由其他模块产生数据和接收数据)
//// TX LBUS Signals input wire tx_axis_tready, output wire tx_axis_tvalid, output wire [63:0] tx_axis_tdata, output wire tx_axis_tlast, output wire [7:0] tx_axis_tkeep, output wire tx_axis_tuser, input wire tx_unfout, output wire [55:0] tx_preamblein, //// RX LBUS Signals input wire rx_axis_tvalid, input wire [63:0] rx_axis_tdata, input wire rx_axis_tlast, input wire [7:0] rx_axis_tkeep, input wire rx_axis_tuser, input wire [55:0] rx_preambleout,
总的来说,我们需要关注的就是两件事,第一件事如何进行初始化,第二件事,如何使用AXI Stream实现我们需要的通信功能。
第一件事是要弄清楚该怎么调用xxv_ethernet_0_axi4_lite_user_if,如何产生各自复位逻辑。第二件事网上教程一大堆,就不用我赘述了。
rx_gt_locked信号是从外部输入的,

连接到了固定的~rx_reset上,

即rx_gt_locked输入的相当于是固定的1'b1即可。
rx_gt_locked_led信号来源于xxv_ethernet_0_axis_traffic_gen_mon模块,

其中tx_resetn信号来源于user_tx_reset | restart_tx_rx

user_tx_reset来源于外部输入

restart_tx_rx也来源于外部输入

stat_rx_aligned信号来源于

这个来自IP核,暂时不管
completion_status信号来自xxv_ethernet_0_example_fsm_axis状态机,
if (stat_rx_block_lock_sync) begin completion_status <= 5'h1F; // 成功完成 end else begin completion_status <= 5'h01; // 锁定失败

stat_reg_compare信号没啥用暂时不管,researt信号也不需要引出。
接下来只需要将AXI4 Lite接到IP的配置端口即可。







