PCIe数据采集系统
一、模块功能划分与职责
1. 时钟管理模块 (clock_manager
)
- 核心功能:
- 生成系统所需的多时钟信号(100MHz 系统时钟、125MHz PCIe 时钟、200MHz DDR3 时钟)。
- 关键接口:
- 输入:系统主时钟
sys_clk
、PCIe 差分参考时钟pcie_refclk_p/n
、 - 输出:各模块所需时钟(
pcie_user_clk
、ddr3_user_clk
)
- 输入:系统主时钟
代码展示
module clock_manager (
// 输入时钟
input wire sys_clk, // 系统主时钟 (100MHz)
input wire pcie_refclk_p, // PCIe参考时钟正极
input wire pcie_refclk_n, // PCIe参考时钟负极
// 输出时钟
output wire pcie_user_clk, // PCIe用户时钟 (125MHz)
output wire ddr3_user_clk, // DDR3用户时钟 (200MHz)
output wire pll_locked // PLL锁定标志
);
// 内部信号声明
wire pcie_refclk; // 单端PCIe参考时钟
wire pll_fb_out; // PLL反馈信号
wire pcie_user_clk_bufg; // PCIe用户时钟 (BUFGMUX输出)
wire ddr3_user_clk_bufg; // DDR3用户时钟 (BUFGMUX输出)
// =========================
// 差分时钟缓冲器 (IBUFDS_GTE2)
// =========================
IBUFDS_GTE2 #(
.REFCLK_EN_TX_PATH ("FALSE"),
.REFCLK_HROW_CK_SEL ("REFCLK_HROW_CK0"),
.REFCLK_ICNTL_RX ("00")
) ibufds_pcie_refclk (
.O (pcie_refclk),
.ODIV2 (),
.CEB (1'b0),
.I (pcie_refclk_p),
.IB (pcie_refclk_n)
);
// =========================
// 时钟生成器 (MMCM/PLL)
// =========================
MMCME4_BASE #(
.BANDWIDTH ("OPTIMIZED"),
.CLKOUT0_DIVIDE_F (8.000), // 125MHz (1000MHz/8)
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT0_PHASE (0.000),
.CLKOUT1_DIVIDE (5), // 200MHz (1000MHz/5)
.CLKOUT1_DUTY_CYCLE (0.500),
.CLKOUT1_PHASE (0.000),
.CLKIN1_PERIOD (10.000), // 100MHz输入周期
.CLKFBOUT_MULT_F (10.000), // VCO = 100MHz * 10 = 1000MHz
.DIVCLK_DIVIDE (1),
.REF_JITTER1 (0.010)
) mmcm_inst (
.CLKOUT0 (pcie_user_clk_bufg),
.CLKOUT1 (ddr3_user_clk_bufg),
.CLKFBOUT (pll_fb_out),
.LOCKED (pll_locked),
.CLKFBIN (pll_fb_out),
.CLKIN1 (sys_clk),
.PWRDWN (1'b0),
.RST (1'b0) // 固定为0(复位由system_control处理)
);
// =========================
// 全局时钟缓冲器 (BUFGMUX)
// =========================
BUFG pcie_user_clk_bufg_inst (
.I (pcie_user_clk_bufg),
.O (pcie_user_clk)
);
BUFG ddr3_user_clk_bufg_inst (
.I (ddr3_user_clk_bufg),
.O (ddr3_user_clk)
);
endmodule
关键问题
1.在上述代码中,提到了BUFG 原语。
BUFG pcie_user_clk_bufg_inst (.I (pcie_user_clk_bufg), .O (pcie_user_clk));
BUFG ddr3_user_clk_bufg_inst (.I (ddr3_user_clk_bufg), .O (ddr3_user_clk));
- BUFG (Buffer Global) 是 Xilinx FPGA 中的全局时钟缓冲器原语,用于将时钟信号驱动到 FPGA 的全局时钟网络(Global Clock Network)。
- 全局时钟网络的特点:
- 低延迟:专门设计的低阻抗布线,确保时钟信号同步到达所有触发器。
- 高驱动能力:能够驱动大量负载(如数千个触发器)而不失真。
- 平衡延迟:所有时钟路径延迟一致,避免时钟偏移(skew)问题。
为什么需要 BUFG?
- FPGA 内部有多种时钟网络:
- 全局时钟网络(由 BUFG 驱动):用于高频、关键路径的时钟(如系统主时钟、PCIe 时钟)。
- 区域时钟网络:用于局部模块的时钟,驱动能力和延迟次于全局网络。
- 如果不使用 BUFG,时钟信号可能通过普通布线到达触发器,导致:
- 时钟延迟增加,影响时序收敛。
- 不同触发器的时钟到达时间不一致(时钟偏移),引发亚稳态。
- 本例中,
pcie_user_clk_bufg
和ddr3_user_clk_bufg
是 MMCM 生成的时钟信号,但需通过 BUFG 驱动到全局网络,确保:- PCIe 模块的所有触发器使用同步的 125MHz 时钟。
- DDR3 控制器的所有操作在 200MHz 全局时钟下同步执行。
2. 系统控制模块 (system_control
)
- 核心功能:
- 复位同步:将 PCIe 物理层复位信号同步到不同时钟域,避免亚稳态。
- 状态监控:接收系统状态和错误标志,通过 LED 实时显示(低 4 位状态,最高位错误)。
- 关键接口:
- 输入:时钟信号、PCIe 复位信号、DDR3/PCIe 初始化完成标志、系统状态、错误标志。
- 输出:同步后的复位信号、调试 LED 信号。
代码展示:
module system_control (
// 时钟输入
input sys_clk, // 系统主时钟 (100MHz, sys_clk域)
input pcie_user_clk, // PCIe用户时钟 (125MHz, pcie_user_clk域)
input ddr3_user_clk, // DDR3用户时钟 (200MHz, ddr3_user_clk域)
// 复位输入
input pcie_perst_n, // PCIe物理层复位 (异步, 低有效)
input sys_rst_n, // 系统全局复位 (低有效, 异步)
input pll_locked, // PLL锁定标志 (来自clock_manager)
// 状态监控输入
input init_calib_complete, // DDR3初始化完成标志 (高有效)
input pcie_init_done, // PCIe初始化完成标志 (高有效)
input [3:0] system_state, // 系统状态机状态 (来自顶层)
input error_flag, // 系统错误标志 (来自顶层)
// 复位输出
output reg pcie_reset_n, // PCIe域同步复位 (低有效, pcie_user_clk域)
output reg system_reset_n, // 系统级同步复位 (低有效, sys_clk域)
output reg ddr3_reset_n, // DDR3域同步复位 (低有效, ddr3_user_clk域)
// 调试输出
output reg [7:0] debug_leds // 8位调试LED (低4位状态, 最高位错误标志)
);
// 复位计数器 (确保PLL锁定后延时释放复位)
reg [15:0] reset_counter;
// ======================
// 系统级复位同步 (sys_clk域)
// ======================
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n || !pll_locked) begin
reset_counter <= 16'h0000;
system_reset_n <= 1'b0;
end else begin
if (reset_counter < 16'hFFFF) begin
reset_counter <= reset_counter + 1'b1;
system_reset_n <= 1'b0; // 保持复位状态
end else begin
system_reset_n <= 1'b1; // 释放复位
end
end
end
// ======================
// PCIe复位同步 (pcie_user_clk域)
// ======================
reg [1:0] pcie_rst_sync;
always @(posedge pcie_user_clk or negedge sys_rst_n) begin
if (!sys_rst_n || !pll_locked) begin
pcie_rst_sync <= 2'b00;
pcie_reset_n <= 1'b0;
end else begin
pcie_rst_sync <= {pcie_rst_sync[0], system_reset_n}; // 同步system_reset_n
pcie_reset_n <= pcie_rst_sync[1];
end
end
// ======================
// DDR3复位同步 (ddr3_user_clk域)
// ======================
reg [1:0] ddr3_rst_sync;
always @(posedge ddr3_user_clk or negedge sys_rst_n) begin
if (!sys_rst_n || !pll_locked) begin
ddr3_rst_sync <= 2'b00;
ddr3_reset_n <= 1'b0;
end else begin
ddr3_rst_sync <= {ddr3_rst_sync[0], system_reset_n}; // 同步system_reset_n
ddr3_reset_n <= ddr3_rst_sync[1];
end
end
// ======================
// 调试LED控制逻辑
// ======================
always @(*) begin
debug_leds = {
error_flag, // 最高位: 错误标志
3'b000, // 中间3位: 保留
system_state[3:0] // 低4位: 系统状态编码
};
end
endmodule
关键问题
1. 复位优先级管理
- 最高优先级:全局复位
sys_rst_n
和 PLL 锁定状态pll_locked
。 - 次优先级:模块级复位(如 PCIe 物理层复位
pcie_perst_n
)。
2. 复位释放顺序
1. 全局复位 sys_rst_n 释放
2. PLL锁定 pll_locked 有效
3. 计数器延时后释放 system_reset_n
4. 同步释放 pcie_reset_n 和 ddr3_reset_n
3.调试 LED 输出
将系统状态(system_state
)和错误标志(error_flag
)编码到 LED 输出,便于硬件调试。
3. PCIe 端点模块 (pcie_endpoint
)
- 核心功能:
- 实现 PCIe Gen2 x4 物理层和链路层,处理差分信号收发。
- 解析 PCIe 事务层包(TLP),支持 MMIO 读写,与主机通信。
- 完成 PCIe 链路训练,输出初始化完成标志
pcie_init_done
。 - 该模块负责处理 PCIe 接口的数据传输和配置,以及与外部设备进行通信。
- 关键接口:
- 物理层:差分信号
pcie_rx_p/n
、pcie_tx_p/n
。 - 控制层:MMIO 读写信号、地址和数据总线。
- 物理层:差分信号
代码展示
// Artix-7 PCIe Gen2 x4端点模块
module pcie_endpoint_acx750 (
// 物理层接口
input pcie_refclk_p, // 参考时钟正极性
input pcie_refclk_n, // 参考时钟负极性
input [3:0] pcie_rx_p, // 接收通道正极性 (x4)
input [3:0] pcie_rx_n, // 接收通道负极性 (x4)
output [3:0] pcie_tx_p, // 发送通道正极性 (x4)
output [3:0] pcie_tx_n, // 发送通道负极性 (x4)
// 时钟与复位
output user_clk, // 用户时钟输出
input reset_n, // 系统复位 (低有效)
// 数据通道接口
output [127:0] rx_data, // 接收数据 (128位)
output [15:0] rx_be, // 接收字节使能 (16位,每字节1位)
output rx_valid, // 接收数据有效
input rx_ready, // 接收准备好
input [127:0] tx_data, // 发送数据 (128位)
input [15:0] tx_be, // 发送字节使能
input tx_valid, // 发送数据有效
output tx_ready, // 发送准备好
// MMIO接口
output mmio_rd, // MMIO读使能
output mmio_wr, // MMIO写使能
output [31:0] mmio_addr, // MMIO地址
output [127:0] mmio_wdata, // MMIO写数据
input [127:0] mmio_rdata, // MMIO读数据
output mmio_rvalid, // MMIO读数据有效
// 配置空间参数
input [15:0] device_id, // 设备ID
input [15:0] vendor_id, // 供应商ID
i