当前位置: 首页 > news >正文

PCIe数据采集系统详解

PCIe数据采集系统详解

        在上篇文章中,废了老大劲儿我们写出了PCIe数据采集系统;其中各个模块各司其职,相互配合。完成了从数据采集到高速存储到DDR3的全过程。今天我们呢就来详细讲解他们之间的关系?以及各个模块的关键点?他们到底是怎么协同工作的?

总体模块图


各模块关键点

1. 在第一个时钟管理模块

有用到:差分时钟缓冲器,MMCM,全局时钟缓冲器

差分时钟缓冲器将PCIe的差分信号转换为单端信号展示,输出但不单列;

MMCM产生 pcie_user_clk_bufg 和 ddr3_user_clk_bufg ,同时产生 pll_locked锁存;

全局时钟缓冲器将pcie_user_clk_bufg 和 ddr3_user_clk_bufg原语应用于全局网络并输出相应信号;


2.在第二个系统控制模块

其主要目的是实现将异步复位信号同步,输出三个复位信号(系统,PCIe,DDR3;均使用了两个同步寄存器打拍同时配合PLL锁存信号)优势有以下:

  1. 消除亚稳态风险,提高系统稳定性。
  2. 简化时序分析,降低设计实现难度。
  3. 精确控制复位释放时序,确保多时钟域系统协调工作。
  4. 增强抗干扰能力,避免复位毛刺引发的问题。

在该模块体现为:确保 PCIe 模块在其专用时钟(pcie_user_clk)稳定后同步释放复位,避免 PCIe 链路初始化错误;控制 DDR3 控制器的复位时序,配合 DDR3 初始化校准流程(init_calib_complete信号),确保内存控制器正确启动。

并且该模块输入一些系统标志如:pcie_perst_n(PCIe物理层复位);init_calib_complete(DDR3初始化完成标志)等,以供相应模块使用,在本系统控制模块未处理,但是经由属于系统的控制部分所以列出。

接收系统状态和错误标志,通过 LED 实时显示


3.第三个PCIe模块

出现了user_clk(125M)user_clk(125M)user_clk(125M)use从r_clk(125M

必须与第一个时钟管理模块进行区分的是:pcie_user_clk(125M);

  • pcie_user_clk 是系统为 PCIe 模块提供的时钟源。
  • user_clk 是 PCIe IP 核向用户逻辑输出的同步时钟,确保数据在用户逻辑和 PCIe 之间正确传输。
  • user_clk的特殊作用PCIe IP 核内部会根据链路状态(如 Gen1/Gen2/Gen3)动态调整时钟相位和频率user_clk是 IP 核内部同步后的时钟,确保与 PCIe 事务时序(非事务层)严格对齐。

PCIe 端点模块的内部结构: PCIe 端点 IP 核通常包含:

  • 物理层(PHY):处理电气信号,使用参考时钟(如 100MHz 差分时钟)。
  • 链路层 / 事务层:处理 TLP(事务层包),使用系统提供的pcie_user_clk
  • 用户接口:提供与用户逻辑通信的时钟(即user_clk)。

在该模块中,输入的是差分信号与复位信号;主要输出用户时钟,MMIO接口与链路完成标志。

数据通道采用 128 位宽接口(PCIe Gen2 标准),带字节使能控制;

    // 参数定义:PCIe基地址寄存器(BAR)大小parameter BAR0_SIZE = 16'h1000;   // 4KBparameter BAR1_SIZE = 16'h4000;   // 16KB// 内部信号wire        pcie_clk;             // PCIe时钟wire        pcie_rst_n;           // PCIe复位 (低有效)wire [63:0] cfg_dw0, cfg_dw1, cfg_dw2, cfg_dw3; // 配置空间数据字
  1. BAR 寄存器:定义 PCIe 配置空间中内存映射区域的大小
  2. 配置空间:PCIe 设备通过 64 字节配置空间向主机暴露参数

PCIe 设备通过一个256 字节的配置空间向主机暴露自身参数,类似一个 "设备档案"。
主机通过读取这个空间了解设备信息(如厂商、功能、支持的 BAR 数量等),并配置设备行为。

  1. 前 64 字节(标准头):所有 PCIe 设备必须实现,包含通用信息

    • 设备标识:Vendor ID、Device ID、Class Code 等
    • 基地址寄存器 (BAR):定义设备可访问的内存 / IO 空间,存储主机分配给设备的基地址
    • 中断配置:IRQ 线、MSI/MSI-X 支持
  2. 后 192 字节:可选扩展区域,用于高级功能(如 PCIe 能力结构)

为什么需要 BAR?

  1. 地址解耦:设备无需预先知道主机分配的地址,通过 BAR 动态映射
  2. 资源管理:主机可根据系统情况灵活分配地址空间
  3. 多设备共存:多个 PCIe 设备可共享同一地址空间,通过 BAR 区分
  4. 安全隔离:主机可限制设备访问的地址范围,提高系统安全性

同时在MMIO控制器例化部分,实现了将 PCIe 事务转换为 FPGA 内部存储器读写操作(存储器映射)

PCIe 初始化流程详解

PCIe 设备初始化需要完成复杂的状态转换,代码中的状态机对应以下关键阶段:

  1. 复位阶段 (INIT_RESET)

    • 等待系统复位释放
    • 初始化内部计数器和标志位
  2. 链路训练阶段 (INIT_WAIT_LT)

    • 监测link_up信号,确认物理层连接建立
    • 超时处理防止链路训练失败导致的死锁
  3. 数据链路层初始化 (INIT_WAIT_DLL)

    • 等待数据链路层锁定(dll_up信号)
    • 建立可靠的数据传输通道
  4. 进入 L0 工作状态 (INIT_WAIT_L0)

    • 确认 LTSSM 状态机进入 L0 状态(正常工作状态)
    • 完成 PCIe 初始化的最后阶段
  5. 初始化完成 (INIT_COMPLETE)

    • 设置pcie_init_done标志,通知系统 PCIe 链路就绪
    • 持续监测链路状态,确保连接稳定

4.第四个MMIO控制器模块

输入了MMIO数据/地址,实现了 PCIe 总线与 FPGA 内部逻辑之间的 MMIO (存储器映射 I/O) 控制器,负责解析 PCIe 事务层包 (TLP) 并转换为内部寄存器访问。

在该模块编写中,就是使用了正常的always逻辑进行数据的解析打包与传输,没有任何技巧(简化了设计),同时定义了两个内存映射区域的基地址;提供了基础的 PCIe 到内部寄存器的映射功能,但缺少:

完整的TLP解析逻辑,BAR地址范围审查,背压机制(发送通道就绪时才能接收新数据),同时MMIO的错误清楚机制并没有撰写;后续可根据具体的项目要求改进。

示例代码如下:

module mmio_controller (input       clk,            // 用户时钟 (125MHz)input       reset_n,        // 复位信号// PCIe数据通道input [127:0] rx_data,      // 接收数据input [15:0]  rx_be,        // 接收字节使能input         rx_valid,     // 接收数据有效output        rx_ready,     // 接收准备好// 省略其他接口...// 新增错误处理接口input  [7:0]  error_flags,  // 外部错误标志输入output        mmio_clear_error, // 清除错误命令output [7:0]  active_errors // 当前活跃错误
);// 寄存器地址定义localparam ERROR_STATUS_REG = 32'h0000_0004; // 错误状态寄存器localparam ERROR_CLEAR_REG  = 32'h0000_0008; // 错误清除寄存器// 内部信号reg [31:0] mmio_addr_reg;reg        mmio_rd_reg, mmio_wr_reg;reg [127:0] mmio_wdata_reg;reg [7:0]   error_status;  // 错误状态寄存器reg         clear_error_cmd; // 清除错误命令暂存// 错误状态更新always @(posedge clk or negedge reset_n) beginif (!reset_n) beginerror_status <= 8'h00;end else begin// 错误标志可以被设置,但只能通过写清除寄存器清除error_status <= error_status | error_flags;// 处理错误清除命令if (mmio_wr_reg && (mmio_addr_reg == ERROR_CLEAR_REG)) beginerror_status <= error_status & (~mmio_wdata_reg[7:0]);endendend// 地址解码增强always @(posedge clk or negedge reset_n) beginif (!reset_n) beginmmio_addr_reg <= 0;mmio_rd_reg <= 0;mmio_wr_reg <= 0;mmio_wdata_reg <= 0;clear_error_cmd <= 0;end else if (rx_valid) begin// 解析PCIe接收数据中的MMIO地址和命令mmio_addr_reg <= rx_data[31:0];mmio_wdata_reg <= rx_data[127:32];mmio_rd_reg <= rx_data[128];mmio_wr_reg <= rx_data[129];// 检测错误清除命令clear_error_cmd <= mmio_wr_reg && (mmio_addr_reg == ERROR_CLEAR_REG);endend// 输出错误清除信号(脉冲有效)assign mmio_clear_error = clear_error_cmd;// 输出当前活跃错误assign active_errors = error_status;// 其他代码保持不变...
endmodule

5.第五个数据采集模块

输入了开始采集命令start_acq(ctrl);输出标志是采集完成信号;

其功能是双通道采集数据,然后打包数据块进行输出,以适应于高速传输模式;

前面单独出过一篇文章来讲解。


6.第六个DMA引擎控制模块

输入的是用户时钟(125M),数据输入,DMA启动信号;主要输出DDR3的写数据;其核心功能是实现高速数据传输,将采集模块的缓冲区数据搬移到 DDR3。

本模块的关键点主要是突发模式的配置与高速传输状态接收

前面单独出过一篇文章来讲解。


7. 第七个DDR3控制器模块

输入的是时钟ddr3_user_clk(200M),输出init_calib_complete信号,代表DDR3初始化校准完成就绪;

其功能是控制 DDR3 存储器的初始化、校准和数据读写。

实际上在代码编写时,主要是将Xilinx MIG IP 核在程序中例化,进而将DDR3物理层接口出现;

实现了用户接口和 MIG IP 核之间的信号转换


在第八个顶层模块中,实现了对前面模块的例化,同时创建了系统状态机用于协调管理各个模块,见上篇文章!!!

相关文章:

  • JAVA:线程调度器与时间分片的技术指南
  • 数据通信原理 光纤通信 期末速成
  • Android minSdk从21升级24后SO库异常
  • linux防火墙
  • 单序列双指针---初阶篇
  • 原生小程序+springboot+vue+协同过滤算法的音乐推荐系统(源码+论文+讲解+安装+部署+调试)
  • 文件上传Ⅲ
  • css:倒影倾斜效果
  • OpenAI与微软洽谈新融资及IPO,Instagram因TikTok流失四成用户
  • TRTC实时对话式AI解决方案,助力人机语音交互极致体验
  • 东方通2024年报分析:信创国产化龙头的蓬勃发展与未来可期
  • linux,我启动一个springboot项目, 用java -jar xxx.jar ,但是没多久这个java进程就会自动关掉
  • Python web 开发 Flask HTTP 服务
  • 在 Ubuntu 系统中,将 JAR 包安装为服务
  • 影楼精修-肤色统一算法解析
  • 【计算机网络】HTTP/1.0,HTTP/1.1,HTTP/2,HTTP/3汇总讲解,清晰表格整理面试重点对比
  • Python Socket编程:实现简单的客户端-服务器通信
  • 微服务初步学习
  • 使用seatunnel同步磐维数据库数据
  • 文章记单词 | 第82篇(六级)
  • 新城悦服务:独董许新民辞任,新任独董与另两人组成调查委员会将调查与关联方资金往来
  • 德州国资欲退出三东筑工,后者大股东系当地房企东海集团
  • 恒生银行回应裁员传闻:受影响的员工数目占银行核心业务员工总数约1%
  • 特朗普促卡塔尔说服伊朗放弃核计划,伊朗总统:你来吓唬我们?
  • 秦洪看盘|指标股发力,A股渐有突破态势
  • “中国神湖”加快放大资源规模!3亿美元换海外年产380万吨钾盐项目